mirror of
https://github.com/langgenius/dify.git
synced 2024-11-16 11:42:29 +08:00
Merge branch 'feat/plugins' of github.com:langgenius/dify into feat/plugins
This commit is contained in:
commit
20357beda4
|
@ -9,7 +9,7 @@ import { pluginManifestToCardPluginProps } from '../../utils'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { installPackageFromGitHub, uninstallPlugin } from '@/service/plugins'
|
import { installPackageFromGitHub, uninstallPlugin } from '@/service/plugins'
|
||||||
import { RiLoader2Line } from '@remixicon/react'
|
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 checkTaskStatus from '../../base/check-task-status'
|
||||||
import { parseGitHubUrl } from '../../utils'
|
import { parseGitHubUrl } from '../../utils'
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { RiLoader2Line } from '@remixicon/react'
|
||||||
import Badge, { BadgeState } from '@/app/components/base/badge/index'
|
import Badge, { BadgeState } from '@/app/components/base/badge/index'
|
||||||
import { useInstallPackageFromLocal } from '@/service/use-plugins'
|
import { useInstallPackageFromLocal } from '@/service/use-plugins'
|
||||||
import checkTaskStatus from '../../base/check-task-status'
|
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'
|
const i18nPrefix = 'plugin.installModal'
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import { Github } from '@/app/components/base/icons/src/public/common'
|
||||||
import { uninstallPlugin } from '@/service/plugins'
|
import { uninstallPlugin } from '@/service/plugins'
|
||||||
import { useGetLanguage } from '@/context/i18n'
|
import { useGetLanguage } from '@/context/i18n'
|
||||||
import { useModalContext } from '@/context/modal-context'
|
import { useModalContext } from '@/context/modal-context'
|
||||||
|
import UpdateFromMarketplace from '@/app/components/plugins/update-plugin/from-market-place'
|
||||||
import { API_PREFIX, MARKETPLACE_URL_PREFIX } from '@/config'
|
import { API_PREFIX, MARKETPLACE_URL_PREFIX } from '@/config'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
|
@ -55,17 +55,35 @@ const DetailHeader = ({
|
||||||
source,
|
source,
|
||||||
tenant_id,
|
tenant_id,
|
||||||
version,
|
version,
|
||||||
|
latest_unique_identifier,
|
||||||
latest_version,
|
latest_version,
|
||||||
meta,
|
meta,
|
||||||
} = detail
|
} = detail
|
||||||
const { author, name, label, description, icon, verified } = detail.declaration
|
const { author, name, label, description, icon, verified } = detail.declaration
|
||||||
const isFromGitHub = source === PluginSource.github
|
const isFromGitHub = source === PluginSource.github
|
||||||
|
const isFromMarketplace = source === PluginSource.marketplace
|
||||||
|
|
||||||
const hasNewVersion = useMemo(() => {
|
const hasNewVersion = useMemo(() => {
|
||||||
return source === PluginSource.github && latest_version !== version
|
if (isFromGitHub)
|
||||||
}, [source, latest_version, version])
|
return latest_version !== version
|
||||||
|
|
||||||
|
if (isFromMarketplace)
|
||||||
|
return !!latest_version && latest_version !== version
|
||||||
|
|
||||||
|
return false
|
||||||
|
}, [isFromGitHub, isFromMarketplace, latest_version, version])
|
||||||
|
|
||||||
|
const [isShowUpdateModal, {
|
||||||
|
setTrue: showUpdateModal,
|
||||||
|
setFalse: hideUpdateModal,
|
||||||
|
}] = useBoolean(false)
|
||||||
|
|
||||||
const handleUpdate = async () => {
|
const handleUpdate = async () => {
|
||||||
|
if (isFromMarketplace) {
|
||||||
|
showUpdateModal()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const fetchedReleases = await fetchReleases(author, name)
|
const fetchedReleases = await fetchReleases(author, name)
|
||||||
if (fetchedReleases.length === 0)
|
if (fetchedReleases.length === 0)
|
||||||
|
@ -106,6 +124,11 @@ const DetailHeader = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleUpdatedFromMarketplace = () => {
|
||||||
|
onUpdate()
|
||||||
|
hideUpdateModal()
|
||||||
|
}
|
||||||
|
|
||||||
const [isShowPluginInfo, {
|
const [isShowPluginInfo, {
|
||||||
setTrue: showPluginInfo,
|
setTrue: showPluginInfo,
|
||||||
setFalse: hidePluginInfo,
|
setFalse: hidePluginInfo,
|
||||||
|
@ -222,6 +245,24 @@ const DetailHeader = ({
|
||||||
isDisabled={deleting}
|
isDisabled={deleting}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{
|
||||||
|
isShowUpdateModal && (
|
||||||
|
<UpdateFromMarketplace
|
||||||
|
payload={{
|
||||||
|
originalPackageInfo: {
|
||||||
|
id: detail.plugin_unique_identifier,
|
||||||
|
payload: detail.declaration,
|
||||||
|
},
|
||||||
|
targetPackageInfo: {
|
||||||
|
id: latest_unique_identifier,
|
||||||
|
version: latest_version,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onCancel={hideUpdateModal}
|
||||||
|
onSave={handleUpdatedFromMarketplace}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ import InstallPluginDropdown from './install-plugin-dropdown'
|
||||||
import { useUploader } from './use-uploader'
|
import { useUploader } from './use-uploader'
|
||||||
import usePermission from './use-permission'
|
import usePermission from './use-permission'
|
||||||
import DebugInfo from './debug-info'
|
import DebugInfo from './debug-info'
|
||||||
import { usePluginTasksStore } from './store'
|
import { usePluginTasksStore } from './plugin-tasks/store'
|
||||||
import InstallInfo from './install-info'
|
import PluginTasks from './plugin-tasks'
|
||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
import TabSlider from '@/app/components/base/tab-slider'
|
import TabSlider from '@/app/components/base/tab-slider'
|
||||||
import Tooltip from '@/app/components/base/tooltip'
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
|
@ -102,8 +102,6 @@ const PluginPage = ({
|
||||||
const options = usePluginPageContext(v => v.options)
|
const options = usePluginPageContext(v => v.options)
|
||||||
const [activeTab, setActiveTab] = usePluginPageContext(v => [v.activeTab, v.setActiveTab])
|
const [activeTab, setActiveTab] = usePluginPageContext(v => [v.activeTab, v.setActiveTab])
|
||||||
const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures)
|
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({
|
const uploaderProps = useUploader({
|
||||||
onFileChange: setCurrentFile,
|
onFileChange: setCurrentFile,
|
||||||
|
@ -142,7 +140,7 @@ const PluginPage = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-shrink-0 items-center gap-1'>
|
<div className='flex flex-shrink-0 items-center gap-1'>
|
||||||
<InstallInfo />
|
<PluginTasks />
|
||||||
{canManagement && (
|
{canManagement && (
|
||||||
<InstallPluginDropdown
|
<InstallPluginDropdown
|
||||||
onSwitchToMarketplaceTab={() => setActiveTab('discover')}
|
onSwitchToMarketplaceTab={() => setActiveTab('discover')}
|
||||||
|
|
|
@ -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 (
|
|
||||||
<div className='flex items-center'>
|
|
||||||
<PortalToFollowElem
|
|
||||||
open={open}
|
|
||||||
onOpenChange={setOpen}
|
|
||||||
placement='bottom-start'
|
|
||||||
offset={{
|
|
||||||
mainAxis: 4,
|
|
||||||
crossAxis: 79,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
|
|
||||||
<Tooltip popupContent='Installing 1/3 plugins...'>
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
'relative flex items-center justify-center w-8 h-8 rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg shadow-xs hover:bg-components-button-secondary-bg-hover',
|
|
||||||
statusError && 'border-components-button-destructive-secondary-border-hover bg-state-destructive-hover hover:bg-state-destructive-hover-alt',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<RiInstallLine
|
|
||||||
className={cn(
|
|
||||||
'w-4 h-4 text-components-button-secondary-text',
|
|
||||||
statusError && 'text-components-button-destructive-secondary-text',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<div className='absolute -right-1 -top-1'>
|
|
||||||
{/* <ProgressCircle
|
|
||||||
percentage={33}
|
|
||||||
circleFillColor='fill-components-progress-brand-bg'
|
|
||||||
sectorFillColor='fill-components-progress-error-bg'
|
|
||||||
circleStrokeColor='stroke-components-progress-error-bg'
|
|
||||||
/> */}
|
|
||||||
<RiCheckboxCircleFill className='w-3.5 h-3.5 text-text-success' />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
</PortalToFollowElemTrigger>
|
|
||||||
<PortalToFollowElemContent className='z-10'>
|
|
||||||
<div className='p-1 pb-2 w-[320px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'>
|
|
||||||
<div className='flex items-center px-2 pt-1 h-7 system-sm-semibold-uppercase'>3 plugins failed to install</div>
|
|
||||||
<div className='flex items-center p-1 pl-2 h-8 rounded-lg hover:bg-state-base-hover'>
|
|
||||||
<div className='relative flex items-center justify-center mr-2 w-6 h-6 rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge'>
|
|
||||||
<RiErrorWarningFill className='absolute -right-0.5 -bottom-0.5 w-3 h-3 text-text-destructive' />
|
|
||||||
</div>
|
|
||||||
<div className='grow system-md-regular text-text-secondary truncate'>
|
|
||||||
DuckDuckGo Search
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
size='small'
|
|
||||||
variant='ghost-accent'
|
|
||||||
>
|
|
||||||
Clear
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</PortalToFollowElemContent>
|
|
||||||
</PortalToFollowElem>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default InstallInfo
|
|
27
web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts
Normal file
27
web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts
Normal file
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
137
web/app/components/plugins/plugin-page/plugin-tasks/index.tsx
Normal file
137
web/app/components/plugins/plugin-page/plugin-tasks/index.tsx
Normal file
|
@ -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 (
|
||||||
|
<div className='flex items-center'>
|
||||||
|
<PortalToFollowElem
|
||||||
|
open={open}
|
||||||
|
onOpenChange={setOpen}
|
||||||
|
placement='bottom-start'
|
||||||
|
offset={{
|
||||||
|
mainAxis: 4,
|
||||||
|
crossAxis: 79,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PortalToFollowElemTrigger
|
||||||
|
onClick={() => {
|
||||||
|
if (isFailed || isInstallingWithError)
|
||||||
|
setOpen(v => !v)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip popupContent={tip}>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'relative flex items-center justify-center w-8 h-8 rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg shadow-xs hover:bg-components-button-secondary-bg-hover',
|
||||||
|
(isInstallingWithError || isFailed) && 'border-components-button-destructive-secondary-border-hover bg-state-destructive-hover hover:bg-state-destructive-hover-alt',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<RiInstallLine
|
||||||
|
className={cn(
|
||||||
|
'w-4 h-4 text-components-button-secondary-text',
|
||||||
|
(isInstallingWithError || isFailed) && 'text-components-button-destructive-secondary-text',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className='absolute -right-1 -top-1'>
|
||||||
|
{
|
||||||
|
isInstalling && (
|
||||||
|
<ProgressCircle
|
||||||
|
percentage={runningPlugins.length / totalPluginsLength * 100}
|
||||||
|
circleFillColor='fill-components-progress-brand-bg'
|
||||||
|
sectorFillColor='fill-components-progress-error-bg'
|
||||||
|
circleStrokeColor='stroke-components-progress-error-bg'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
isInstallingWithError && (
|
||||||
|
<ProgressCircle
|
||||||
|
percentage={runningPlugins.length / totalPluginsLength * 100}
|
||||||
|
circleFillColor='fill-components-progress-brand-bg'
|
||||||
|
sectorFillColor='fill-components-progress-error-bg'
|
||||||
|
circleStrokeColor='stroke-components-progress-error-bg'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
isSuccess && (
|
||||||
|
<RiCheckboxCircleFill className='w-3.5 h-3.5 text-text-success' />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
isFailed && (
|
||||||
|
<RiErrorWarningFill className='w-3.5 h-3.5 text-text-destructive' />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</PortalToFollowElemTrigger>
|
||||||
|
<PortalToFollowElemContent className='z-10'>
|
||||||
|
<div className='p-1 pb-2 w-[320px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'>
|
||||||
|
<div className='flex items-center px-2 pt-1 h-7 system-sm-semibold-uppercase'>{t('plugin.task.installedError')}</div>
|
||||||
|
<div className='flex items-center p-1 pl-2 h-8 rounded-lg hover:bg-state-base-hover'>
|
||||||
|
<div className='relative flex items-center justify-center mr-2 w-6 h-6 rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge'>
|
||||||
|
<RiErrorWarningFill className='absolute -right-0.5 -bottom-0.5 w-3 h-3 text-text-destructive' />
|
||||||
|
</div>
|
||||||
|
<div className='grow system-md-regular text-text-secondary truncate'>
|
||||||
|
DuckDuckGo Search
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
size='small'
|
||||||
|
variant='ghost-accent'
|
||||||
|
>
|
||||||
|
{t('common.operation.clear')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PortalToFollowElemContent>
|
||||||
|
</PortalToFollowElem>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PluginTasks
|
|
@ -1,5 +1,5 @@
|
||||||
import { create } from 'zustand'
|
import { create } from 'zustand'
|
||||||
import type { PluginTask } from '../types'
|
import type { PluginTask } from '@/app/components/plugins/types'
|
||||||
import { fetchPluginTasks } from '@/service/plugins'
|
import { fetchPluginTasks } from '@/service/plugins'
|
||||||
|
|
||||||
type PluginTasksStore = {
|
type PluginTasksStore = {
|
|
@ -100,6 +100,7 @@ export type PluginDetail = {
|
||||||
endpoints_active: number
|
endpoints_active: number
|
||||||
version: string
|
version: string
|
||||||
latest_version: string
|
latest_version: string
|
||||||
|
latest_unique_identifier: string
|
||||||
source: PluginSource
|
source: PluginSource
|
||||||
meta?: MetaData
|
meta?: MetaData
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { pluginManifestToCardPluginProps } from '@/app/components/plugins/instal
|
||||||
import useGetIcon from '../install-plugin/base/use-get-icon'
|
import useGetIcon from '../install-plugin/base/use-get-icon'
|
||||||
import { updateFromMarketPlace } from '@/service/plugins'
|
import { updateFromMarketPlace } from '@/service/plugins'
|
||||||
import checkTaskStatus from '@/app/components/plugins/install-plugin/base/check-task-status'
|
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'
|
const i18nPrefix = 'plugin.upgrade'
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ const UpdatePluginModal: FC<Props> = ({
|
||||||
const handleConfirm = useCallback(async () => {
|
const handleConfirm = useCallback(async () => {
|
||||||
if (uploadStep === UploadStep.notStarted) {
|
if (uploadStep === UploadStep.notStarted) {
|
||||||
setUploadStep(UploadStep.upgrading)
|
setUploadStep(UploadStep.upgrading)
|
||||||
|
try {
|
||||||
const {
|
const {
|
||||||
all_installed: isInstalled,
|
all_installed: isInstalled,
|
||||||
task_id: taskId,
|
task_id: taskId,
|
||||||
|
@ -76,6 +77,7 @@ const UpdatePluginModal: FC<Props> = ({
|
||||||
original_plugin_unique_identifier: originalPackageInfo.id,
|
original_plugin_unique_identifier: originalPackageInfo.id,
|
||||||
new_plugin_unique_identifier: targetPackageInfo.id,
|
new_plugin_unique_identifier: targetPackageInfo.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isInstalled) {
|
if (isInstalled) {
|
||||||
onSave()
|
onSave()
|
||||||
return
|
return
|
||||||
|
@ -87,6 +89,11 @@ const UpdatePluginModal: FC<Props> = ({
|
||||||
})
|
})
|
||||||
onSave()
|
onSave()
|
||||||
}
|
}
|
||||||
|
catch (e) {
|
||||||
|
setUploadStep(UploadStep.notStarted)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
if (uploadStep === UploadStep.installed) {
|
if (uploadStep === UploadStep.installed) {
|
||||||
onSave()
|
onSave()
|
||||||
onCancel()
|
onCancel()
|
||||||
|
|
|
@ -124,6 +124,12 @@ const translation = {
|
||||||
inDifyMarketplace: 'in Dify Marketplace',
|
inDifyMarketplace: 'in Dify Marketplace',
|
||||||
moreFrom: 'More from 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
|
export default translation
|
||||||
|
|
|
@ -124,6 +124,12 @@ const translation = {
|
||||||
inDifyMarketplace: '在 Dify 市场中',
|
inDifyMarketplace: '在 Dify 市场中',
|
||||||
moreFrom: '更多来自市场',
|
moreFrom: '更多来自市场',
|
||||||
},
|
},
|
||||||
|
task: {
|
||||||
|
installing: '{{installingLength}}/{{totalLength}} 插件安装中...',
|
||||||
|
installingWithError: '{{installingLength}}/{{totalLength}} 插件安装中,{{errorLength}} 安装失败。点击查看',
|
||||||
|
installError: '{{errorLength}} 个插件安装失败,点击查看',
|
||||||
|
installedError: '{{errorLength}} 个插件安装失败',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default translation
|
export default translation
|
||||||
|
|
Loading…
Reference in New Issue
Block a user