diff --git a/web/app/components/app/configuration/config-var/config-modal/__tests__/form-fields.spec.tsx b/web/app/components/app/configuration/config-var/config-modal/__tests__/form-fields.spec.tsx
index 1ce6a4d0e5..91fc828c2f 100644
--- a/web/app/components/app/configuration/config-var/config-modal/__tests__/form-fields.spec.tsx
+++ b/web/app/components/app/configuration/config-var/config-modal/__tests__/form-fields.spec.tsx
@@ -166,6 +166,12 @@ describe('ConfigModalFormFields', () => {
})
it('should wire file, json schema, and visibility controls', () => {
+ const textInputProps = createBaseProps()
+ const textInputView = render()
+ expect(screen.getByText('variableConfig.hidden')).toBeInTheDocument()
+ expect(screen.getByText('variableConfig.hiddenDescription')).toBeInTheDocument()
+ textInputView.unmount()
+
const singleFileProps = createBaseProps()
singleFileProps.tempPayload = {
...singleFileProps.tempPayload,
@@ -174,20 +180,20 @@ describe('ConfigModalFormFields', () => {
allowed_file_extensions: [],
allowed_file_upload_methods: ['remote_url'],
}
- render()
- expect(screen.getByText('variableConfig.hidden')).toBeInTheDocument()
- expect(screen.getByText('variableConfig.hiddenDescription')).toBeInTheDocument()
+ const singleFileView = render()
+ expect(screen.queryByText('variableConfig.hidden')).not.toBeInTheDocument()
+ expect(screen.queryByText('variableConfig.hiddenDescription')).not.toBeInTheDocument()
fireEvent.click(screen.getByText('single-file-setting'))
fireEvent.click(screen.getByText('upload-file'))
- fireEvent.click(screen.getAllByText('unchecked')[0])
- fireEvent.click(screen.getAllByText('unchecked')[1])
+ fireEvent.click(screen.getByText('unchecked'))
expect(singleFileProps.onFilePayloadChange).toHaveBeenCalledWith({ number_limits: 1 })
expect(singleFileProps.payloadChangeHandlers.default).toHaveBeenCalledWith(expect.objectContaining({
fileId: 'file-1',
}))
expect(singleFileProps.payloadChangeHandlers.required).toHaveBeenCalledWith(true)
- expect(singleFileProps.payloadChangeHandlers.hide).toHaveBeenCalledWith(true)
+ expect(singleFileProps.payloadChangeHandlers.hide).not.toHaveBeenCalled()
+ singleFileView.unmount()
const multiFileProps = createBaseProps()
multiFileProps.tempPayload = {
@@ -198,8 +204,9 @@ describe('ConfigModalFormFields', () => {
allowed_file_upload_methods: ['remote_url'],
}
render()
+ expect(screen.queryByText('variableConfig.hidden')).not.toBeInTheDocument()
fireEvent.click(screen.getByText('multi-file-setting'))
- fireEvent.click(screen.getAllByText('upload-file')[1])
+ fireEvent.click(screen.getByText('upload-file'))
expect(multiFileProps.onFilePayloadChange).toHaveBeenCalledWith({ number_limits: 3 })
expect(multiFileProps.payloadChangeHandlers.default).toHaveBeenCalledWith([
expect.objectContaining({ fileId: 'file-1' }),
diff --git a/web/app/components/app/configuration/config-var/config-modal/__tests__/index-logic.spec.tsx b/web/app/components/app/configuration/config-var/config-modal/__tests__/index-logic.spec.tsx
index 4888d284d2..fccd48725e 100644
--- a/web/app/components/app/configuration/config-var/config-modal/__tests__/index-logic.spec.tsx
+++ b/web/app/components/app/configuration/config-var/config-modal/__tests__/index-logic.spec.tsx
@@ -25,6 +25,7 @@ vi.mock('../form-fields', () => ({
return (
{String(props.tempPayload.type)}
+
{String(props.tempPayload.hide)}
{String(props.tempPayload.label ?? '')}
{String(props.tempPayload.json_schema ?? '')}
{String(props.tempPayload.default ?? '')}
@@ -115,7 +116,7 @@ describe('ConfigModal logic', () => {
})
it('should derive payload fields from mocked form-field callbacks', async () => {
- renderConfigModal()
+ renderConfigModal(createPayload({ hide: true }))
fireEvent.click(screen.getByTestId('valid-key-blur'))
await waitFor(() => {
@@ -138,6 +139,7 @@ describe('ConfigModal logic', () => {
fireEvent.click(screen.getByTestId('type-change'))
await waitFor(() => {
expect(screen.getByTestId('payload-type')).toHaveTextContent(InputVarType.singleFile)
+ expect(screen.getByTestId('payload-hide')).toHaveTextContent('false')
})
fireEvent.click(screen.getByTestId('file-payload-change'))
diff --git a/web/app/components/app/configuration/config-var/config-modal/__tests__/utils.spec.ts b/web/app/components/app/configuration/config-var/config-modal/__tests__/utils.spec.ts
index 1c00e1c5b2..2317868004 100644
--- a/web/app/components/app/configuration/config-var/config-modal/__tests__/utils.spec.ts
+++ b/web/app/components/app/configuration/config-var/config-modal/__tests__/utils.spec.ts
@@ -49,11 +49,13 @@ describe('config-modal utils', () => {
const payload = createInputVar({
type: InputVarType.textInput,
default: 'hello',
+ hide: true,
})
const nextPayload = createPayloadForType(payload, InputVarType.multiFiles)
expect(nextPayload.type).toBe(InputVarType.multiFiles)
+ expect(nextPayload.hide).toBe(false)
expect(nextPayload.max_length).toBe(DEFAULT_FILE_UPLOAD_SETTING.max_length)
expect(nextPayload.allowed_file_types).toEqual(DEFAULT_FILE_UPLOAD_SETTING.allowed_file_types)
expect(nextPayload.default).toBe('hello')
@@ -249,6 +251,24 @@ describe('config-modal utils', () => {
})
})
+ it('should force file inputs to stay visible when saving', () => {
+ const result = validateConfigModalPayload({
+ tempPayload: createInputVar({
+ type: InputVarType.singleFile,
+ hide: true,
+ allowed_file_types: [SupportUploadFileTypes.document],
+ allowed_file_extensions: [],
+ }),
+ payload: createInputVar(),
+ checkVariableName: () => true,
+ t,
+ })
+
+ expect(result.payloadToSave).toEqual(expect.objectContaining({
+ hide: false,
+ }))
+ })
+
it('should stop validation when the variable name checker rejects the payload', () => {
const result = validateConfigModalPayload({
tempPayload: createInputVar({
diff --git a/web/app/components/app/configuration/config-var/config-modal/form-fields.tsx b/web/app/components/app/configuration/config-var/config-modal/form-fields.tsx
index 1aa12320aa..de0a96ce02 100644
--- a/web/app/components/app/configuration/config-var/config-modal/form-fields.tsx
+++ b/web/app/components/app/configuration/config-var/config-modal/form-fields.tsx
@@ -68,6 +68,7 @@ const ConfigModalFormFields: FC
= ({
t,
}) => {
const { type, label, variable } = tempPayload
+ const isFileInput = [InputVarType.singleFile, InputVarType.multiFiles].includes(type)
return (
@@ -174,7 +175,7 @@ const ConfigModalFormFields: FC
= ({
>
)}
- {[InputVarType.singleFile, InputVarType.multiFiles].includes(type) && (
+ {isFileInput && (
<>
= ({
)}
- onPayloadChange('required')(!tempPayload.required)} />
+ onPayloadChange('required')(!tempPayload.required)} />
{t('variableConfig.required', { ns: 'appDebug' })}
-
-
onPayloadChange('hide')(!tempPayload.hide)} />
-
-
{t('variableConfig.hidden', { ns: 'appDebug' })}
-
-
-
-
-
-
-
- {t('variableConfig.hiddenDescription', { ns: 'appDebug' })}
-
-
+ {!isFileInput && (
+
+
onPayloadChange('hide')(!tempPayload.hide)} />
+
+
{t('variableConfig.hidden', { ns: 'appDebug' })}
+
+
+
+
+
+
+
+ {t('variableConfig.hiddenDescription', { ns: 'appDebug' })}
+
+
+
-
+ )}
)
}
diff --git a/web/app/components/app/configuration/config-var/config-modal/utils.ts b/web/app/components/app/configuration/config-var/config-modal/utils.ts
index fdc0ac3501..e24e4b6593 100644
--- a/web/app/components/app/configuration/config-var/config-modal/utils.ts
+++ b/web/app/components/app/configuration/config-var/config-modal/utils.ts
@@ -88,7 +88,9 @@ export const createPayloadForType = (payload: InputVar, type: InputVarType) => {
draft.default = undefined
if ([InputVarType.singleFile, InputVarType.multiFiles].includes(type)) {
- (Object.keys(DEFAULT_FILE_UPLOAD_SETTING) as Array).forEach((key) => {
+ draft.hide = false
+ const fileUploadSettingKeys = Object.keys(DEFAULT_FILE_UPLOAD_SETTING) as Array
+ fileUploadSettingKeys.forEach((key) => {
if (key !== 'max_length')
draft[key] = DEFAULT_FILE_UPLOAD_SETTING[key] as never
})
@@ -158,38 +160,41 @@ export const validateConfigModalPayload = ({
checkVariableName,
t,
}: ValidateConfigModalPayloadOptions): ValidateConfigModalPayloadResult => {
+ const normalizedTempPayload = [InputVarType.singleFile, InputVarType.multiFiles].includes(tempPayload.type)
+ ? { ...tempPayload, hide: false }
+ : tempPayload
const jsonSchemaValue = tempPayload.json_schema
const schemaEmpty = isJsonSchemaEmpty(jsonSchemaValue)
const normalizedJsonSchema = schemaEmpty ? undefined : jsonSchemaValue
- const payloadToSave = tempPayload.type === InputVarType.jsonObject && schemaEmpty
- ? { ...tempPayload, json_schema: undefined }
- : tempPayload
+ const payloadToSave = normalizedTempPayload.type === InputVarType.jsonObject && schemaEmpty
+ ? { ...normalizedTempPayload, json_schema: undefined }
+ : normalizedTempPayload
- const moreInfo = tempPayload.variable === payload?.variable
+ const moreInfo = normalizedTempPayload.variable === payload?.variable
? undefined
: {
type: ChangeType.changeVarName,
- payload: { beforeKey: payload?.variable || '', afterKey: tempPayload.variable },
+ payload: { beforeKey: payload?.variable || '', afterKey: normalizedTempPayload.variable },
}
- if (!checkVariableName(tempPayload.variable))
+ if (!checkVariableName(normalizedTempPayload.variable))
return {}
- if (!tempPayload.label) {
+ if (!normalizedTempPayload.label) {
return {
errorMessage: t('variableConfig.errorMsg.labelNameRequired', { ns: 'appDebug' }),
}
}
- if (tempPayload.type === InputVarType.select) {
- if (!tempPayload.options?.length) {
+ if (normalizedTempPayload.type === InputVarType.select) {
+ if (!normalizedTempPayload.options?.length) {
return {
errorMessage: t('variableConfig.errorMsg.atLeastOneOption', { ns: 'appDebug' }),
}
}
const duplicated = new Set()
- const hasRepeatedItem = tempPayload.options.some((option) => {
+ const hasRepeatedItem = normalizedTempPayload.options.some((option) => {
if (duplicated.has(option))
return true
@@ -204,8 +209,8 @@ export const validateConfigModalPayload = ({
}
}
- if ([InputVarType.singleFile, InputVarType.multiFiles].includes(tempPayload.type)) {
- if (!tempPayload.allowed_file_types?.length) {
+ if ([InputVarType.singleFile, InputVarType.multiFiles].includes(normalizedTempPayload.type)) {
+ if (!normalizedTempPayload.allowed_file_types?.length) {
return {
errorMessage: t('errorMsg.fieldRequired', {
ns: 'workflow',
@@ -214,7 +219,7 @@ export const validateConfigModalPayload = ({
}
}
- if (tempPayload.allowed_file_types.includes(SupportUploadFileTypes.custom) && !tempPayload.allowed_file_extensions?.length) {
+ if (normalizedTempPayload.allowed_file_types.includes(SupportUploadFileTypes.custom) && !normalizedTempPayload.allowed_file_extensions?.length) {
return {
errorMessage: t('errorMsg.fieldRequired', {
ns: 'workflow',
@@ -224,7 +229,7 @@ export const validateConfigModalPayload = ({
}
}
- if (tempPayload.type === InputVarType.jsonObject && !schemaEmpty && typeof normalizedJsonSchema === 'string') {
+ if (normalizedTempPayload.type === InputVarType.jsonObject && !schemaEmpty && typeof normalizedJsonSchema === 'string') {
try {
const schema = JSON.parse(normalizedJsonSchema)
if (schema?.type !== 'object') {