diff --git a/api/controllers/console/datasets/datasets.py b/api/controllers/console/datasets/datasets.py index c0422ef6f4..70b6e932e9 100644 --- a/api/controllers/console/datasets/datasets.py +++ b/api/controllers/console/datasets/datasets.py @@ -422,7 +422,6 @@ class DatasetApi(Resource): raise NotFound("Dataset not found.") payload = DatasetUpdatePayload.model_validate(console_ns.payload or {}) - payload_data = payload.model_dump(exclude_unset=True) current_user, current_tenant_id = current_account_with_tenant() # check embedding model setting if ( @@ -434,6 +433,7 @@ class DatasetApi(Resource): dataset.tenant_id, payload.embedding_model_provider, payload.embedding_model ) payload.is_multimodal = is_multimodal + payload_data = payload.model_dump(exclude_unset=True) # The role of the current user in the ta table must be admin, owner, editor, or dataset_operator DatasetPermissionService.check_permission( current_user, dataset, payload.permission, payload.partial_member_list diff --git a/api/core/rag/datasource/retrieval_service.py b/api/core/rag/datasource/retrieval_service.py index 7c5759e01b..e4ca25b46b 100644 --- a/api/core/rag/datasource/retrieval_service.py +++ b/api/core/rag/datasource/retrieval_service.py @@ -417,13 +417,6 @@ class RetrievalService: DocumentSegment.status == "completed", DocumentSegment.id == segment_id, ) - .options( - load_only( - DocumentSegment.id, - DocumentSegment.content, - DocumentSegment.answer, - ) - ) .first() ) diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts b/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts index fba7dad454..7b9e7953c6 100644 --- a/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts +++ b/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts @@ -1,13 +1,9 @@ import { useCallback, - useEffect, - useRef, - useState, } from 'react' import { TaskStatus } from '@/app/components/plugins/types' import type { PluginStatus } from '@/app/components/plugins/types' import { - useMutationClearAllTaskPlugin, useMutationClearTaskPlugin, usePluginTaskList, } from '@/service/use-plugins' @@ -18,7 +14,6 @@ export const usePluginTaskStatus = () => { handleRefetch, } = usePluginTaskList() const { mutateAsync } = useMutationClearTaskPlugin() - const { mutateAsync: mutateAsyncClearAll } = useMutationClearAllTaskPlugin() const allPlugins = pluginTasks.map(task => task.plugins.map((plugin) => { return { ...plugin, @@ -45,10 +40,6 @@ export const usePluginTaskStatus = () => { }) handleRefetch() }, [mutateAsync, handleRefetch]) - const handleClearAllErrorPlugin = useCallback(async () => { - await mutateAsyncClearAll() - handleRefetch() - }, [mutateAsyncClearAll, handleRefetch]) const totalPluginsLength = allPlugins.length const runningPluginsLength = runningPlugins.length const errorPluginsLength = errorPlugins.length @@ -60,26 +51,6 @@ export const usePluginTaskStatus = () => { const isSuccess = successPluginsLength === totalPluginsLength && totalPluginsLength > 0 const isFailed = runningPluginsLength === 0 && (errorPluginsLength + successPluginsLength) === totalPluginsLength && totalPluginsLength > 0 && errorPluginsLength > 0 - const [opacity, setOpacity] = useState(1) - const timerRef = useRef(null) - - useEffect(() => { - if (isSuccess) { - if (timerRef.current) { - clearTimeout(timerRef.current) - timerRef.current = null - } - if (opacity > 0) { - timerRef.current = setTimeout(() => { - setOpacity(v => v - 0.1) - }, 200) - } - } - - if (!isSuccess) - setOpacity(1) - }, [isSuccess, opacity]) - return { errorPlugins, successPlugins, @@ -94,7 +65,5 @@ export const usePluginTaskStatus = () => { isSuccess, isFailed, handleClearErrorPlugin, - handleClearAllErrorPlugin, - opacity, } } diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx index c0bf5824e7..4c37705287 100644 --- a/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx +++ b/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx @@ -1,4 +1,5 @@ import { + useCallback, useMemo, useState, } from 'react' @@ -6,6 +7,7 @@ import { RiCheckboxCircleFill, RiErrorWarningFill, RiInstallLine, + RiLoaderLine, } from '@remixicon/react' import { useTranslation } from 'react-i18next' import { usePluginTaskStatus } from './hooks' @@ -14,7 +16,6 @@ import { 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 CardIcon from '@/app/components/plugins/card/base/card-icon' @@ -22,6 +23,7 @@ import cn from '@/utils/classnames' import { useGetLanguage } from '@/context/i18n' import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' import DownloadingIcon from '@/app/components/header/plugins-nav/downloading-icon' +import Tooltip from '@/app/components/base/tooltip' const PluginTasks = () => { const { t } = useTranslation() @@ -29,6 +31,8 @@ const PluginTasks = () => { const [open, setOpen] = useState(false) const { errorPlugins, + successPlugins, + runningPlugins, runningPluginsLength, successPluginsLength, errorPluginsLength, @@ -39,33 +43,69 @@ const PluginTasks = () => { isSuccess, isFailed, handleClearErrorPlugin, - handleClearAllErrorPlugin, - opacity, } = usePluginTaskStatus() const { getIconUrl } = useGetIcon() + const handleClearAllWithModal = useCallback(async () => { + // Clear all completed plugins (success and error) but keep running ones + const completedPlugins = [...successPlugins, ...errorPlugins] + + // Clear all completed plugins individually + for (const plugin of completedPlugins) + await handleClearErrorPlugin(plugin.taskId, plugin.plugin_unique_identifier) + + // Only close modal if no plugins are still installing + if (runningPluginsLength === 0) + setOpen(false) + }, [successPlugins, errorPlugins, handleClearErrorPlugin, runningPluginsLength]) + + const handleClearErrorsWithModal = useCallback(async () => { + // Clear only error plugins, not all plugins + for (const plugin of errorPlugins) + await handleClearErrorPlugin(plugin.taskId, plugin.plugin_unique_identifier) + // Only close modal if no plugins are still installing + if (runningPluginsLength === 0) + setOpen(false) + }, [errorPlugins, handleClearErrorPlugin, runningPluginsLength]) + + const handleClearSingleWithModal = useCallback(async (taskId: string, pluginId: string) => { + await handleClearErrorPlugin(taskId, pluginId) + // Only close modal if no plugins are still installing + if (runningPluginsLength === 0) + setOpen(false) + }, [handleClearErrorPlugin, runningPluginsLength]) + const tip = useMemo(() => { - if (isInstalling) - return t('plugin.task.installing', { installingLength: runningPluginsLength }) - - if (isInstallingWithSuccess) - return t('plugin.task.installingWithSuccess', { installingLength: runningPluginsLength, successLength: successPluginsLength }) - if (isInstallingWithError) return t('plugin.task.installingWithError', { installingLength: runningPluginsLength, successLength: successPluginsLength, errorLength: errorPluginsLength }) - + if (isInstallingWithSuccess) + return t('plugin.task.installingWithSuccess', { installingLength: runningPluginsLength, successLength: successPluginsLength }) + if (isInstalling) + return t('plugin.task.installing') if (isFailed) - return t('plugin.task.installError', { errorLength: errorPluginsLength }) - }, [isInstalling, isInstallingWithSuccess, isInstallingWithError, isFailed, errorPluginsLength, runningPluginsLength, successPluginsLength, t]) + return t('plugin.task.installedError', { errorLength: errorPluginsLength }) + if (isSuccess) + return t('plugin.task.installSuccess', { successLength: successPluginsLength }) + return t('plugin.task.installed') + }, [ + errorPluginsLength, + isFailed, + isInstalling, + isInstallingWithError, + isInstallingWithSuccess, + isSuccess, + runningPluginsLength, + successPluginsLength, + t, + ]) - if (!totalPluginsLength) + // Show icon if there are any plugin tasks (completed, running, or failed) + // Only hide when there are absolutely no plugin tasks + if (totalPluginsLength === 0) return null return ( -
+
{ > { - if (isFailed) + if (isFailed || isInstalling || isInstallingWithSuccess || isInstallingWithError || isSuccess) setOpen(v => !v) }} > - +
@@ -124,7 +169,7 @@ const PluginTasks = () => { ) } { - isSuccess && ( + (isSuccess || (successPluginsLength > 0 && runningPluginsLength === 0 && errorPluginsLength === 0)) && ( ) } @@ -138,52 +183,129 @@ const PluginTasks = () => { -
-
- {t('plugin.task.installedError', { errorLength: errorPluginsLength })} - -
-
- { - errorPlugins.map(errorPlugin => ( -
-
- - -
-
-
- {errorPlugin.labels[language]} -
-
- {errorPlugin.message} -
-
- -
- )) - } -
+
+ + +
+
+
+ {runningPlugin.labels[language]} +
+
+ {t('plugin.task.installing')} +
+
+
+ ))} +
+ + )} + + {/* Success Plugins */} + {successPlugins.length > 0 && ( + <> +
+ {t('plugin.task.installed')} ({successPlugins.length}) + +
+
+ {successPlugins.map(successPlugin => ( +
+
+ + +
+
+
+ {successPlugin.labels[language]} +
+
+ {successPlugin.message || t('plugin.task.installed')} +
+
+
+ ))} +
+ + )} + + {/* Error Plugins */} + {errorPlugins.length > 0 && ( + <> +
+ {t('plugin.task.installError', { errorLength: errorPlugins.length })} + +
+
+ {errorPlugins.map(errorPlugin => ( +
+
+ + +
+
+
+ {errorPlugin.labels[language]} +
+
+ {errorPlugin.message} +
+
+ +
+ ))} +
+ + )}
diff --git a/web/i18n/de-DE/plugin.ts b/web/i18n/de-DE/plugin.ts index 18da902a6c..50d42b3671 100644 --- a/web/i18n/de-DE/plugin.ts +++ b/web/i18n/de-DE/plugin.ts @@ -230,6 +230,11 @@ const translation = { installing: 'Installation von {{installingLength}} Plugins, 0 erledigt.', installError: '{{errorLength}} Plugins konnten nicht installiert werden, klicken Sie hier, um sie anzusehen', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, allCategories: 'Alle Kategorien', install: '{{num}} Installationen', diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts index 62a5f35c0b..edd60d65fb 100644 --- a/web/i18n/en-US/plugin.ts +++ b/web/i18n/en-US/plugin.ts @@ -270,12 +270,17 @@ const translation = { partnerTip: 'Verified by a Dify partner', }, task: { - installing: 'Installing {{installingLength}} plugins, 0 done.', + installing: 'Installing plugins', installingWithSuccess: 'Installing {{installingLength}} plugins, {{successLength}} success.', installingWithError: 'Installing {{installingLength}} plugins, {{successLength}} success, {{errorLength}} failed', installError: '{{errorLength}} plugins failed to install, click to view', installedError: '{{errorLength}} plugins failed to install', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', clearAll: 'Clear all', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, requestAPlugin: 'Request a plugin', publishPlugins: 'Publish plugins', diff --git a/web/i18n/es-ES/plugin.ts b/web/i18n/es-ES/plugin.ts index 76e9f27c39..2452161791 100644 --- a/web/i18n/es-ES/plugin.ts +++ b/web/i18n/es-ES/plugin.ts @@ -230,6 +230,11 @@ const translation = { 'Los complementos {{errorLength}} no se pudieron instalar, haga clic para ver', installingWithError: 'Instalando plugins {{installingLength}}, {{successLength}} éxito, {{errorLength}} fallido', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, fromMarketplace: 'De Marketplace', endpointsEnabled: '{{num}} conjuntos de puntos finales habilitados', diff --git a/web/i18n/fa-IR/plugin.ts b/web/i18n/fa-IR/plugin.ts index 3b171a01ce..030ca0022d 100644 --- a/web/i18n/fa-IR/plugin.ts +++ b/web/i18n/fa-IR/plugin.ts @@ -223,6 +223,11 @@ const translation = { 'نصب پلاگین های {{installingLength}}، {{successLength}} موفقیت آمیز است.', installingWithError: 'نصب پلاگین های {{installingLength}}، {{successLength}} با موفقیت مواجه شد، {{errorLength}} ناموفق بود', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, searchTools: 'ابزارهای جستجو...', findMoreInMarketplace: 'اطلاعات بیشتر در Marketplace', diff --git a/web/i18n/fr-FR/plugin.ts b/web/i18n/fr-FR/plugin.ts index e1e7ae14ef..f19f08eb6f 100644 --- a/web/i18n/fr-FR/plugin.ts +++ b/web/i18n/fr-FR/plugin.ts @@ -228,6 +228,11 @@ const translation = { installedError: '{{errorLength}} les plugins n’ont pas pu être installés', clearAll: 'Effacer tout', installing: 'Installation des plugins {{installingLength}}, 0 fait.', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, search: 'Rechercher', installAction: 'Installer', diff --git a/web/i18n/hi-IN/plugin.ts b/web/i18n/hi-IN/plugin.ts index c8a5618e1f..8e65877b58 100644 --- a/web/i18n/hi-IN/plugin.ts +++ b/web/i18n/hi-IN/plugin.ts @@ -227,6 +227,11 @@ const translation = { '{{installingLength}} प्लगइन्स स्थापित कर रहे हैं, {{successLength}} सफल, {{errorLength}} विफल', installingWithSuccess: '{{installingLength}} प्लगइन्स स्थापित कर रहे हैं, {{successLength}} सफल।', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, installFrom: 'से इंस्टॉल करें', fromMarketplace: 'मार्केटप्लेस से', diff --git a/web/i18n/id-ID/plugin.ts b/web/i18n/id-ID/plugin.ts index bcf9d88b34..d849777121 100644 --- a/web/i18n/id-ID/plugin.ts +++ b/web/i18n/id-ID/plugin.ts @@ -261,6 +261,11 @@ const translation = { installingWithError: 'Memasang {{installingLength}} plugin, {{successLength}} berhasil, {{errorLength}} gagal', installError: 'Gagal menginstal plugin {{errorLength}}, klik untuk melihat', installedError: 'Gagal menginstal {{errorLength}} plugin', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, auth: { customCredentialUnavailable: 'Kredensial kustom saat ini tidak tersedia', diff --git a/web/i18n/it-IT/plugin.ts b/web/i18n/it-IT/plugin.ts index ac5deb2ed3..aaa5803550 100644 --- a/web/i18n/it-IT/plugin.ts +++ b/web/i18n/it-IT/plugin.ts @@ -208,6 +208,11 @@ const translation = { installedError: 'Impossibile installare i plugin di {{errorLength}}', installingWithError: 'Installazione dei plugin {{installingLength}}, {{successLength}} successo, {{errorLength}} fallito', installingWithSuccess: 'Installazione dei plugin {{installingLength}}, {{successLength}} successo.', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, searchInMarketplace: 'Cerca nel Marketplace', endpointsEnabled: '{{num}} set di endpoint abilitati', diff --git a/web/i18n/ja-JP/plugin.ts b/web/i18n/ja-JP/plugin.ts index 3b7985668a..d79baeb3b1 100644 --- a/web/i18n/ja-JP/plugin.ts +++ b/web/i18n/ja-JP/plugin.ts @@ -208,6 +208,11 @@ const translation = { installedError: '{{errorLength}} プラグインのインストールに失敗しました', installingWithError: '{{installingLength}}個のプラグインをインストール中、{{successLength}}件成功、{{errorLength}}件失敗', installing: '{{installingLength}}個のプラグインをインストール中、0 個完了。', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, from: 'インストール元', install: '{{num}} インストール', diff --git a/web/i18n/ko-KR/plugin.ts b/web/i18n/ko-KR/plugin.ts index 875776d700..710490b9fb 100644 --- a/web/i18n/ko-KR/plugin.ts +++ b/web/i18n/ko-KR/plugin.ts @@ -208,6 +208,11 @@ const translation = { installingWithError: '{{installingLength}} 플러그인 설치, {{successLength}} 성공, {{errorLength}} 실패', installError: '{{errorLength}} 플러그인 설치 실패, 보려면 클릭하십시오.', clearAll: '모두 지우기', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, installAction: '설치하다', searchTools: '검색 도구...', diff --git a/web/i18n/pl-PL/plugin.ts b/web/i18n/pl-PL/plugin.ts index dcd799ae2e..e4d9081217 100644 --- a/web/i18n/pl-PL/plugin.ts +++ b/web/i18n/pl-PL/plugin.ts @@ -208,6 +208,11 @@ const translation = { installingWithSuccess: 'Instalacja wtyczek {{installingLength}}, {{successLength}} powodzenie.', clearAll: 'Wyczyść wszystko', installingWithError: 'Instalacja wtyczek {{installingLength}}, {{successLength}} powodzenie, {{errorLength}} niepowodzenie', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, search: 'Szukać', installFrom: 'ZAINSTALUJ Z', diff --git a/web/i18n/pt-BR/plugin.ts b/web/i18n/pt-BR/plugin.ts index 0fc620579c..b24d37ee63 100644 --- a/web/i18n/pt-BR/plugin.ts +++ b/web/i18n/pt-BR/plugin.ts @@ -208,6 +208,11 @@ const translation = { installingWithError: 'Instalando plug-ins {{installingLength}}, {{successLength}} sucesso, {{errorLength}} falhou', installing: 'Instalando plugins {{installingLength}}, 0 feito.', clearAll: 'Apagar tudo', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, installAction: 'Instalar', endpointsEnabled: '{{num}} conjuntos de endpoints habilitados', diff --git a/web/i18n/ro-RO/plugin.ts b/web/i18n/ro-RO/plugin.ts index 547dbe0942..e3db03a057 100644 --- a/web/i18n/ro-RO/plugin.ts +++ b/web/i18n/ro-RO/plugin.ts @@ -208,6 +208,11 @@ const translation = { installingWithError: 'Instalarea pluginurilor {{installingLength}}, {{successLength}} succes, {{errorLength}} eșuat', installingWithSuccess: 'Instalarea pluginurilor {{installingLength}}, {{successLength}} succes.', installing: 'Instalarea pluginurilor {{installingLength}}, 0 terminat.', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, fromMarketplace: 'Din Marketplace', from: 'Din', diff --git a/web/i18n/ru-RU/plugin.ts b/web/i18n/ru-RU/plugin.ts index 55061a34f5..23214fb195 100644 --- a/web/i18n/ru-RU/plugin.ts +++ b/web/i18n/ru-RU/plugin.ts @@ -208,6 +208,11 @@ const translation = { installingWithSuccess: 'Установка плагинов {{installingLength}}, {{successLength}} успех.', installedError: 'плагины {{errorLength}} не удалось установить', installError: 'Плагины {{errorLength}} не удалось установить, нажмите для просмотра', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, install: '{{num}} установок', searchCategories: 'Поиск категорий', diff --git a/web/i18n/sl-SI/plugin.ts b/web/i18n/sl-SI/plugin.ts index ca8594df2f..ea99b649bf 100644 --- a/web/i18n/sl-SI/plugin.ts +++ b/web/i18n/sl-SI/plugin.ts @@ -211,6 +211,11 @@ const translation = { installingWithSuccess: 'Namestitev {{installingLength}} dodatkov, {{successLength}} uspešnih.', installedError: '{{errorLength}} vtičnikov ni uspelo namestiti', installingWithError: 'Namestitev {{installingLength}} vtičnikov, {{successLength}} uspešnih, {{errorLength}} neuspešnih', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, endpointsEnabled: '{{num}} nizov končnih točk omogočenih', search: 'Iskanje', diff --git a/web/i18n/th-TH/plugin.ts b/web/i18n/th-TH/plugin.ts index 64705b7e04..8f59a5bded 100644 --- a/web/i18n/th-TH/plugin.ts +++ b/web/i18n/th-TH/plugin.ts @@ -208,6 +208,11 @@ const translation = { installedError: '{{errorLength}} ปลั๊กอินติดตั้งไม่สําเร็จ', clearAll: 'ล้างทั้งหมด', installError: '{{errorLength}} ปลั๊กอินติดตั้งไม่สําเร็จ คลิกเพื่อดู', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, searchCategories: 'หมวดหมู่การค้นหา', searchInMarketplace: 'ค้นหาใน Marketplace', diff --git a/web/i18n/tr-TR/plugin.ts b/web/i18n/tr-TR/plugin.ts index 8aa60e0e7b..bdc10bc753 100644 --- a/web/i18n/tr-TR/plugin.ts +++ b/web/i18n/tr-TR/plugin.ts @@ -208,6 +208,11 @@ const translation = { installingWithSuccess: '{{installingLength}} eklentileri yükleniyor, {{successLength}} başarılı.', installError: '{{errorLength}} eklentileri yüklenemedi, görüntülemek için tıklayın', installingWithError: '{{installingLength}} eklentileri yükleniyor, {{successLength}} başarılı, {{errorLength}} başarısız oldu', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, allCategories: 'Tüm Kategoriler', installAction: 'Yüklemek', diff --git a/web/i18n/uk-UA/plugin.ts b/web/i18n/uk-UA/plugin.ts index 2d2683026d..948edc0c82 100644 --- a/web/i18n/uk-UA/plugin.ts +++ b/web/i18n/uk-UA/plugin.ts @@ -208,6 +208,11 @@ const translation = { installError: 'Плагіни {{errorLength}} не вдалося встановити, натисніть, щоб переглянути', installing: 'Встановлення плагінів {{installingLength}}, 0 виконано.', installingWithSuccess: 'Встановлення плагінів {{installingLength}}, успіх {{successLength}}.', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, from: 'Від', searchInMarketplace: 'Пошук у Marketplace', diff --git a/web/i18n/vi-VN/plugin.ts b/web/i18n/vi-VN/plugin.ts index 6eb4e9fbe5..127738f849 100644 --- a/web/i18n/vi-VN/plugin.ts +++ b/web/i18n/vi-VN/plugin.ts @@ -208,6 +208,11 @@ const translation = { installError: '{{errorLength}} plugin không cài đặt được, nhấp để xem', installedError: '{{errorLength}} plugin không cài đặt được', clearAll: 'Xóa tất cả', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, from: 'Từ', installAction: 'Cài đặt', diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts index d648bccb85..20b238f178 100644 --- a/web/i18n/zh-Hans/plugin.ts +++ b/web/i18n/zh-Hans/plugin.ts @@ -270,12 +270,17 @@ const translation = { partnerTip: '此插件由 Dify 合作伙伴认证', }, task: { - installing: '{{installingLength}} 个插件安装中,0 已完成', + installing: '正在安装插件', installingWithSuccess: '{{installingLength}} 个插件安装中,{{successLength}} 安装成功', installingWithError: '{{installingLength}} 个插件安装中,{{successLength}} 安装成功,{{errorLength}} 安装失败', installError: '{{errorLength}} 个插件安装失败,点击查看', installedError: '{{errorLength}} 个插件安装失败', + installSuccess: '{{successLength}} 个插件安装成功', + installed: '已安装', clearAll: '清除所有', + runningPlugins: '正在安装的插件', + successPlugins: '安装成功的插件', + errorPlugins: '安装失败的插件', }, requestAPlugin: '申请插件', publishPlugins: '发布插件', diff --git a/web/i18n/zh-Hant/plugin.ts b/web/i18n/zh-Hant/plugin.ts index 5ec8936257..d2809f9971 100644 --- a/web/i18n/zh-Hant/plugin.ts +++ b/web/i18n/zh-Hant/plugin.ts @@ -208,6 +208,11 @@ const translation = { installingWithSuccess: '安裝 {{installingLength}} 個插件,{{successLength}} 成功。', clearAll: '全部清除', installing: '安裝 {{installingLength}} 個插件,0 個完成。', + installSuccess: '{{successLength}} plugins installed successfully', + installed: 'Installed', + runningPlugins: 'Installing Plugins', + successPlugins: 'Successfully Installed Plugins', + errorPlugins: 'Failed to Install Plugins', }, requestAPlugin: '申请插件', publishPlugins: '發佈插件', diff --git a/web/jest.setup.ts b/web/jest.setup.ts index 383ba412a2..006b28322e 100644 --- a/web/jest.setup.ts +++ b/web/jest.setup.ts @@ -2,16 +2,22 @@ import '@testing-library/jest-dom' import { cleanup } from '@testing-library/react' // Fix for @headlessui/react compatibility with happy-dom -// headlessui tries to set focus property which is read-only in happy-dom +// headlessui tries to override focus properties which may be read-only in happy-dom if (typeof window !== 'undefined') { - // Ensure window.focus is writable for headlessui - if (!Object.getOwnPropertyDescriptor(window, 'focus')?.writable) { - Object.defineProperty(window, 'focus', { - value: jest.fn(), - writable: true, - configurable: true, - }) + const ensureWritable = (target: object, prop: string) => { + const descriptor = Object.getOwnPropertyDescriptor(target, prop) + if (descriptor && !descriptor.writable) { + const original = descriptor.value ?? descriptor.get?.call(target) + Object.defineProperty(target, prop, { + value: typeof original === 'function' ? original : jest.fn(), + writable: true, + configurable: true, + }) + } } + + ensureWritable(window, 'focus') + ensureWritable(HTMLElement.prototype, 'focus') } afterEach(() => { diff --git a/web/service/use-plugins.ts b/web/service/use-plugins.ts index b5b8779a82..639d889fa0 100644 --- a/web/service/use-plugins.ts +++ b/web/service/use-plugins.ts @@ -634,7 +634,8 @@ export const usePluginTaskList = (category?: PluginCategoryEnum | string) => { export const useMutationClearTaskPlugin = () => { return useMutation({ mutationFn: ({ taskId, pluginId }: { taskId: string; pluginId: string }) => { - return post<{ success: boolean }>(`/workspaces/current/plugin/tasks/${taskId}/delete/${pluginId}`) + const encodedPluginId = encodeURIComponent(pluginId) + return post<{ success: boolean }>(`/workspaces/current/plugin/tasks/${taskId}/delete/${encodedPluginId}`) }, }) }