feat: support bool type variable frontend (#24437)
Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com>
This commit is contained in:
@@ -23,6 +23,7 @@ import SuggestedQuestions from '@/app/components/base/chat/chat/answer/suggested
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import cn from '@/utils/classnames'
|
||||
import type { FileEntity } from '../../file-uploader/types'
|
||||
import { formatBooleanInputs } from '@/utils/model-config'
|
||||
import Avatar from '../../avatar'
|
||||
|
||||
const ChatWrapper = () => {
|
||||
@@ -89,7 +90,7 @@ const ChatWrapper = () => {
|
||||
|
||||
let hasEmptyInput = ''
|
||||
let fileIsUploading = false
|
||||
const requiredVars = inputsForms.filter(({ required }) => required)
|
||||
const requiredVars = inputsForms.filter(({ required, type }) => required && type !== InputVarType.checkbox)
|
||||
if (requiredVars.length) {
|
||||
requiredVars.forEach(({ variable, label, type }) => {
|
||||
if (hasEmptyInput)
|
||||
@@ -131,7 +132,7 @@ const ChatWrapper = () => {
|
||||
const data: any = {
|
||||
query: message,
|
||||
files,
|
||||
inputs: currentConversationId ? currentConversationInputs : newConversationInputs,
|
||||
inputs: formatBooleanInputs(inputsForms, currentConversationId ? currentConversationInputs : newConversationInputs),
|
||||
conversation_id: currentConversationId,
|
||||
parent_message_id: (isRegenerate ? parentAnswer?.id : getLastAnswer(chatList)?.id) || null,
|
||||
}
|
||||
|
@@ -222,6 +222,14 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
type: 'number',
|
||||
}
|
||||
}
|
||||
|
||||
if(item.checkbox) {
|
||||
return {
|
||||
...item.checkbox,
|
||||
default: false,
|
||||
type: 'checkbox',
|
||||
}
|
||||
}
|
||||
if (item.select) {
|
||||
const isInputInOptions = item.select.options.includes(initInputs[item.select.variable])
|
||||
return {
|
||||
@@ -245,6 +253,13 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (item.json_object) {
|
||||
return {
|
||||
...item.json_object,
|
||||
type: 'json_object',
|
||||
}
|
||||
}
|
||||
|
||||
let value = initInputs[item['text-input'].variable]
|
||||
if (value && item['text-input'].max_length && value.length > item['text-input'].max_length)
|
||||
value = value.slice(0, item['text-input'].max_length)
|
||||
@@ -340,7 +355,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
|
||||
let hasEmptyInput = ''
|
||||
let fileIsUploading = false
|
||||
const requiredVars = inputsForms.filter(({ required }) => required)
|
||||
const requiredVars = inputsForms.filter(({ required, type }) => required && type !== InputVarType.checkbox)
|
||||
if (requiredVars.length) {
|
||||
requiredVars.forEach(({ variable, label, type }) => {
|
||||
if (hasEmptyInput)
|
||||
|
@@ -6,6 +6,9 @@ import Textarea from '@/app/components/base/textarea'
|
||||
import { PortalSelect } from '@/app/components/base/select'
|
||||
import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
|
||||
import { InputVarType } from '@/app/components/workflow/types'
|
||||
import BoolInput from '@/app/components/workflow/nodes/_base/components/before-run-form/bool-input'
|
||||
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
|
||||
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
|
||||
|
||||
type Props = {
|
||||
showTip?: boolean
|
||||
@@ -42,12 +45,14 @@ const InputsFormContent = ({ showTip }: Props) => {
|
||||
<div className='space-y-4'>
|
||||
{visibleInputsForms.map(form => (
|
||||
<div key={form.variable} className='space-y-1'>
|
||||
<div className='flex h-6 items-center gap-1'>
|
||||
<div className='system-md-semibold text-text-secondary'>{form.label}</div>
|
||||
{!form.required && (
|
||||
<div className='system-xs-regular text-text-tertiary'>{t('appDebug.variableTable.optional')}</div>
|
||||
)}
|
||||
</div>
|
||||
{form.type !== InputVarType.checkbox && (
|
||||
<div className='flex h-6 items-center gap-1'>
|
||||
<div className='system-md-semibold text-text-secondary'>{form.label}</div>
|
||||
{!form.required && (
|
||||
<div className='system-xs-regular text-text-tertiary'>{t('appDebug.variableTable.optional')}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{form.type === InputVarType.textInput && (
|
||||
<Input
|
||||
value={inputsFormValue?.[form.variable] || ''}
|
||||
@@ -70,6 +75,14 @@ const InputsFormContent = ({ showTip }: Props) => {
|
||||
placeholder={form.label}
|
||||
/>
|
||||
)}
|
||||
{form.type === InputVarType.checkbox && (
|
||||
<BoolInput
|
||||
name={form.label}
|
||||
value={!!inputsFormValue?.[form.variable]}
|
||||
required={form.required}
|
||||
onChange={value => handleFormChange(form.variable, value)}
|
||||
/>
|
||||
)}
|
||||
{form.type === InputVarType.select && (
|
||||
<PortalSelect
|
||||
popupClassName='w-[200px]'
|
||||
@@ -105,6 +118,18 @@ const InputsFormContent = ({ showTip }: Props) => {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{form.type === InputVarType.jsonObject && (
|
||||
<CodeEditor
|
||||
language={CodeLanguage.json}
|
||||
value={inputsFormValue?.[form.variable] || ''}
|
||||
onChange={v => handleFormChange(form.variable, v)}
|
||||
noWrapper
|
||||
className='bg h-[80px] overflow-y-auto rounded-[10px] bg-components-input-bg-normal p-1'
|
||||
placeholder={
|
||||
<div className='whitespace-pre'>{form.json_schema}</div>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{showTip && (
|
||||
|
@@ -12,7 +12,7 @@ export const useCheckInputsForms = () => {
|
||||
const checkInputsForm = useCallback((inputs: Record<string, any>, inputsForm: InputForm[]) => {
|
||||
let hasEmptyInput = ''
|
||||
let fileIsUploading = false
|
||||
const requiredVars = inputsForm.filter(({ required }) => required)
|
||||
const requiredVars = inputsForm.filter(({ required, type }) => required && type !== InputVarType.checkbox) // boolean can be not checked
|
||||
|
||||
if (requiredVars?.length) {
|
||||
requiredVars.forEach(({ variable, label, type }) => {
|
||||
|
@@ -31,6 +31,12 @@ export const getProcessedInputs = (inputs: Record<string, any>, inputsForm: Inpu
|
||||
|
||||
inputsForm.forEach((item) => {
|
||||
const inputValue = inputs[item.variable]
|
||||
// set boolean type default value
|
||||
if(item.type === InputVarType.checkbox) {
|
||||
processedInputs[item.variable] = !!inputValue
|
||||
return
|
||||
}
|
||||
|
||||
if (!inputValue)
|
||||
return
|
||||
|
||||
|
@@ -90,7 +90,7 @@ const ChatWrapper = () => {
|
||||
|
||||
let hasEmptyInput = ''
|
||||
let fileIsUploading = false
|
||||
const requiredVars = inputsForms.filter(({ required }) => required)
|
||||
const requiredVars = inputsForms.filter(({ required, type }) => required && type !== InputVarType.checkbox) // boolean can be not checked
|
||||
if (requiredVars.length) {
|
||||
requiredVars.forEach(({ variable, label, type }) => {
|
||||
if (hasEmptyInput)
|
||||
|
@@ -195,6 +195,13 @@ export const useEmbeddedChatbot = () => {
|
||||
type: 'number',
|
||||
}
|
||||
}
|
||||
if (item.checkbox) {
|
||||
return {
|
||||
...item.checkbox,
|
||||
default: false,
|
||||
type: 'checkbox',
|
||||
}
|
||||
}
|
||||
if (item.select) {
|
||||
const isInputInOptions = item.select.options.includes(initInputs[item.select.variable])
|
||||
return {
|
||||
@@ -218,6 +225,13 @@ export const useEmbeddedChatbot = () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (item.json_object) {
|
||||
return {
|
||||
...item.json_object,
|
||||
type: 'json_object',
|
||||
}
|
||||
}
|
||||
|
||||
let value = initInputs[item['text-input'].variable]
|
||||
if (value && item['text-input'].max_length && value.length > item['text-input'].max_length)
|
||||
value = value.slice(0, item['text-input'].max_length)
|
||||
@@ -312,7 +326,7 @@ export const useEmbeddedChatbot = () => {
|
||||
|
||||
let hasEmptyInput = ''
|
||||
let fileIsUploading = false
|
||||
const requiredVars = inputsForms.filter(({ required }) => required)
|
||||
const requiredVars = inputsForms.filter(({ required, type }) => required && type !== InputVarType.checkbox)
|
||||
if (requiredVars.length) {
|
||||
requiredVars.forEach(({ variable, label, type }) => {
|
||||
if (hasEmptyInput)
|
||||
|
@@ -6,6 +6,9 @@ import Textarea from '@/app/components/base/textarea'
|
||||
import { PortalSelect } from '@/app/components/base/select'
|
||||
import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
|
||||
import { InputVarType } from '@/app/components/workflow/types'
|
||||
import BoolInput from '@/app/components/workflow/nodes/_base/components/before-run-form/bool-input'
|
||||
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
|
||||
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
|
||||
|
||||
type Props = {
|
||||
showTip?: boolean
|
||||
@@ -42,12 +45,14 @@ const InputsFormContent = ({ showTip }: Props) => {
|
||||
<div className='space-y-4'>
|
||||
{visibleInputsForms.map(form => (
|
||||
<div key={form.variable} className='space-y-1'>
|
||||
{form.type !== InputVarType.checkbox && (
|
||||
<div className='flex h-6 items-center gap-1'>
|
||||
<div className='system-md-semibold text-text-secondary'>{form.label}</div>
|
||||
{!form.required && (
|
||||
<div className='system-xs-regular text-text-tertiary'>{t('appDebug.variableTable.optional')}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{form.type === InputVarType.textInput && (
|
||||
<Input
|
||||
value={inputsFormValue?.[form.variable] || ''}
|
||||
@@ -70,6 +75,14 @@ const InputsFormContent = ({ showTip }: Props) => {
|
||||
placeholder={form.label}
|
||||
/>
|
||||
)}
|
||||
{form.type === InputVarType.checkbox && (
|
||||
<BoolInput
|
||||
name={form.label}
|
||||
value={inputsFormValue?.[form.variable]}
|
||||
required={form.required}
|
||||
onChange={value => handleFormChange(form.variable, value)}
|
||||
/>
|
||||
)}
|
||||
{form.type === InputVarType.select && (
|
||||
<PortalSelect
|
||||
popupClassName='w-[200px]'
|
||||
@@ -105,6 +118,18 @@ const InputsFormContent = ({ showTip }: Props) => {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{form.type === InputVarType.jsonObject && (
|
||||
<CodeEditor
|
||||
language={CodeLanguage.json}
|
||||
value={inputsFormValue?.[form.variable] || ''}
|
||||
onChange={v => handleFormChange(form.variable, v)}
|
||||
noWrapper
|
||||
className='bg h-[80px] overflow-y-auto rounded-[10px] bg-components-input-bg-normal p-1'
|
||||
placeholder={
|
||||
<div className='whitespace-pre'>{form.json_schema}</div>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{showTip && (
|
||||
|
@@ -24,7 +24,7 @@ export enum FormTypeEnum {
|
||||
secretInput = 'secret-input',
|
||||
select = 'select',
|
||||
radio = 'radio',
|
||||
boolean = 'boolean',
|
||||
checkbox = 'checkbox',
|
||||
files = 'files',
|
||||
file = 'file',
|
||||
modelSelector = 'model-selector',
|
||||
|
@@ -53,7 +53,6 @@ const CurrentBlockReplacementBlock = ({
|
||||
return mergeRegister(
|
||||
editor.registerNodeTransform(CustomTextNode, textNode => decoratorTransform(textNode, getMatch, createCurrentBlockNode)),
|
||||
)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
return null
|
||||
|
@@ -52,7 +52,6 @@ const ErrorMessageBlockReplacementBlock = ({
|
||||
return mergeRegister(
|
||||
editor.registerNodeTransform(CustomTextNode, textNode => decoratorTransform(textNode, getMatch, createErrorMessageBlockNode)),
|
||||
)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
return null
|
||||
|
@@ -52,7 +52,6 @@ const LastRunReplacementBlock = ({
|
||||
return mergeRegister(
|
||||
editor.registerNodeTransform(CustomTextNode, textNode => decoratorTransform(textNode, getMatch, createLastRunBlockNode)),
|
||||
)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
return null
|
||||
|
Reference in New Issue
Block a user