feat: files attr select

This commit is contained in:
Joel 2024-08-13 13:59:19 +08:00
parent ae098ad121
commit 6549519fa5
6 changed files with 78 additions and 5 deletions

View File

@ -96,7 +96,7 @@ const Select: FC<ISelectProps> = ({
<div className='group text-gray-800'> <div className='group text-gray-800'>
{allowSearch {allowSearch
? <Combobox.Input ? <Combobox.Input
className={`w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 cursor-not-allowed`} className={classNames('w-full rounded-lg border-0 py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 cursor-not-allowed', bgClassName)}
onChange={(event) => { onChange={(event) => {
if (!disabled) if (!disabled)
setQuery(event.target.value) setQuery(event.target.value)
@ -200,7 +200,7 @@ const SimpleSelect: FC<ISelectProps> = ({
}} }}
> >
<div className={classNames('relative h-9', wrapperClassName)}> <div className={classNames('relative h-9', wrapperClassName)}>
<Listbox.Button className={`flex items-center w-full h-full rounded-lg border-0 bg-gray-100 pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'} ${className}`}> <Listbox.Button className={classNames(`flex items-center w-full h-full rounded-lg border-0 bg-gray-100 pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`, className)}>
<span className={classNames('block truncate text-left', !selectedItem?.name && 'text-gray-400')}>{selectedItem?.name ?? localPlaceholder}</span> <span className={classNames('block truncate text-left', !selectedItem?.name && 'text-gray-400')}>{selectedItem?.name ?? localPlaceholder}</span>
<span className="absolute inset-y-0 right-0 flex items-center pr-2"> <span className="absolute inset-y-0 right-0 flex items-center pr-2">
{selectedItem {selectedItem

View File

@ -1,17 +1,22 @@
import { import {
useCallback, useCallback,
useMemo,
useState, useState,
} from 'react' } from 'react'
import { useTranslation } from 'react-i18next'
import { RiDeleteBinLine } from '@remixicon/react' import { RiDeleteBinLine } from '@remixicon/react'
import type { VarType as NumberVarType } from '../../../tool/types' import type { VarType as NumberVarType } from '../../../tool/types'
import type { import type {
ComparisonOperator,
Condition, Condition,
HandleRemoveCondition, HandleRemoveCondition,
HandleUpdateCondition, HandleUpdateCondition,
} from '../../types' } from '../../types'
import {
ComparisonOperator,
} from '../../types'
import { comparisonOperatorNotRequireValue } from '../../utils' import { comparisonOperatorNotRequireValue } from '../../utils'
import ConditionNumberInput from '../condition-number-input' import ConditionNumberInput from '../condition-number-input'
import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from '../../default'
import ConditionOperator from './condition-operator' import ConditionOperator from './condition-operator'
import ConditionInput from './condition-input' import ConditionInput from './condition-input'
import VariableTag from '@/app/components/workflow/nodes/_base/components/variable-tag' import VariableTag from '@/app/components/workflow/nodes/_base/components/variable-tag'
@ -21,6 +26,9 @@ import type {
} from '@/app/components/workflow/types' } from '@/app/components/workflow/types'
import { VarType } from '@/app/components/workflow/types' import { VarType } from '@/app/components/workflow/types'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { SimpleSelect as Select } from '@/app/components/base/select'
const optionNameI18NPrefix = 'workflow.nodes.ifElse.optionName'
type ConditionItemProps = { type ConditionItemProps = {
disabled?: boolean disabled?: boolean
@ -44,6 +52,8 @@ const ConditionItem = ({
availableNodes, availableNodes,
numberVariables, numberVariables,
}: ConditionItemProps) => { }: ConditionItemProps) => {
const { t } = useTranslation()
const [isHovered, setIsHovered] = useState(false) const [isHovered, setIsHovered] = useState(false)
const handleUpdateConditionOperator = useCallback((value: ComparisonOperator) => { const handleUpdateConditionOperator = useCallback((value: ComparisonOperator) => {
@ -71,6 +81,26 @@ const ConditionItem = ({
onUpdateCondition(caseId, condition.id, newCondition) onUpdateCondition(caseId, condition.id, newCondition)
}, [caseId, condition, onUpdateCondition]) }, [caseId, condition, onUpdateCondition])
const isSelect = condition.comparison_operator && [ComparisonOperator.in, ComparisonOperator.notIn].includes(condition.comparison_operator)
const selectOptions = useMemo(() => {
if (isSelect) {
if (file?.key === 'type') {
return FILE_TYPE_OPTIONS.map(item => ({
name: t(`${optionNameI18NPrefix}.${item.i18nKey}`),
value: item.value,
}))
}
if (file?.key === 'transfer_method') {
return TRANSFER_METHOD.map(item => ({
name: t(`${optionNameI18NPrefix}.${item.i18nKey}`),
value: item.value,
}))
}
return []
}
return []
}, [file?.key, isSelect, t])
return ( return (
<div className='flex mb-1 last-of-type:mb-0'> <div className='flex mb-1 last-of-type:mb-0'>
<div className={cn( <div className={cn(
@ -94,7 +124,7 @@ const ConditionItem = ({
/> />
</div> </div>
{ {
!comparisonOperatorNotRequireValue(condition.comparison_operator) && condition.varType !== VarType.number && ( !comparisonOperatorNotRequireValue(condition.comparison_operator) && !isSelect && condition.varType !== VarType.number && (
<div className='px-2 py-1 max-h-[100px] border-t border-t-divider-subtle overflow-y-auto'> <div className='px-2 py-1 max-h-[100px] border-t border-t-divider-subtle overflow-y-auto'>
<ConditionInput <ConditionInput
disabled={disabled} disabled={disabled}
@ -107,7 +137,7 @@ const ConditionItem = ({
) )
} }
{ {
!comparisonOperatorNotRequireValue(condition.comparison_operator) && condition.varType === VarType.number && ( !comparisonOperatorNotRequireValue(condition.comparison_operator) && !isSelect && condition.varType === VarType.number && (
<div className='px-2 py-1 pt-[3px] border-t border-t-divider-subtle'> <div className='px-2 py-1 pt-[3px] border-t border-t-divider-subtle'>
<ConditionNumberInput <ConditionNumberInput
numberVarType={condition.numberVarType} numberVarType={condition.numberVarType}
@ -119,6 +149,19 @@ const ConditionItem = ({
</div> </div>
) )
} }
{
!comparisonOperatorNotRequireValue(condition.comparison_operator) && isSelect && (
<div className='p-1'>
<Select
wrapperClassName='h-6'
className='pl-0 text-xs'
defaultValue={condition.value}
items={selectOptions}
onSelect={item => handleUpdateConditionValue(item.value as string)}
/>
</div>
)
}
</div> </div>
<div <div
className='shrink-0 flex items-center justify-center ml-1 mt-1 w-6 h-6 rounded-lg cursor-pointer hover:bg-state-destructive-hover text-text-tertiary hover:text-text-destructive' className='shrink-0 flex items-center justify-center ml-1 mt-1 w-6 h-6 rounded-lg cursor-pointer hover:bg-state-destructive-hover text-text-tertiary hover:text-text-destructive'

View File

@ -1,6 +1,7 @@
import { BlockEnum, type NodeDefault } from '../../types' import { BlockEnum, type NodeDefault } from '../../types'
import { type IfElseNodeType, LogicalOperator } from './types' import { type IfElseNodeType, LogicalOperator } from './types'
import { isEmptyRelatedOperator } from './utils' import { isEmptyRelatedOperator } from './utils'
import { TransferMethod } from '@/types/app'
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants' import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants'
const i18nPrefix = 'workflow.errorMsg' const i18nPrefix = 'workflow.errorMsg'
@ -61,3 +62,15 @@ const nodeDefault: NodeDefault<IfElseNodeType> = {
} }
export default nodeDefault export default nodeDefault
export const FILE_TYPE_OPTIONS = [
{ value: 'image', i18nKey: 'image' },
{ value: 'doc', i18nKey: 'doc' },
{ value: 'audio', i18nKey: 'audio' },
{ value: 'video', i18nKey: 'video' },
]
export const TRANSFER_METHOD = [
{ value: TransferMethod.local_file, i18nKey: 'localUpload' },
{ value: TransferMethod.remote_url, i18nKey: 'url' },
]

View File

@ -82,6 +82,7 @@ export const getOperators = (type?: VarType, file?: { key: string }) => {
ComparisonOperator.notEmpty, ComparisonOperator.notEmpty,
] ]
} }
return []
} }
switch (type) { switch (type) {
case VarType.string: case VarType.string:

View File

@ -390,6 +390,14 @@ const translation = {
'in': 'in', 'in': 'in',
'not in': 'not in', 'not in': 'not in',
}, },
optionName: {
image: 'Image',
doc: 'Doc',
audio: 'Audio',
video: 'Video',
localUpload: 'Local Upload',
url: 'URL',
},
enterValue: 'Enter value', enterValue: 'Enter value',
addCondition: 'Add Condition', addCondition: 'Add Condition',
conditionNotSetup: 'Condition NOT setup', conditionNotSetup: 'Condition NOT setup',

View File

@ -390,6 +390,14 @@ const translation = {
'in': '在', 'in': '在',
'not in': '不在', 'not in': '不在',
}, },
optionName: {
image: '图片',
doc: '文档',
audio: '音频',
video: '视频',
localUpload: '本地上传',
url: 'URL',
},
enterValue: '输入值', enterValue: '输入值',
addCondition: '添加条件', addCondition: '添加条件',
conditionNotSetup: '条件未设置', conditionNotSetup: '条件未设置',