From 30775109fd25747ea5dc16ded48dcedc93bb7cae Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 21 Aug 2025 14:47:29 +0800 Subject: [PATCH] feat: can edit and choose obj --- .../config-var/config-modal/config.ts | 24 +++++++++++++++++++ .../config-var/config-modal/field.tsx | 9 ++++++- .../config-var/config-modal/index.tsx | 22 +++++++++++++++++ .../config-var/config-modal/type-select.tsx | 2 -- .../_base/components/input-var-type-icon.tsx | 3 ++- .../nodes/_base/components/variable/utils.ts | 1 + web/app/components/workflow/types.ts | 2 ++ web/i18n/en-US/app-debug.ts | 3 +++ web/i18n/zh-Hans/app-debug.ts | 3 +++ 9 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 web/app/components/app/configuration/config-var/config-modal/config.ts diff --git a/web/app/components/app/configuration/config-var/config-modal/config.ts b/web/app/components/app/configuration/config-var/config-modal/config.ts new file mode 100644 index 0000000000..0de8f79302 --- /dev/null +++ b/web/app/components/app/configuration/config-var/config-modal/config.ts @@ -0,0 +1,24 @@ +export const jsonObjectWrap = { + type: 'object', + properties: {}, + required: [], + additionalProperties: true, +} + +export const jsonConfigPlaceHolder = JSON.stringify( + { + foo: { + type: 'string', + }, + bar: { + type: 'object', + properties: { + sub: { + type: 'number', + }, + }, + required: [], + additionalProperties: true, + }, + }, null, 2, +) diff --git a/web/app/components/app/configuration/config-var/config-modal/field.tsx b/web/app/components/app/configuration/config-var/config-modal/field.tsx index 78bd2d9f72..b24e0be6ce 100644 --- a/web/app/components/app/configuration/config-var/config-modal/field.tsx +++ b/web/app/components/app/configuration/config-var/config-modal/field.tsx @@ -2,21 +2,28 @@ import type { FC } from 'react' import React from 'react' import cn from '@/utils/classnames' +import { useTranslation } from 'react-i18next' type Props = { className?: string title: string + isOptional?: boolean children: React.JSX.Element } const Field: FC = ({ className, title, + isOptional, children, }) => { + const { t } = useTranslation() return (
-
{title}
+
+ {title} + {isOptional && ({t('appDebug.variableConfig.optional')})} +
{children}
) 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 70ce802841..9f3944f3d4 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 @@ -22,6 +22,9 @@ import { DEFAULT_VALUE_MAX_LEN } from '@/config' import type { Item as SelectItem } from './type-select' import TypeSelector from './type-select' import { SimpleSelect } from '@/app/components/base/select' +import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' +import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' +import { jsonConfigPlaceHolder } from './config' const TEXT_MAX_LENGTH = 256 @@ -110,6 +113,10 @@ const ConfigModal: FC = ({ value: InputVarType.multiFiles, }, ] : []), + { + name: t('appDebug.variableConfig.json'), + value: InputVarType.jsonObject, + }, ] const handleTypeChange = useCallback((item: SelectItem) => { @@ -285,6 +292,21 @@ const ConfigModal: FC = ({ /> )} + {type === InputVarType.jsonObject && ( + + handlePayloadChange('json_schema')(value)} + noWrapper + className='bg h-[80px] overflow-y-auto rounded-[10px] bg-components-input-bg-normal p-1' + placeholder={ +
{jsonConfigPlaceHolder}
+ } + /> +
+ )} +
handlePayloadChange('required')(!tempPayload.required)} /> {t('appDebug.variableConfig.required')} 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 index 01bd09ea44..3f6a01ed7c 100644 --- 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 @@ -2,7 +2,6 @@ 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, @@ -36,7 +35,6 @@ const TypeSelector: FC = ({ popupInnerClassName, readonly, }) => { - const { t } = useTranslation() const [open, setOpen] = useState(false) const selectedItem = value ? items.find(item => item.value === value) : undefined 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 c821cd5306..d1b7b84dea 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, RiCheckboxLine, RiCheckboxMultipleLine, RiFileCopy2Line, RiFileList2Line, RiHashtag, RiTextSnippet } from '@remixicon/react' +import { RiAlignLeft, RiBracesLine, RiCheckboxLine, RiCheckboxMultipleLine, RiFileCopy2Line, RiFileList2Line, RiHashtag, RiTextSnippet } from '@remixicon/react' import { InputVarType } from '../../../types' type Props = { @@ -16,6 +16,7 @@ const getIcon = (type: InputVarType) => { [InputVarType.select]: RiCheckboxMultipleLine, [InputVarType.number]: RiHashtag, [InputVarType.checkbox]: RiCheckboxLine, + [InputVarType.jsonObject]: RiBracesLine, [InputVarType.singleFile]: RiFileList2Line, [InputVarType.multiFiles]: RiFileCopy2Line, } as any)[type] || RiTextSnippet diff --git a/web/app/components/workflow/nodes/_base/components/variable/utils.ts b/web/app/components/workflow/nodes/_base/components/variable/utils.ts index 1054caba6c..e5c17f6c5c 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/utils.ts +++ b/web/app/components/workflow/nodes/_base/components/variable/utils.ts @@ -62,6 +62,7 @@ export const inputVarTypeToVarType = (type: InputVarType): VarType => { [InputVarType.checkbox]: VarType.boolean, [InputVarType.singleFile]: VarType.file, [InputVarType.multiFiles]: VarType.arrayFile, + [InputVarType.jsonObject]: VarType.object, } as any)[type] || VarType.string } diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index 8b17cd9670..5cad042cf6 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -184,6 +184,7 @@ export enum InputVarType { url = 'url', files = 'files', json = 'json', // obj, array + jsonObject = 'json_object', // only object support define json schema contexts = 'contexts', // knowledge retrieval iterator = 'iterator', // iteration input singleFile = 'file', @@ -209,6 +210,7 @@ export type InputVar = { getVarValueFromDependent?: boolean hide?: boolean isFileItem?: boolean + json_schema?: string // for jsonObject type } & Partial export type ModelConfig = { diff --git a/web/i18n/en-US/app-debug.ts b/web/i18n/en-US/app-debug.ts index 049a9f8dac..0c17ca6fb9 100644 --- a/web/i18n/en-US/app-debug.ts +++ b/web/i18n/en-US/app-debug.ts @@ -375,6 +375,9 @@ const translation = { 'select': 'Select', 'number': 'Number', 'checkbox': 'Checkbox', + 'json': 'JSON Code', + 'jsonSchema': 'JSON Schema', + 'optional': 'optional', '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 d1202b9b26..bb64f41bf1 100644 --- a/web/i18n/zh-Hans/app-debug.ts +++ b/web/i18n/zh-Hans/app-debug.ts @@ -375,6 +375,9 @@ const translation = { 'checkbox': '复选框', 'single-file': '单文件', 'multi-files': '文件列表', + 'json': 'JSON', + 'jsonSchema': 'JSON Schema', + 'optional': '可选', 'notSet': '未设置,在 Prompt 中输入 {{input}} 试试', 'stringTitle': '文本框设置', 'maxLength': '最大长度',