mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 18:27:19 +08:00
chore: file type not show hidden
This commit is contained in:
parent
21420eab64
commit
27791ac121
@ -166,6 +166,12 @@ describe('ConfigModalFormFields', () => {
|
||||
})
|
||||
|
||||
it('should wire file, json schema, and visibility controls', () => {
|
||||
const textInputProps = createBaseProps()
|
||||
const textInputView = render(<ConfigModalFormFields {...textInputProps} />)
|
||||
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(<ConfigModalFormFields {...singleFileProps} />)
|
||||
expect(screen.getByText('variableConfig.hidden')).toBeInTheDocument()
|
||||
expect(screen.getByText('variableConfig.hiddenDescription')).toBeInTheDocument()
|
||||
const singleFileView = render(<ConfigModalFormFields {...singleFileProps} />)
|
||||
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(<ConfigModalFormFields {...multiFileProps} />)
|
||||
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' }),
|
||||
|
||||
@ -25,6 +25,7 @@ vi.mock('../form-fields', () => ({
|
||||
return (
|
||||
<div data-testid="config-form-fields">
|
||||
<div data-testid="payload-type">{String(props.tempPayload.type)}</div>
|
||||
<div data-testid="payload-hide">{String(props.tempPayload.hide)}</div>
|
||||
<div data-testid="payload-label">{String(props.tempPayload.label ?? '')}</div>
|
||||
<div data-testid="payload-schema">{String(props.tempPayload.json_schema ?? '')}</div>
|
||||
<div data-testid="payload-default">{String(props.tempPayload.default ?? '')}</div>
|
||||
@ -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'))
|
||||
|
||||
@ -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({
|
||||
|
||||
@ -68,6 +68,7 @@ const ConfigModalFormFields: FC<ConfigModalFormFieldsProps> = ({
|
||||
t,
|
||||
}) => {
|
||||
const { type, label, variable } = tempPayload
|
||||
const isFileInput = [InputVarType.singleFile, InputVarType.multiFiles].includes(type)
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
@ -174,7 +175,7 @@ const ConfigModalFormFields: FC<ConfigModalFormFieldsProps> = ({
|
||||
</>
|
||||
)}
|
||||
|
||||
{[InputVarType.singleFile, InputVarType.multiFiles].includes(type) && (
|
||||
{isFileInput && (
|
||||
<>
|
||||
<FileUploadSetting
|
||||
payload={tempPayload as UploadFileSetting}
|
||||
@ -215,26 +216,28 @@ const ConfigModalFormFields: FC<ConfigModalFormFieldsProps> = ({
|
||||
)}
|
||||
|
||||
<div className="mt-5! flex h-6 items-center space-x-2">
|
||||
<Checkbox checked={tempPayload.required} disabled={tempPayload.hide} onCheck={() => onPayloadChange('required')(!tempPayload.required)} />
|
||||
<Checkbox checked={tempPayload.required} disabled={!isFileInput && tempPayload.hide} onCheck={() => onPayloadChange('required')(!tempPayload.required)} />
|
||||
<span className="system-sm-semibold text-text-secondary">{t('variableConfig.required', { ns: 'appDebug' })}</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-5! flex h-6 items-center space-x-2">
|
||||
<Checkbox checked={tempPayload.hide} disabled={tempPayload.required} onCheck={() => onPayloadChange('hide')(!tempPayload.hide)} />
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="system-sm-semibold text-text-secondary">{t('variableConfig.hidden', { ns: 'appDebug' })}</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex h-4 w-4 items-center justify-center">
|
||||
<RiQuestionLine className="h-3.5 w-3.5 text-text-tertiary" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{t('variableConfig.hiddenDescription', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{!isFileInput && (
|
||||
<div className="mt-5! flex h-6 items-center space-x-2">
|
||||
<Checkbox checked={tempPayload.hide} disabled={tempPayload.required} onCheck={() => onPayloadChange('hide')(!tempPayload.hide)} />
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="system-sm-semibold text-text-secondary">{t('variableConfig.hidden', { ns: 'appDebug' })}</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex h-4 w-4 items-center justify-center">
|
||||
<RiQuestionLine className="h-3.5 w-3.5 text-text-tertiary" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{t('variableConfig.hiddenDescription', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -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<keyof typeof DEFAULT_FILE_UPLOAD_SETTING>).forEach((key) => {
|
||||
draft.hide = false
|
||||
const fileUploadSettingKeys = Object.keys(DEFAULT_FILE_UPLOAD_SETTING) as Array<keyof typeof DEFAULT_FILE_UPLOAD_SETTING>
|
||||
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<string>()
|
||||
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') {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user