app selector in form
This commit is contained in:
parent
7b4d67d72f
commit
f9f2e68bd8
@ -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>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user