This commit is contained in:
2025-12-01 17:21:38 +08:00
parent 32fee2b8ab
commit fab8c13cb3
7511 changed files with 996300 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
import { checkTaskStatus as fetchCheckTaskStatus } from '@/service/plugins'
import type { PluginStatus } from '../../types'
import { TaskStatus } from '../../types'
import { sleep } from '@/utils'
const INTERVAL = 10 * 1000 // 10 seconds
type Params = {
taskId: string
pluginUniqueIdentifier: string
}
function checkTaskStatus() {
let nextStatus = TaskStatus.running
let isStop = false
const doCheckStatus = async ({
taskId,
pluginUniqueIdentifier,
}: Params) => {
if (isStop) {
return {
status: TaskStatus.success,
}
}
const res = await fetchCheckTaskStatus(taskId)
const { plugins } = res.task
const plugin = plugins.find((p: PluginStatus) => p.plugin_unique_identifier === pluginUniqueIdentifier)
if (!plugin) {
nextStatus = TaskStatus.failed
return {
status: TaskStatus.failed,
error: 'Plugin package not found',
}
}
nextStatus = plugin.status
if (nextStatus === TaskStatus.running) {
await sleep(INTERVAL)
return await doCheckStatus({
taskId,
pluginUniqueIdentifier,
})
}
if (nextStatus === TaskStatus.failed) {
return {
status: TaskStatus.failed,
error: plugin.message,
}
}
return ({
status: TaskStatus.success,
})
}
return {
check: doCheckStatus,
stop: () => {
isStop = true
},
}
}
export default checkTaskStatus

View File

@@ -0,0 +1,60 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import Card from '../../card'
import Button from '@/app/components/base/button'
import type { Plugin, PluginDeclaration, PluginManifestInMarket } from '../../types'
import { pluginManifestInMarketToPluginProps, pluginManifestToCardPluginProps } from '../utils'
import Badge, { BadgeState } from '@/app/components/base/badge/index'
type Props = {
payload?: Plugin | PluginDeclaration | PluginManifestInMarket | null
isMarketPayload?: boolean
isFailed: boolean
errMsg?: string | null
onCancel: () => void
}
const Installed: FC<Props> = ({
payload,
isMarketPayload,
isFailed,
errMsg,
onCancel,
}) => {
const { t } = useTranslation()
const handleClose = () => {
onCancel()
}
return (
<>
<div className='flex flex-col items-start justify-center gap-4 self-stretch px-6 py-3'>
<p className='system-md-regular text-text-secondary'>{(isFailed && errMsg) ? errMsg : t(`plugin.installModal.${isFailed ? 'installFailedDesc' : 'installedSuccessfullyDesc'}`)}</p>
{payload && (
<div className='flex flex-wrap content-start items-start gap-1 self-stretch rounded-2xl bg-background-section-burn p-2'>
<Card
className='w-full'
payload={isMarketPayload ? pluginManifestInMarketToPluginProps(payload as PluginManifestInMarket) : pluginManifestToCardPluginProps(payload as PluginDeclaration)}
installed={!isFailed}
installFailed={isFailed}
titleLeft={<Badge className='mx-1' size="s" state={BadgeState.Default}>{(payload as PluginDeclaration).version || (payload as PluginManifestInMarket).latest_version}</Badge>}
/>
</div>
)}
</div>
{/* Action Buttons */}
<div className='flex items-center justify-end gap-2 self-stretch p-6 pt-5'>
<Button
variant='primary'
className='min-w-[72px]'
onClick={handleClose}
>
{t('common.operation.close')}
</Button>
</div>
</>
)
}
export default React.memo(Installed)

View File

@@ -0,0 +1,45 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import { Group } from '../../../base/icons/src/vender/other'
import { LoadingPlaceholder } from '@/app/components/plugins/card/base/placeholder'
import Checkbox from '@/app/components/base/checkbox'
import { RiCloseLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
const LoadingError: FC = () => {
const { t } = useTranslation()
return (
<div className='flex items-center space-x-2'>
<Checkbox
className='shrink-0'
checked={false}
disabled
/>
<div className='hover-bg-components-panel-on-panel-item-bg relative grow rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg p-4 pb-3 shadow-xs'>
<div className="flex">
<div
className='relative flex h-10 w-10 items-center justify-center gap-2 rounded-[10px] border-[0.5px]
border-state-destructive-border bg-state-destructive-hover p-1 backdrop-blur-sm'>
<div className='flex h-5 w-5 items-center justify-center'>
<Group className='text-text-quaternary' />
</div>
<div className='absolute bottom-[-4px] right-[-4px] rounded-full border-[2px] border-components-panel-bg bg-state-destructive-solid'>
<RiCloseLine className='h-3 w-3 text-text-primary-on-surface' />
</div>
</div>
<div className="ml-3 grow">
<div className="system-md-semibold flex h-5 items-center text-text-destructive">
{t('plugin.installModal.pluginLoadError')}
</div>
<div className='system-xs-regular mt-0.5 text-text-tertiary'>
{t('plugin.installModal.pluginLoadErrorDesc')}
</div>
</div>
</div>
<LoadingPlaceholder className="mt-3 w-[420px]" />
</div>
</div>
)
}
export default React.memo(LoadingError)

View File

@@ -0,0 +1,23 @@
'use client'
import React from 'react'
import Placeholder from '../../card/base/placeholder'
import Checkbox from '@/app/components/base/checkbox'
const Loading = () => {
return (
<div className='flex items-center space-x-2'>
<Checkbox
className='shrink-0'
checked={false}
disabled
/>
<div className='hover-bg-components-panel-on-panel-item-bg relative grow rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg p-4 pb-3 shadow-xs'>
<Placeholder
wrapClassName='w-full'
/>
</div>
</div>
)
}
export default React.memo(Loading)

View File

@@ -0,0 +1,16 @@
import { useCallback } from 'react'
import { API_PREFIX } from '@/config'
import { useSelector } from '@/context/app-context'
const useGetIcon = () => {
const currentWorkspace = useSelector(s => s.currentWorkspace)
const getIconUrl = useCallback((fileName: string) => {
return `${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${currentWorkspace.id}&filename=${fileName}`
}, [currentWorkspace.id])
return {
getIconUrl,
}
}
export default useGetIcon

View File

@@ -0,0 +1,34 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import Badge, { BadgeState } from '@/app/components/base/badge/index'
import type { VersionProps } from '../../types'
const Version: FC<VersionProps> = ({
hasInstalled,
installedVersion,
toInstallVersion,
}) => {
return (
<>
{
!hasInstalled
? (
<Badge className='mx-1' size="s" state={BadgeState.Default}>{toInstallVersion}</Badge>
)
: (
<>
<Badge className='mx-1' size="s" state={BadgeState.Warning}>
{`${installedVersion} -> ${toInstallVersion}`}
</Badge>
{/* <div className='flex px-0.5 justify-center items-center gap-0.5'>
<div className='text-text-warning system-xs-medium'>Used in 3 apps</div>
<RiInformation2Line className='w-4 h-4 text-text-tertiary' />
</div> */}
</>
)
}
</>
)
}
export default React.memo(Version)