mirror of
https://github.com/langgenius/dify.git
synced 2025-12-25 01:00:42 -05:00
refactor: update install status handling in plugin installation process (#27594)
This commit is contained in:
@@ -4,7 +4,7 @@ import React, { useCallback, useState } from 'react'
|
||||
import { InstallStep } from '../../types'
|
||||
import Install from './steps/install'
|
||||
import Installed from './steps/installed'
|
||||
import type { Dependency, InstallStatusResponse, Plugin } from '../../types'
|
||||
import type { Dependency, InstallStatus, Plugin } from '../../types'
|
||||
|
||||
type Props = {
|
||||
step: InstallStep
|
||||
@@ -26,8 +26,8 @@ const ReadyToInstall: FC<Props> = ({
|
||||
isFromMarketPlace,
|
||||
}) => {
|
||||
const [installedPlugins, setInstalledPlugins] = useState<Plugin[]>([])
|
||||
const [installStatus, setInstallStatus] = useState<InstallStatusResponse[]>([])
|
||||
const handleInstalled = useCallback((plugins: Plugin[], installStatus: InstallStatusResponse[]) => {
|
||||
const [installStatus, setInstallStatus] = useState<InstallStatus[]>([])
|
||||
const handleInstalled = useCallback((plugins: Plugin[], installStatus: InstallStatus[]) => {
|
||||
setInstallStatus(installStatus)
|
||||
setInstalledPlugins(plugins)
|
||||
onStepChange(InstallStep.installed)
|
||||
|
||||
@@ -2,23 +2,31 @@
|
||||
import type { FC } from 'react'
|
||||
import { useRef } from 'react'
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import type { Dependency, InstallStatusResponse, Plugin, VersionInfo } from '../../../types'
|
||||
import {
|
||||
type Dependency,
|
||||
type InstallStatus,
|
||||
type InstallStatusResponse,
|
||||
type Plugin,
|
||||
TaskStatus,
|
||||
type VersionInfo,
|
||||
} from '../../../types'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { RiLoader2Line } from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { ExposeRefs } from './install-multi'
|
||||
import InstallMulti from './install-multi'
|
||||
import { useInstallOrUpdate } from '@/service/use-plugins'
|
||||
import { useInstallOrUpdate, usePluginTaskList } from '@/service/use-plugins'
|
||||
import useRefreshPluginList from '../../hooks/use-refresh-plugin-list'
|
||||
import { useCanInstallPluginFromMarketplace } from '@/app/components/plugins/plugin-page/use-reference-setting'
|
||||
import { useMittContextSelector } from '@/context/mitt-context'
|
||||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import checkTaskStatus from '../../base/check-task-status'
|
||||
const i18nPrefix = 'plugin.installModal'
|
||||
|
||||
type Props = {
|
||||
allPlugins: Dependency[]
|
||||
onStartToInstall?: () => void
|
||||
onInstalled: (plugins: Plugin[], installStatus: InstallStatusResponse[]) => void
|
||||
onInstalled: (plugins: Plugin[], installStatus: InstallStatus[]) => void
|
||||
onCancel: () => void
|
||||
isFromMarketPlace?: boolean
|
||||
isHideButton?: boolean
|
||||
@@ -55,18 +63,60 @@ const Install: FC<Props> = ({
|
||||
setCanInstall(true)
|
||||
}, [])
|
||||
|
||||
const {
|
||||
check,
|
||||
stop,
|
||||
} = checkTaskStatus()
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
stop()
|
||||
onCancel()
|
||||
}, [onCancel, stop])
|
||||
|
||||
const { handleRefetch } = usePluginTaskList()
|
||||
|
||||
// Install from marketplace and github
|
||||
const { mutate: installOrUpdate, isPending: isInstalling } = useInstallOrUpdate({
|
||||
onSuccess: (res: InstallStatusResponse[]) => {
|
||||
onInstalled(selectedPlugins, res.map((r, i) => {
|
||||
return ({
|
||||
...r,
|
||||
isFromMarketPlace: allPlugins[selectedIndexes[i]].type === 'marketplace',
|
||||
onSuccess: async (res: InstallStatusResponse[]) => {
|
||||
const isAllSettled = res.every(r => r.status === TaskStatus.success || r.status === TaskStatus.failed)
|
||||
// if all settled, return the install status
|
||||
if (isAllSettled) {
|
||||
onInstalled(selectedPlugins, res.map((r, i) => {
|
||||
return ({
|
||||
success: r.status === TaskStatus.success,
|
||||
isFromMarketPlace: allPlugins[selectedIndexes[i]].type === 'marketplace',
|
||||
})
|
||||
}))
|
||||
const hasInstallSuccess = res.some(r => r.status === TaskStatus.success)
|
||||
if (hasInstallSuccess) {
|
||||
refreshPluginList(undefined, true)
|
||||
emit('plugin:install:success', selectedPlugins.map((p) => {
|
||||
return `${p.plugin_id}/${p.name}`
|
||||
}))
|
||||
}
|
||||
return
|
||||
}
|
||||
// if not all settled, keep checking the status of the plugins
|
||||
handleRefetch()
|
||||
const installStatus = await Promise.all(res.map(async (item, index) => {
|
||||
if (item.status !== TaskStatus.running) {
|
||||
return {
|
||||
success: item.status === TaskStatus.success,
|
||||
isFromMarketPlace: allPlugins[selectedIndexes[index]].type === 'marketplace',
|
||||
}
|
||||
}
|
||||
const { status } = await check({
|
||||
taskId: item.taskId,
|
||||
pluginUniqueIdentifier: item.uniqueIdentifier,
|
||||
})
|
||||
return {
|
||||
success: status === TaskStatus.success,
|
||||
isFromMarketPlace: allPlugins[selectedIndexes[index]].type === 'marketplace',
|
||||
}
|
||||
}))
|
||||
const hasInstallSuccess = res.some(r => r.success)
|
||||
onInstalled(selectedPlugins, installStatus)
|
||||
const hasInstallSuccess = installStatus.some(r => r.success)
|
||||
if (hasInstallSuccess) {
|
||||
refreshPluginList(undefined, true)
|
||||
emit('plugin:install:success', selectedPlugins.map((p) => {
|
||||
return `${p.plugin_id}/${p.name}`
|
||||
}))
|
||||
@@ -150,7 +200,7 @@ const Install: FC<Props> = ({
|
||||
</div>
|
||||
<div className='flex items-center justify-end gap-2 self-stretch'>
|
||||
{!canInstall && (
|
||||
<Button variant='secondary' className='min-w-[72px]' onClick={onCancel}>
|
||||
<Button variant='secondary' className='min-w-[72px]' onClick={handleCancel}>
|
||||
{t('common.operation.cancel')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import type { InstallStatusResponse, Plugin } from '../../../types'
|
||||
import type { InstallStatus, Plugin } from '../../../types'
|
||||
import Card from '@/app/components/plugins/card'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -11,7 +11,7 @@ import { MARKETPLACE_API_PREFIX } from '@/config'
|
||||
|
||||
type Props = {
|
||||
list: Plugin[]
|
||||
installStatus: InstallStatusResponse[]
|
||||
installStatus: InstallStatus[]
|
||||
onCancel: () => void
|
||||
isHideButton?: boolean
|
||||
}
|
||||
|
||||
@@ -331,6 +331,7 @@ const DetailHeader = ({
|
||||
pluginPayload={{
|
||||
provider: provider?.name || '',
|
||||
category: AuthCategory.tool,
|
||||
providerType: provider?.type || '',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -314,6 +314,7 @@ const ToolSelector: FC<Props> = ({
|
||||
pluginPayload={{
|
||||
provider: currentProvider.name,
|
||||
category: AuthCategory.tool,
|
||||
providerType: currentProvider.type,
|
||||
}}
|
||||
credentialId={value?.credential_id}
|
||||
onAuthorizationItemClick={handleAuthorizationItemClick}
|
||||
|
||||
@@ -280,6 +280,12 @@ export type InstallPackageResponse = {
|
||||
}
|
||||
|
||||
export type InstallStatusResponse = {
|
||||
status: TaskStatus,
|
||||
taskId: string,
|
||||
uniqueIdentifier: string,
|
||||
}
|
||||
|
||||
export type InstallStatus = {
|
||||
success: boolean,
|
||||
isFromMarketPlace?: boolean
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user