From bd1073ff1a158d1731e7a5624a359cdb754c0bbc Mon Sep 17 00:00:00 2001 From: twwu Date: Mon, 19 May 2025 16:26:13 +0800 Subject: [PATCH] refactor: update input variable types to use PipelineInputVarType and simplify form data handling --- .../input-field/editor/form/hidden-fields.tsx | 11 ++- .../input-field/editor/form/hooks.ts | 76 +++++++++---------- .../input-field/editor/form/index.tsx | 4 +- .../editor/form/initial-fields.tsx | 14 ++-- .../input-field/editor/form/schema.ts | 16 ++-- .../editor/form/show-all-settings.tsx | 3 +- .../input-field/editor/form/types.ts | 11 +-- .../components/input-field/editor/index.tsx | 35 ++++++++- .../components/input-field/editor/utils.ts | 18 +++-- .../input-field/field-list/field-item.tsx | 7 +- .../input-field/field-list/index.tsx | 10 ++- .../components/input-field/index.tsx | 50 +++++++----- .../components/rag-pipeline/store/index.ts | 32 +------- web/config/index.ts | 10 +++ web/models/pipeline.ts | 48 +++++++----- 15 files changed, 194 insertions(+), 151 deletions(-) diff --git a/web/app/components/rag-pipeline/components/input-field/editor/form/hidden-fields.tsx b/web/app/components/rag-pipeline/components/input-field/editor/form/hidden-fields.tsx index 6a9c04a154..f95ca7b4dd 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/form/hidden-fields.tsx +++ b/web/app/components/rag-pipeline/components/input-field/editor/form/hidden-fields.tsx @@ -1,12 +1,11 @@ import React from 'react' import { withForm } from '@/app/components/base/form' -import type { FormData } from './types' import InputField from '@/app/components/base/form/form-scenarios/input-field/field' import { useStore } from '@tanstack/react-form' import { useHiddenConfigurations } from './hooks' type HiddenFieldsProps = { - initialData?: FormData + initialData?: Record } const HiddenFields = ({ @@ -25,10 +24,10 @@ const HiddenFields = ({ return ( <> {hiddenConfigurations.map((config, index) => { - const FieldComponent = InputField({ - initialData, - config, - }) + const FieldComponent = InputField({ + initialData, + config, + }) return })} diff --git a/web/app/components/rag-pipeline/components/input-field/editor/form/hooks.ts b/web/app/components/rag-pipeline/components/input-field/editor/form/hooks.ts index 13e0537b03..3a43c2e030 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/form/hooks.ts +++ b/web/app/components/rag-pipeline/components/input-field/editor/form/hooks.ts @@ -1,5 +1,4 @@ import { useTranslation } from 'react-i18next' -import { InputVarType } from '@/app/components/workflow/types' import { useCallback, useMemo } from 'react' import type { InputFieldConfiguration } from '@/app/components/base/form/form-scenarios/input-field/types' import { InputFieldType } from '@/app/components/base/form/form-scenarios/input-field/types' @@ -11,21 +10,22 @@ import { DEFAULT_FILE_UPLOAD_SETTING } from '@/app/components/workflow/constants import { DEFAULT_VALUE_MAX_LEN } from '@/config' import type { FormData } from './types' import { TEXT_MAX_LENGTH } from './schema' +import { PipelineInputVarType } from '@/models/pipeline' -export const useHiddenFieldNames = (type: InputVarType) => { +export const useHiddenFieldNames = (type: PipelineInputVarType) => { const { t } = useTranslation() const hiddenFieldNames = useMemo(() => { let fieldNames = [] switch (type) { - case InputVarType.textInput: - case InputVarType.paragraph: + case PipelineInputVarType.textInput: + case PipelineInputVarType.paragraph: fieldNames = [ t('appDebug.variableConfig.defaultValue'), t('appDebug.variableConfig.placeholder'), t('appDebug.variableConfig.tooltips'), ] break - case InputVarType.number: + case PipelineInputVarType.number: fieldNames = [ t('appDebug.variableConfig.defaultValue'), t('appDebug.variableConfig.unit'), @@ -33,19 +33,19 @@ export const useHiddenFieldNames = (type: InputVarType) => { t('appDebug.variableConfig.tooltips'), ] break - case InputVarType.select: + case PipelineInputVarType.select: fieldNames = [ t('appDebug.variableConfig.defaultValue'), t('appDebug.variableConfig.tooltips'), ] break - case InputVarType.singleFile: + case PipelineInputVarType.singleFile: fieldNames = [ t('appDebug.variableConfig.uploadMethod'), t('appDebug.variableConfig.tooltips'), ] break - case InputVarType.multiFiles: + case PipelineInputVarType.multiFiles: fieldNames = [ t('appDebug.variableConfig.uploadMethod'), t('appDebug.variableConfig.maxNumberOfUploads'), @@ -71,20 +71,20 @@ export const useConfigurations = (props: { const { setFieldValue, supportFile } = props const handleTypeChange = useCallback((type: string) => { - if ([InputVarType.singleFile, InputVarType.multiFiles].includes(type as InputVarType)) { + if ([PipelineInputVarType.singleFile, PipelineInputVarType.multiFiles].includes(type as PipelineInputVarType)) { setFieldValue('allowedFileUploadMethods', DEFAULT_FILE_UPLOAD_SETTING.allowed_file_upload_methods) setFieldValue('allowedTypesAndExtensions', { allowedFileTypes: DEFAULT_FILE_UPLOAD_SETTING.allowed_file_types, allowedFileExtensions: DEFAULT_FILE_UPLOAD_SETTING.allowed_file_extensions, }) - if (type === InputVarType.multiFiles) + if (type === PipelineInputVarType.multiFiles) setFieldValue('maxLength', DEFAULT_FILE_UPLOAD_SETTING.max_length) } - if (type === InputVarType.paragraph) + if (type === PipelineInputVarType.paragraph) setFieldValue('maxLength', DEFAULT_VALUE_MAX_LEN) }, [setFieldValue]) - const initialConfigurations = useMemo((): InputFieldConfiguration[] => { + const initialConfigurations = useMemo((): InputFieldConfiguration[] => { return [{ type: InputFieldType.inputTypeSelect, label: t('appDebug.variableConfig.fieldType'), @@ -117,7 +117,7 @@ export const useConfigurations = (props: { required: true, showConditions: [{ variable: 'type', - value: InputVarType.textInput, + value: PipelineInputVarType.textInput, }], min: 1, max: TEXT_MAX_LENGTH, @@ -128,7 +128,7 @@ export const useConfigurations = (props: { required: true, showConditions: [{ variable: 'type', - value: InputVarType.select, + value: PipelineInputVarType.select, }], }, { type: InputFieldType.fileTypes, @@ -137,7 +137,7 @@ export const useConfigurations = (props: { required: true, showConditions: [{ variable: 'type', - value: InputVarType.singleFile, + value: PipelineInputVarType.singleFile, }], }, { type: InputFieldType.fileTypes, @@ -146,7 +146,7 @@ export const useConfigurations = (props: { required: true, showConditions: [{ variable: 'type', - value: InputVarType.multiFiles, + value: PipelineInputVarType.multiFiles, }], }, { type: InputFieldType.checkbox, @@ -157,7 +157,7 @@ export const useConfigurations = (props: { }] }, [handleTypeChange, supportFile, t]) - return initialConfigurations + return initialConfigurations } export const useHiddenConfigurations = (props: { @@ -192,7 +192,7 @@ export const useHiddenConfigurations = (props: { return [] }, [options, t]) - const hiddenConfigurations = useMemo((): InputFieldConfiguration[] => { + const hiddenConfigurations = useMemo((): InputFieldConfiguration[] => { return [{ type: InputFieldType.textInput, label: t('appDebug.variableConfig.defaultValue'), @@ -201,20 +201,20 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.textInput, + value: PipelineInputVarType.textInput, }], showOptional: true, }, { - type: InputFieldType.textInput, - label: t('appDebug.variableConfig.defaultValue'), - variable: 'default', - placeholder: t('appDebug.variableConfig.defaultValuePlaceholder'), - required: false, - showConditions: [{ - variable: 'type', - value: InputVarType.paragraph, - }], - showOptional: true, + type: InputFieldType.textInput, + label: t('appDebug.variableConfig.defaultValue'), + variable: 'default', + placeholder: t('appDebug.variableConfig.defaultValuePlaceholder'), + required: false, + showConditions: [{ + variable: 'type', + value: PipelineInputVarType.paragraph, + }], + showOptional: true, }, { type: InputFieldType.numberInput, label: t('appDebug.variableConfig.defaultValue'), @@ -223,7 +223,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.number, + value: PipelineInputVarType.number, }], showOptional: true, }, { @@ -233,7 +233,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.select, + value: PipelineInputVarType.select, }], showOptional: true, options: defaultSelectOptions, @@ -248,7 +248,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.textInput, + value: PipelineInputVarType.textInput, }], showOptional: true, }, { @@ -259,7 +259,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.paragraph, + value: PipelineInputVarType.paragraph, }], showOptional: true, }, { @@ -270,7 +270,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.number, + value: PipelineInputVarType.number, }], showOptional: true, }, { @@ -281,7 +281,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.number, + value: PipelineInputVarType.number, }], showOptional: true, }, { @@ -291,7 +291,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.singleFile, + value: PipelineInputVarType.singleFile, }], }, { type: InputFieldType.uploadMethod, @@ -300,7 +300,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.multiFiles, + value: PipelineInputVarType.multiFiles, }], }, { type: InputFieldType.numberSlider, @@ -309,7 +309,7 @@ export const useHiddenConfigurations = (props: { required: false, showConditions: [{ variable: 'type', - value: InputVarType.multiFiles, + value: PipelineInputVarType.multiFiles, }], description: t('appDebug.variableConfig.maxNumberTip', { imgLimit: formatFileSize(imgSizeLimit), diff --git a/web/app/components/rag-pipeline/components/input-field/editor/form/index.tsx b/web/app/components/rag-pipeline/components/input-field/editor/form/index.tsx index 7f18b6ee82..a26371a4e8 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/form/index.tsx +++ b/web/app/components/rag-pipeline/components/input-field/editor/form/index.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import { useCallback, useState } from 'react' import { ChangeType } from '@/app/components/workflow/types' import { useFileUploadConfig } from '@/service/use-common' -import type { InputFieldFormProps } from './types' +import type { FormData, InputFieldFormProps } from './types' import { useAppForm } from '@/app/components/base/form' import { createInputFieldSchema } from './schema' import Toast from '@/app/components/base/toast' @@ -53,7 +53,7 @@ const InputFieldForm = ({ type: ChangeType.changeVarName, payload: { beforeKey: initialData?.variable || '', afterKey: value.variable }, } - onSubmit(value, moreInfo) + onSubmit(value as FormData, moreInfo) }, }) diff --git a/web/app/components/rag-pipeline/components/input-field/editor/form/initial-fields.tsx b/web/app/components/rag-pipeline/components/input-field/editor/form/initial-fields.tsx index 85181188af..c00708ed6e 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/form/initial-fields.tsx +++ b/web/app/components/rag-pipeline/components/input-field/editor/form/initial-fields.tsx @@ -1,12 +1,10 @@ import React, { useCallback } from 'react' import { withForm } from '@/app/components/base/form' -import type { FormData } from './types' import InputField from '@/app/components/base/form/form-scenarios/input-field/field' -import type { DeepKeys } from '@tanstack/react-form' import { useConfigurations } from './hooks' type InitialFieldsProps = { - initialData?: FormData + initialData?: Record supportFile: boolean } @@ -18,7 +16,7 @@ const InitialFields = ({ render: function Render({ form, }) { - const setFieldValue = useCallback((fieldName: DeepKeys, value: any) => { + const setFieldValue = useCallback((fieldName: string, value: any) => { form.setFieldValue(fieldName, value) }, [form]) @@ -30,10 +28,10 @@ const InitialFields = ({ return ( <> {initialConfigurations.map((config, index) => { - const FieldComponent = InputField({ - initialData, - config, - }) + const FieldComponent = InputField({ + initialData, + config, + }) return })} diff --git a/web/app/components/rag-pipeline/components/input-field/editor/form/schema.ts b/web/app/components/rag-pipeline/components/input-field/editor/form/schema.ts index 217134c42b..c816c007ed 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/form/schema.ts +++ b/web/app/components/rag-pipeline/components/input-field/editor/form/schema.ts @@ -1,8 +1,8 @@ -import { InputVarType } from '@/app/components/workflow/types' import { MAX_VAR_KEY_LENGTH } from '@/config' import type { TFunction } from 'i18next' import { z } from 'zod' import type { SchemaOptions } from './types' +import { PipelineInputVarType } from '@/models/pipeline' export const TEXT_MAX_LENGTH = 256 @@ -30,7 +30,7 @@ export const SupportedFileTypes = z.enum([ 'custom', ]) -export const createInputFieldSchema = (type: InputVarType, t: TFunction, options: SchemaOptions) => { +export const createInputFieldSchema = (type: PipelineInputVarType, t: TFunction, options: SchemaOptions) => { const { maxFileUploadLimit } = options const commonSchema = z.object({ type: InputType, @@ -47,22 +47,22 @@ export const createInputFieldSchema = (type: InputVarType, t: TFunction, options message: t('appDebug.variableConfig.errorMsg.labelNameRequired'), }), required: z.boolean(), - hint: z.string().optional(), + tooltips: z.string().optional(), }) - if (type === InputVarType.textInput || type === InputVarType.paragraph) { + if (type === PipelineInputVarType.textInput || type === PipelineInputVarType.paragraph) { return z.object({ maxLength: z.number().min(1).max(TEXT_MAX_LENGTH), default: z.string().optional(), }).merge(commonSchema).passthrough() } - if (type === InputVarType.number) { + if (type === PipelineInputVarType.number) { return z.object({ default: z.number().optional(), unit: z.string().optional(), placeholder: z.string().optional(), }).merge(commonSchema).passthrough() } - if (type === InputVarType.select) { + if (type === PipelineInputVarType.select) { return z.object({ options: z.array(z.string()).nonempty({ message: t('appDebug.variableConfig.errorMsg.atLeastOneOption'), @@ -75,7 +75,7 @@ export const createInputFieldSchema = (type: InputVarType, t: TFunction, options default: z.string().optional(), }).merge(commonSchema).passthrough() } - if (type === InputVarType.singleFile) { + if (type === PipelineInputVarType.singleFile) { return z.object({ allowedFileUploadMethods: z.array(TransferMethod), allowedTypesAndExtensions: z.object({ @@ -84,7 +84,7 @@ export const createInputFieldSchema = (type: InputVarType, t: TFunction, options }), }).merge(commonSchema).passthrough() } - if (type === InputVarType.multiFiles) { + if (type === PipelineInputVarType.multiFiles) { return z.object({ allowedFileUploadMethods: z.array(TransferMethod), allowedTypesAndExtensions: z.object({ diff --git a/web/app/components/rag-pipeline/components/input-field/editor/form/show-all-settings.tsx b/web/app/components/rag-pipeline/components/input-field/editor/form/show-all-settings.tsx index 752f694a73..2c66fcbcca 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/form/show-all-settings.tsx +++ b/web/app/components/rag-pipeline/components/input-field/editor/form/show-all-settings.tsx @@ -1,13 +1,12 @@ import React from 'react' import { withForm } from '@/app/components/base/form' -import type { FormData } from './types' import { useStore } from '@tanstack/react-form' import { useHiddenFieldNames } from './hooks' import { useTranslation } from 'react-i18next' import { RiArrowRightSLine } from '@remixicon/react' type ShowAllSettingsProps = { - initialData?: FormData + initialData?: Record handleShowAllSettings: () => void } diff --git a/web/app/components/rag-pipeline/components/input-field/editor/form/types.ts b/web/app/components/rag-pipeline/components/input-field/editor/form/types.ts index 602a9f3e0e..8692e56813 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/form/types.ts +++ b/web/app/components/rag-pipeline/components/input-field/editor/form/types.ts @@ -1,14 +1,15 @@ -import type { InputVarType, MoreInfo, SupportUploadFileTypes } from '@/app/components/workflow/types' +import type { MoreInfo, SupportUploadFileTypes } from '@/app/components/workflow/types' +import type { PipelineInputVarType } from '@/models/pipeline' import type { TransferMethod } from '@/types/app' export type FormData = { - type: InputVarType + type: PipelineInputVarType label: string variable: string maxLength?: number - default?: string | number + default?: string required: boolean - hint?: string + tooltips?: string options?: string[] placeholder?: string unit?: string @@ -20,7 +21,7 @@ export type FormData = { } export type InputFieldFormProps = { - initialData: FormData + initialData: Record supportFile?: boolean onCancel: () => void onSubmit: (value: FormData, moreInfo?: MoreInfo) => void diff --git a/web/app/components/rag-pipeline/components/input-field/editor/index.tsx b/web/app/components/rag-pipeline/components/input-field/editor/index.tsx index c7b473c478..c6b5bd131a 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/index.tsx +++ b/web/app/components/rag-pipeline/components/input-field/editor/index.tsx @@ -1,10 +1,11 @@ import { RiCloseLine } from '@remixicon/react' import DialogWrapper from '../dialog-wrapper' -import type { InputVar } from '@/app/components/workflow/types' import InputFieldForm from './form' import { convertToInputFieldFormData } from './utils' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' +import type { InputVar } from '@/models/pipeline' +import type { FormData } from './form/types' type InputFieldEditorProps = { show: boolean @@ -22,8 +23,36 @@ const InputFieldEditor = ({ const { t } = useTranslation() const formData = convertToInputFieldFormData(initialData) - const handleSubmit = useCallback((value: InputVar) => { - onSubmit(value) + const handleSubmit = useCallback((value: FormData) => { + const { + type, + label, + variable, + maxLength, + required, + tooltips, + options, + placeholder, + unit, + default: defaultValue, + allowedFileUploadMethods, + allowedTypesAndExtensions, + } = value + onSubmit({ + type, + label, + variable, + max_length: maxLength, + required, + tooltips, + options, + placeholder, + unit, + default: defaultValue, + allowed_file_upload_methods: allowedFileUploadMethods, + allowed_file_types: allowedTypesAndExtensions.allowedFileTypes, + allowed_file_extensions: allowedTypesAndExtensions.allowedFileExtensions, + }) onClose() }, [onSubmit, onClose]) diff --git a/web/app/components/rag-pipeline/components/input-field/editor/utils.ts b/web/app/components/rag-pipeline/components/input-field/editor/utils.ts index ab85c9c8b5..655626550a 100644 --- a/web/app/components/rag-pipeline/components/input-field/editor/utils.ts +++ b/web/app/components/rag-pipeline/components/input-field/editor/utils.ts @@ -1,6 +1,12 @@ -import type { InputVar } from '@/app/components/workflow/types' +import type { InputVar } from '@/models/pipeline' import type { FormData } from './form/types' -import { getNewVarInWorkflow } from '@/utils/var' +import { VAR_ITEM_TEMPLATE_IN_PIPELINE } from '@/config' + +const getNewInputVarInRagPipeline = (): InputVar => { + return { + ...VAR_ITEM_TEMPLATE_IN_PIPELINE, + } +} export const convertToInputFieldFormData = (data?: InputVar): FormData => { const { @@ -10,23 +16,23 @@ export const convertToInputFieldFormData = (data?: InputVar): FormData => { max_length, 'default': defaultValue, required, - hint, + tooltips, options, placeholder, unit, allowed_file_upload_methods, allowed_file_types, allowed_file_extensions, - } = data || getNewVarInWorkflow('') + } = data || getNewInputVarInRagPipeline() return { type, - label: label as string, + label, variable, maxLength: max_length, default: defaultValue, required, - hint, + tooltips, options, placeholder, unit, diff --git a/web/app/components/rag-pipeline/components/input-field/field-list/field-item.tsx b/web/app/components/rag-pipeline/components/input-field/field-list/field-item.tsx index 0c3dfa910e..9de9341c77 100644 --- a/web/app/components/rag-pipeline/components/input-field/field-list/field-item.tsx +++ b/web/app/components/rag-pipeline/components/input-field/field-list/field-item.tsx @@ -7,11 +7,12 @@ import { RiDraggable, RiEditLine, } from '@remixicon/react' -import type { InputVar } from '@/app/components/workflow/types' import { InputField } from '@/app/components/base/icons/src/vender/pipeline' import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon' import cn from '@/utils/classnames' import Badge from '@/app/components/base/badge' +import type { InputVar } from '@/models/pipeline' +import type { InputVarType } from '@/app/components/workflow/types' type FieldItemProps = { readonly?: boolean @@ -33,7 +34,7 @@ const FieldItem = ({ return (
{t('workflow.nodes.start.required')} )} - +
) : (!readonly && ( diff --git a/web/app/components/rag-pipeline/components/input-field/field-list/index.tsx b/web/app/components/rag-pipeline/components/input-field/field-list/index.tsx index 1c8e61e320..a2cd88c571 100644 --- a/web/app/components/rag-pipeline/components/input-field/field-list/index.tsx +++ b/web/app/components/rag-pipeline/components/input-field/field-list/index.tsx @@ -1,4 +1,3 @@ -import type { InputVar } from '@/app/components/workflow/types' import { RiAddLine } from '@remixicon/react' import FieldItem from './field-item' import cn from '@/utils/classnames' @@ -6,6 +5,7 @@ import { useCallback, useMemo, useState } from 'react' import InputFieldEditor from '../editor' import { ReactSortable } from 'react-sortablejs' import produce from 'immer' +import type { InputVar } from '@/models/pipeline' type FieldListProps = { LabelRightContent: React.ReactNode @@ -48,7 +48,7 @@ const FieldList = ({ }, [handleInputFieldsChange, inputFields]) const handleAddField = () => { - setCurrentIndex(-1) + setCurrentIndex(-1) // -1 means add new field setCurrentInputField(undefined) setShowInputFieldEditor(true) } @@ -61,6 +61,10 @@ const FieldList = ({ const handleSubmitChange = useCallback((data: InputVar) => { const newInputFields = produce(inputFields, (draft) => { + if (currentIndex === -1) { + draft.push(data) + return + } draft[currentIndex] = data }) handleInputFieldsChange(newInputFields) @@ -91,7 +95,7 @@ const FieldList = ({ list={optionList} setList={list => handleListSortChange(list)} handle='.handle' - ghostClass="opacity-50" + ghostClass='opacity-50' animation={150} disabled={readonly} > diff --git a/web/app/components/rag-pipeline/components/input-field/index.tsx b/web/app/components/rag-pipeline/components/input-field/index.tsx index bd8b0fbba7..baec8c9aa0 100644 --- a/web/app/components/rag-pipeline/components/input-field/index.tsx +++ b/web/app/components/rag-pipeline/components/input-field/index.tsx @@ -5,7 +5,7 @@ import { } from 'react' import { useStore } from '@/app/components/workflow/store' import { RiCloseLine } from '@remixicon/react' -import { BlockEnum, type InputVar } from '@/app/components/workflow/types' +import { BlockEnum } from '@/app/components/workflow/types' import DialogWrapper from './dialog-wrapper' import FieldList from './field-list' import FooterTip from './footer-tip' @@ -15,6 +15,8 @@ import { useNodes } from 'reactflow' import type { DataSourceNodeType } from '@/app/components/workflow/nodes/data-source/types' import { useTranslation } from 'react-i18next' import produce from 'immer' +import { useNodesSyncDraft } from '../../hooks' +import type { InputVar, RAGPipelineVariables } from '@/models/pipeline' type InputFieldDialogProps = { readonly?: boolean @@ -29,6 +31,7 @@ const InputFieldDialog = ({ const setShowInputFieldDialog = useStore(state => state.setShowInputFieldDialog) const ragPipelineVariables = useStore(state => state.ragPipelineVariables) const setRagPipelineVariables = useStore(state => state.setRagPipelineVariables) + const { doSyncWorkflowDraft } = useNodesSyncDraft() const datasourceTitleMap = useMemo(() => { const datasourceNameMap: Record = {} @@ -44,11 +47,11 @@ const InputFieldDialog = ({ const inputFieldsMap = useMemo(() => { const inputFieldsMap: Record = {} ragPipelineVariables?.forEach((variable) => { - const { nodeId, variables } = variable - if (nodeId) - inputFieldsMap[nodeId] = variables + const { belong_to_node_id: nodeId, ...varConfig } = variable + if (inputFieldsMap[nodeId]) + inputFieldsMap[nodeId].push(varConfig) else - inputFieldsMap.shared = variables + inputFieldsMap[nodeId] = [varConfig] }) return inputFieldsMap }, [ragPipelineVariables]) @@ -57,13 +60,23 @@ const InputFieldDialog = ({ return Object.keys(inputFieldsMap).filter(key => key !== 'shared') }, [inputFieldsMap]) - const updateInputFields = useCallback((key: string, value: InputVar[]) => { - const newRagPipelineVariables = produce(ragPipelineVariables!, (draft) => { - const index = draft.findIndex(variable => variable.nodeId === key) - draft[index].variables = value + const updateInputFields = useCallback(async (key: string, value: InputVar[]) => { + const NewInputFieldsMap = produce(inputFieldsMap, (draft) => { + draft[key] = value + }) + const newRagPipelineVariables: RAGPipelineVariables = [] + Object.keys(NewInputFieldsMap).forEach((key) => { + const inputFields = NewInputFieldsMap[key] + inputFields.forEach((inputField) => { + newRagPipelineVariables.push({ + ...inputField, + belong_to_node_id: key, + }) + }) }) setRagPipelineVariables?.(newRagPipelineVariables) - }, [ragPipelineVariables, setRagPipelineVariables]) + await doSyncWorkflowDraft() + }, [doSyncWorkflowDraft, inputFieldsMap, setRagPipelineVariables]) const closePanel = useCallback(() => { setShowInputFieldDialog?.(false) @@ -99,6 +112,7 @@ const InputFieldDialog = ({ return null return ( } inputFields={inputFields} readonly={readonly} @@ -109,15 +123,13 @@ const InputFieldDialog = ({ }) } {/* Shared Inputs */} - {inputFieldsMap.shared?.length > 0 && ( - } - inputFields={inputFieldsMap.shared} - readonly={readonly} - labelClassName='pt-1 pb-2' - handleInputFieldsChange={updateInputFields.bind(null, '')} - /> - )} + } + inputFields={inputFieldsMap.shared || []} + readonly={readonly} + labelClassName='pt-1 pb-2' + handleInputFieldsChange={updateInputFields.bind(null, 'shared')} + /> diff --git a/web/app/components/rag-pipeline/store/index.ts b/web/app/components/rag-pipeline/store/index.ts index 769d7f69f2..857c60529f 100644 --- a/web/app/components/rag-pipeline/store/index.ts +++ b/web/app/components/rag-pipeline/store/index.ts @@ -1,6 +1,5 @@ import type { RAGPipelineVariables } from '@/models/pipeline' import type { StateCreator } from 'zustand' -import { InputVarType } from '../../workflow/types' export type RagPipelineSliceShape = { pipelineId: string @@ -19,35 +18,6 @@ export const createRagPipelineSliceSlice: StateCreator = setShowInputFieldDialog: showInputFieldDialog => set(() => ({ showInputFieldDialog })), nodesDefaultConfigs: {}, setNodesDefaultConfigs: nodesDefaultConfigs => set(() => ({ nodesDefaultConfigs })), - ragPipelineVariables: [{ - // TODO: delete mock data - nodeId: '123', - variables: [{ - variable: 'name', - label: 'name', - type: InputVarType.textInput, - required: true, - max_length: 12, - }, { - variable: 'num', - label: 'num', - type: InputVarType.number, - required: true, - }], - }, { - nodeId: '', - variables: [{ - variable: 'name', - label: 'name', - type: InputVarType.textInput, - required: true, - max_length: 12, - }, { - variable: 'num', - label: 'num', - type: InputVarType.number, - required: true, - }], - }], + ragPipelineVariables: [], setRagPipelineVariables: (ragPipelineVariables: RAGPipelineVariables) => set(() => ({ ragPipelineVariables })), }) diff --git a/web/config/index.ts b/web/config/index.ts index 4d308807c5..6b27207a10 100644 --- a/web/config/index.ts +++ b/web/config/index.ts @@ -1,6 +1,7 @@ import { InputVarType } from '@/app/components/workflow/types' import { AgentStrategy } from '@/types/app' import { PromptRole } from '@/models/debug' +import { PipelineInputVarType } from '@/models/pipeline' export let apiPrefix = '' export let webPrefix = '' @@ -162,6 +163,15 @@ export const VAR_ITEM_TEMPLATE_IN_WORKFLOW = { options: [], } +export const VAR_ITEM_TEMPLATE_IN_PIPELINE = { + variable: '', + label: '', + type: PipelineInputVarType.textInput, + max_length: DEFAULT_VALUE_MAX_LEN, + required: true, + options: [], +} + export const appDefaultIconBackground = '#D5F5F6' export const NEED_REFRESH_APP_LIST_KEY = 'needRefreshAppList' diff --git a/web/models/pipeline.ts b/web/models/pipeline.ts index b516611a42..4578fe59c4 100644 --- a/web/models/pipeline.ts +++ b/web/models/pipeline.ts @@ -1,9 +1,10 @@ -import type { Edge, InputVar, InputVarType, Node } from '@/app/components/workflow/types' +import type { Edge, Node, SupportUploadFileTypes } from '@/app/components/workflow/types' import type { DSLImportMode, DSLImportStatus } from './app' import type { ChunkingMode, DatasetPermission, IconInfo } from './datasets' import type { Dependency } from '@/app/components/plugins/types' import type { AppIconSelection } from '@/app/components/base/app-icon-picker' import type { Viewport } from 'reactflow' +import type { TransferMethod } from '@/types/app' export type PipelineTemplateListParams = { type: 'built-in' | 'customized' @@ -96,24 +97,37 @@ export type PipelineCheckDependenciesResponse = { leaked_dependencies: Dependency[] } -export type Variables = { - type: InputVarType - label: string - description: string - variable: string - max_length: number - required: boolean - options?: string[] - default: string | number | boolean +export enum PipelineInputVarType { + textInput = 'text-input', + paragraph = 'paragraph', + select = 'select', + number = 'number', + singleFile = 'file', + multiFiles = 'file-list', + checkbox = 'checkbox', } +export type RAGPipelineVariable = { + belong_to_node_id: string // indicates belong to which node or 'shared' + type: PipelineInputVarType + label: string + variable: string + max_length?: number + default?: string + placeholder?: string + unit?: string + required: boolean + tooltips?: string + options?: string[] + allowed_file_upload_methods?: TransferMethod[] + allowed_file_types?: SupportUploadFileTypes[] + allowed_file_extensions?: string[] +} + +export type InputVar = Omit + export type PipelineProcessingParamsResponse = { - variables: Variables[] + variables: RAGPipelineVariable[] } -export type RAGPipelineVariable = InputVar - -export type RAGPipelineVariables = Array<{ - nodeId: string - variables: RAGPipelineVariable[] -}> +export type RAGPipelineVariables = RAGPipelineVariable[]