refactor: update install status handling in plugin installation process (#27594)

This commit is contained in:
Wu Tianwei
2025-10-29 18:31:02 +08:00
committed by GitHub
parent f260627660
commit 4ca7ba000c
13 changed files with 157 additions and 32 deletions

View File

@@ -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)

View File

@@ -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>
)}

View File

@@ -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
}

View File

@@ -331,6 +331,7 @@ const DetailHeader = ({
pluginPayload={{
provider: provider?.name || '',
category: AuthCategory.tool,
providerType: provider?.type || '',
}}
/>
)

View File

@@ -314,6 +314,7 @@ const ToolSelector: FC<Props> = ({
pluginPayload={{
provider: currentProvider.name,
category: AuthCategory.tool,
providerType: currentProvider.type,
}}
credentialId={value?.credential_id}
onAuthorizationItemClick={handleAuthorizationItemClick}

View File

@@ -280,6 +280,12 @@ export type InstallPackageResponse = {
}
export type InstallStatusResponse = {
status: TaskStatus,
taskId: string,
uniqueIdentifier: string,
}
export type InstallStatus = {
success: boolean,
isFromMarketPlace?: boolean
}