app selector in form

This commit is contained in:
JzoNg 2024-11-14 15:53:20 +08:00
parent 7b4d67d72f
commit f9f2e68bd8
3 changed files with 44 additions and 12 deletions

View File

@ -19,6 +19,7 @@ import Tooltip from '@/app/components/base/tooltip'
import Radio from '@/app/components/base/radio' import Radio from '@/app/components/base/radio'
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal' import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector' import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector'
import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector'
type FormProps = { type FormProps = {
className?: string className?: string
@ -347,7 +348,32 @@ const Form: FC<FormProps> = ({
} }
if (formSchema.type === FormTypeEnum.appSelector) { if (formSchema.type === FormTypeEnum.appSelector) {
// TODO const {
variable,
label,
required,
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
return (
<div key={variable} className={cn(itemClassName, 'py-3')}>
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
{label[language] || label.en_US}
{
required && (
<span className='ml-1 text-red-500'>*</span>
)
}
{tooltipContent}
</div>
<AppSelector
disabled={readonly}
value={value[variable]}
onSelect={item => handleFormChange(variable, item as any)}
/>
{fieldMoreInfo?.(formSchema)}
{validating && changeKey === variable && <ValidatingTip />}
</div>
)
} }
} }

View File

@ -13,12 +13,10 @@ import type {
} from '@floating-ui/react' } from '@floating-ui/react'
import Input from '@/app/components/base/input' import Input from '@/app/components/base/input'
import AppIcon from '@/app/components/base/app-icon' import AppIcon from '@/app/components/base/app-icon'
import {
useAppFullList,
} from '@/service/use-apps'
import type { App } from '@/types/app' import type { App } from '@/types/app'
type Props = { type Props = {
appList: App[]
disabled: boolean disabled: boolean
trigger: React.ReactNode trigger: React.ReactNode
placement?: Placement placement?: Placement
@ -29,6 +27,7 @@ type Props = {
} }
const AppPicker: FC<Props> = ({ const AppPicker: FC<Props> = ({
appList,
disabled, disabled,
trigger, trigger,
placement = 'right-start', placement = 'right-start',
@ -38,9 +37,8 @@ const AppPicker: FC<Props> = ({
onSelect, onSelect,
}) => { }) => {
const [searchText, setSearchText] = useState('') const [searchText, setSearchText] = useState('')
const { data: appList } = useAppFullList()
const filteredAppList = useMemo(() => { const filteredAppList = useMemo(() => {
return (appList?.data || []).filter(app => app.name.toLowerCase().includes(searchText.toLowerCase())).filter(app => (app.mode !== 'advanced-chat' && app.mode !== 'workflow') || !!app.workflow) return (appList || []).filter(app => app.name.toLowerCase().includes(searchText.toLowerCase())).filter(app => (app.mode !== 'advanced-chat' && app.mode !== 'workflow') || !!app.workflow)
}, [appList, searchText]) }, [appList, searchText])
const getAppType = (app: App) => { const getAppType = (app: App) => {
switch (app.mode) { switch (app.mode) {

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React, { useState } from 'react' import React, { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { import {
PortalToFollowElem, PortalToFollowElem,
@ -11,7 +11,7 @@ import AppTrigger from '@/app/components/plugins/plugin-detail-panel/app-selecto
import AppPicker from '@/app/components/plugins/plugin-detail-panel/app-selector/app-picker' import AppPicker from '@/app/components/plugins/plugin-detail-panel/app-selector/app-picker'
// import Button from '@/app/components/base/button' // import Button from '@/app/components/base/button'
import { useAppDetail } from '@/service/use-apps' import { useAppFullList } from '@/service/use-apps'
import type { App } from '@/types/app' import type { App } from '@/types/app'
import type { import type {
OffsetOptions, OffsetOptions,
@ -48,7 +48,12 @@ const AppSelector: FC<Props> = ({
onShowChange(true) onShowChange(true)
} }
const { data: currentApp } = useAppDetail(value?.app_id || 'empty') 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])
const [isShowChooseApp, setIsShowChooseApp] = useState(false) const [isShowChooseApp, setIsShowChooseApp] = useState(false)
const handleSelectApp = (app: App) => { const handleSelectApp = (app: App) => {
const appValue = { const appValue = {
@ -60,6 +65,8 @@ const AppSelector: FC<Props> = ({
setIsShowChooseApp(false) setIsShowChooseApp(false)
} }
// const { data: currentApp } = useAppDetail(value?.app_id || 'empty')
return ( return (
<> <>
<PortalToFollowElem <PortalToFollowElem
@ -74,25 +81,26 @@ const AppSelector: FC<Props> = ({
> >
<AppTrigger <AppTrigger
open={isShow} open={isShow}
appDetail={currentApp} appDetail={currentAppInfo}
/> />
</PortalToFollowElemTrigger> </PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'> <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="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'> <div className='px-4 py-3 flex flex-col gap-1'>
<div className='h-6 flex items-center system-sm-semibold text-text-secondary'>{t('tools.toolSelector.label')}</div> <div className='h-6 flex items-center system-sm-semibold text-text-secondary'>{t('app.appSelector.label')}</div>
<AppPicker <AppPicker
placement='bottom' placement='bottom'
offset={offset} offset={offset}
trigger={ trigger={
<AppTrigger <AppTrigger
open={isShowChooseApp} open={isShowChooseApp}
appDetail={currentApp} appDetail={currentAppInfo}
/> />
} }
isShow={isShowChooseApp} isShow={isShowChooseApp}
onShowChange={setIsShowChooseApp} onShowChange={setIsShowChooseApp}
disabled={false} disabled={false}
appList={appList?.data || []}
onSelect={handleSelectApp} onSelect={handleSelectApp}
/> />
</div> </div>