From 77aa35ff1528178f1434ab2c4059d474f4315b17 Mon Sep 17 00:00:00 2001 From: Joel Date: Fri, 4 Jul 2025 15:27:52 +0800 Subject: [PATCH] feat: add boolean type --- .../config-var/config-modal/index.tsx | 91 ++++++++++-------- .../config-var/config-modal/type-select.tsx | 96 +++++++++++++++++++ .../_base/components/input-var-type-icon.tsx | 3 +- web/app/components/workflow/types.ts | 1 + web/i18n/en-US/app-debug.ts | 1 + web/i18n/zh-Hans/app-debug.ts | 1 + 6 files changed, 154 insertions(+), 39 deletions(-) create mode 100644 web/app/components/app/configuration/config-var/config-modal/type-select.tsx diff --git a/web/app/components/app/configuration/config-var/config-modal/index.tsx b/web/app/components/app/configuration/config-var/config-modal/index.tsx index 29cbc55b90..c5edad5a3e 100644 --- a/web/app/components/app/configuration/config-var/config-modal/index.tsx +++ b/web/app/components/app/configuration/config-var/config-modal/index.tsx @@ -7,7 +7,6 @@ import produce from 'immer' import ModalFoot from '../modal-foot' import ConfigSelect from '../config-select' import ConfigString from '../config-string' -import SelectTypeItem from '../select-type-item' import Field from './field' import Input from '@/app/components/base/input' import Toast from '@/app/components/base/toast' @@ -20,6 +19,8 @@ import FileUploadSetting from '@/app/components/workflow/nodes/_base/components/ import Checkbox from '@/app/components/base/checkbox' import { DEFAULT_FILE_UPLOAD_SETTING } from '@/app/components/workflow/constants' import { DEFAULT_VALUE_MAX_LEN } from '@/config' +import type { Item as SelectItem } from './type-select' +import TypeSelector from './type-select' const TEXT_MAX_LENGTH = 256 @@ -77,23 +78,56 @@ const ConfigModal: FC = ({ } }, []) - const handleTypeChange = useCallback((type: InputVarType) => { - return () => { - const newPayload = produce(tempPayload, (draft) => { - draft.type = type - if ([InputVarType.singleFile, InputVarType.multiFiles].includes(type)) { - (Object.keys(DEFAULT_FILE_UPLOAD_SETTING)).forEach((key) => { - if (key !== 'max_length') - (draft as any)[key] = (DEFAULT_FILE_UPLOAD_SETTING as any)[key] - }) - if (type === InputVarType.multiFiles) - draft.max_length = DEFAULT_FILE_UPLOAD_SETTING.max_length - } - if (type === InputVarType.paragraph) - draft.max_length = DEFAULT_VALUE_MAX_LEN - }) - setTempPayload(newPayload) - } + const selectOptions: SelectItem[] = [ + { + name: t('appDebug.variableConfig.text-input'), + value: InputVarType.textInput, + }, + { + name: t('appDebug.variableConfig.paragraph'), + value: InputVarType.paragraph, + }, + { + name: t('appDebug.variableConfig.select'), + value: InputVarType.select, + }, + { + name: t('appDebug.variableConfig.number'), + value: InputVarType.number, + }, + { + name: t('appDebug.variableConfig.boolean'), + value: InputVarType.boolean, + }, + ...(supportFile ? [ + { + name: t('appDebug.variableConfig.single-file'), + value: InputVarType.singleFile, + }, + { + name: t('appDebug.variableConfig.multi-files'), + value: InputVarType.multiFiles, + }, + ] : []), + ] + + const handleTypeChange = useCallback((item: SelectItem) => { + const type = item.value as InputVarType + + const newPayload = produce(tempPayload, (draft) => { + draft.type = type + if ([InputVarType.singleFile, InputVarType.multiFiles].includes(type)) { + (Object.keys(DEFAULT_FILE_UPLOAD_SETTING)).forEach((key) => { + if (key !== 'max_length') + (draft as any)[key] = (DEFAULT_FILE_UPLOAD_SETTING as any)[key] + }) + if (type === InputVarType.multiFiles) + draft.max_length = DEFAULT_FILE_UPLOAD_SETTING.max_length + } + if (type === InputVarType.paragraph) + draft.max_length = DEFAULT_VALUE_MAX_LEN + }) + setTempPayload(newPayload) }, [tempPayload]) const handleVarKeyBlur = useCallback((e: any) => { @@ -121,15 +155,6 @@ const ConfigModal: FC = ({ if (!isVariableNameValid) return - // TODO: check if key already exists. should the consider the edit case - // if (varKeys.map(key => key?.trim()).includes(tempPayload.variable.trim())) { - // Toast.notify({ - // type: 'error', - // message: t('appDebug.varKeyError.keyAlreadyExists', { key: tempPayload.variable }), - // }) - // return - // } - if (!tempPayload.label) { Toast.notify({ type: 'error', message: t('appDebug.variableConfig.errorMsg.labelNameRequired') }) return @@ -183,18 +208,8 @@ const ConfigModal: FC = ({ >
- -
- - - - - {supportFile && <> - - - } -
+
diff --git a/web/app/components/app/configuration/config-var/config-modal/type-select.tsx b/web/app/components/app/configuration/config-var/config-modal/type-select.tsx new file mode 100644 index 0000000000..a8b14872a7 --- /dev/null +++ b/web/app/components/app/configuration/config-var/config-modal/type-select.tsx @@ -0,0 +1,96 @@ +'use client' +import type { FC } from 'react' +import React, { useState } from 'react' +import { ChevronDownIcon } from '@heroicons/react/20/solid' +import { useTranslation } from 'react-i18next' +import classNames from '@/utils/classnames' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon' +import type { InputVarType } from '@/app/components/workflow/types' +import cn from '@/utils/classnames' + +export type Item = { + value: InputVarType + name: string +} + +type Props = { + value: string | number + onSelect: (value: Item) => void + items: Item[] + popupClassName?: string + popupInnerClassName?: string + readonly?: boolean + hideChecked?: boolean +} +const TypeSelector: FC = ({ + value, + onSelect, + items, + popupInnerClassName, + readonly, +}) => { + const { t } = useTranslation() + const [open, setOpen] = useState(false) + const selectedItem = value ? items.find(item => item.value === value) : undefined + + return ( + + !readonly && setOpen(v => !v)} className='w-full'> +
+
+ + + {selectedItem?.name} + +
+
+ +
+
+ +
+ +
+ {items.map((item: Item) => ( +
{ + onSelect(item) + setOpen(false) + }} + > +
+ + {item.name} +
+ +
+ ))} +
+
+
+ ) +} + +export default TypeSelector diff --git a/web/app/components/workflow/nodes/_base/components/input-var-type-icon.tsx b/web/app/components/workflow/nodes/_base/components/input-var-type-icon.tsx index d3cc1dbc78..a0d89aecc2 100644 --- a/web/app/components/workflow/nodes/_base/components/input-var-type-icon.tsx +++ b/web/app/components/workflow/nodes/_base/components/input-var-type-icon.tsx @@ -1,7 +1,7 @@ 'use client' import type { FC } from 'react' import React from 'react' -import { RiAlignLeft, RiCheckboxMultipleLine, RiFileCopy2Line, RiFileList2Line, RiHashtag, RiTextSnippet } from '@remixicon/react' +import { RiAlignLeft, RiCheckboxLine, RiCheckboxMultipleLine, RiFileCopy2Line, RiFileList2Line, RiHashtag, RiTextSnippet } from '@remixicon/react' import { InputVarType } from '../../../types' type Props = { @@ -15,6 +15,7 @@ const getIcon = (type: InputVarType) => { [InputVarType.paragraph]: RiAlignLeft, [InputVarType.select]: RiCheckboxMultipleLine, [InputVarType.number]: RiHashtag, + [InputVarType.boolean]: RiCheckboxLine, [InputVarType.singleFile]: RiFileList2Line, [InputVarType.multiFiles]: RiFileCopy2Line, } as any)[type] || RiTextSnippet diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index c9e5aa31b5..55717d75dd 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -175,6 +175,7 @@ export enum InputVarType { paragraph = 'paragraph', select = 'select', number = 'number', + boolean = 'boolean', url = 'url', files = 'files', json = 'json', // obj, array diff --git a/web/i18n/en-US/app-debug.ts b/web/i18n/en-US/app-debug.ts index 349ff37118..c81aae4e02 100644 --- a/web/i18n/en-US/app-debug.ts +++ b/web/i18n/en-US/app-debug.ts @@ -355,6 +355,7 @@ const translation = { 'paragraph': 'Paragraph', 'select': 'Select', 'number': 'Number', + 'boolean': 'Checkbox', 'single-file': 'Single File', 'multi-files': 'File List', 'notSet': 'Not set, try typing {{input}} in the prefix prompt', diff --git a/web/i18n/zh-Hans/app-debug.ts b/web/i18n/zh-Hans/app-debug.ts index 4f84b396d0..60158e1918 100644 --- a/web/i18n/zh-Hans/app-debug.ts +++ b/web/i18n/zh-Hans/app-debug.ts @@ -349,6 +349,7 @@ const translation = { 'paragraph': '段落', 'select': '下拉选项', 'number': '数字', + 'boolean': '复选框', 'single-file': '单文件', 'multi-files': '文件列表', 'notSet': '未设置,在 Prompt 中输入 {{input}} 试试',