dify/web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx

117 lines
3.4 KiB
TypeScript
Raw Normal View History

2024-11-14 13:02:12 +08:00
'use client'
import type { FC } from 'react'
2024-11-14 15:53:20 +08:00
import React, { useMemo, useState } from 'react'
2024-11-14 13:02:12 +08:00
import { useTranslation } from 'react-i18next'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import AppTrigger from '@/app/components/plugins/plugin-detail-panel/app-selector/app-trigger'
2024-11-14 14:11:55 +08:00
import AppPicker from '@/app/components/plugins/plugin-detail-panel/app-selector/app-picker'
// import Button from '@/app/components/base/button'
2024-11-14 13:02:12 +08:00
2024-11-14 15:53:20 +08:00
import { useAppFullList } from '@/service/use-apps'
2024-11-14 14:11:55 +08:00
import type { App } from '@/types/app'
2024-11-14 13:02:12 +08:00
import type {
OffsetOptions,
Placement,
} from '@floating-ui/react'
type Props = {
value?: {
2024-11-14 14:11:55 +08:00
app_id: string
inputs: Record<string, any>
files?: any[]
2024-11-14 13:02:12 +08:00
}
disabled?: boolean
placement?: Placement
offset?: OffsetOptions
2024-11-14 14:11:55 +08:00
onSelect: (app: {
app_id: string
inputs: Record<string, any>
files?: any[]
2024-11-14 13:02:12 +08:00
}) => void
supportAddCustomTool?: boolean
}
const AppSelector: FC<Props> = ({
value,
disabled,
placement = 'bottom',
offset = 4,
onSelect,
}) => {
const { t } = useTranslation()
const [isShow, onShowChange] = useState(false)
const handleTriggerClick = () => {
if (disabled) return
onShowChange(true)
}
2024-11-14 15:53:20 +08:00
const { data: appList } = useAppFullList()
const currentAppInfo = useMemo(() => {
if (!appList?.data || !value)
return undefined
return appList.data.find(app => app.id === value.app_id)
}, [appList?.data, value])
2024-11-14 13:02:12 +08:00
const [isShowChooseApp, setIsShowChooseApp] = useState(false)
2024-11-14 14:11:55 +08:00
const handleSelectApp = (app: App) => {
const appValue = {
app_id: app.id,
inputs: value?.inputs || {},
files: value?.files || [],
2024-11-14 13:02:12 +08:00
}
2024-11-14 14:11:55 +08:00
onSelect(appValue)
2024-11-14 13:02:12 +08:00
setIsShowChooseApp(false)
}
2024-11-14 15:53:20 +08:00
// const { data: currentApp } = useAppDetail(value?.app_id || 'empty')
2024-11-14 13:02:12 +08:00
return (
<>
<PortalToFollowElem
placement={placement}
offset={offset}
open={isShow}
onOpenChange={onShowChange}
>
<PortalToFollowElemTrigger
className='w-full'
onClick={handleTriggerClick}
>
<AppTrigger
open={isShow}
2024-11-14 15:53:20 +08:00
appDetail={currentAppInfo}
2024-11-14 13:02:12 +08:00
/>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'>
<div className="relative w-[389px] min-h-20 rounded-xl bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg">
<div className='px-4 py-3 flex flex-col gap-1'>
2024-11-14 15:53:20 +08:00
<div className='h-6 flex items-center system-sm-semibold text-text-secondary'>{t('app.appSelector.label')}</div>
2024-11-14 14:11:55 +08:00
<AppPicker
2024-11-14 13:02:12 +08:00
placement='bottom'
offset={offset}
trigger={
<AppTrigger
open={isShowChooseApp}
2024-11-14 15:53:20 +08:00
appDetail={currentAppInfo}
2024-11-14 13:02:12 +08:00
/>
}
isShow={isShowChooseApp}
onShowChange={setIsShowChooseApp}
disabled={false}
2024-11-14 15:53:20 +08:00
appList={appList?.data || []}
2024-11-14 14:11:55 +08:00
onSelect={handleSelectApp}
2024-11-14 13:02:12 +08:00
/>
</div>
{/* app inputs config panel */}
<div className='px-4 py-3 flex items-center border-t border-divider-subtle'>
</div>
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
</>
)
}
export default React.memo(AppSelector)