123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- 'use client'
- import type { FC } from 'react'
- import React, { useCallback } from 'react'
- import useSWR from 'swr'
- import produce from 'immer'
- import { useTranslation } from 'react-i18next'
- import type { UploadFileSetting } from '../../../types'
- import { SupportUploadFileTypes } from '../../../types'
- import OptionCard from './option-card'
- import FileTypeItem from './file-type-item'
- import InputNumberWithSlider from './input-number-with-slider'
- import Field from '@/app/components/app/configuration/config-var/config-modal/field'
- import { TransferMethod } from '@/types/app'
- import { fetchFileUploadConfig } from '@/service/common'
- import { useFileSizeLimit } from '@/app/components/base/file-uploader/hooks'
- import { formatFileSize } from '@/utils/format'
- type Props = {
- payload: UploadFileSetting
- isMultiple: boolean
- inFeaturePanel?: boolean
- hideSupportFileType?: boolean
- onChange: (payload: UploadFileSetting) => void
- }
- const FileUploadSetting: FC<Props> = ({
- payload,
- isMultiple,
- inFeaturePanel = false,
- hideSupportFileType = false,
- onChange,
- }) => {
- const { t } = useTranslation()
- const {
- allowed_file_upload_methods,
- max_length,
- allowed_file_types,
- allowed_file_extensions,
- } = payload
- const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig)
- const { imgSizeLimit, docSizeLimit, audioSizeLimit, videoSizeLimit } = useFileSizeLimit(fileUploadConfigResponse)
- const handleSupportFileTypeChange = useCallback((type: SupportUploadFileTypes) => {
- const newPayload = produce(payload, (draft) => {
- if (type === SupportUploadFileTypes.custom) {
- if (!draft.allowed_file_types.includes(SupportUploadFileTypes.custom))
- draft.allowed_file_types = [SupportUploadFileTypes.custom]
- else
- draft.allowed_file_types = draft.allowed_file_types.filter(v => v !== type)
- }
- else {
- draft.allowed_file_types = draft.allowed_file_types.filter(v => v !== SupportUploadFileTypes.custom)
- if (draft.allowed_file_types.includes(type))
- draft.allowed_file_types = draft.allowed_file_types.filter(v => v !== type)
- else
- draft.allowed_file_types.push(type)
- }
- })
- onChange(newPayload)
- }, [onChange, payload])
- const handleUploadMethodChange = useCallback((method: TransferMethod) => {
- return () => {
- const newPayload = produce(payload, (draft) => {
- if (method === TransferMethod.all)
- draft.allowed_file_upload_methods = [TransferMethod.local_file, TransferMethod.remote_url]
- else
- draft.allowed_file_upload_methods = [method]
- })
- onChange(newPayload)
- }
- }, [onChange, payload])
- const handleCustomFileTypesChange = useCallback((customFileTypes: string[]) => {
- const newPayload = produce(payload, (draft) => {
- draft.allowed_file_extensions = customFileTypes.map((v) => {
- if (v.startsWith('.')) // Not start with dot
- return v.slice(1)
- return v
- })
- })
- onChange(newPayload)
- }, [onChange, payload])
- const handleMaxUploadNumLimitChange = useCallback((value: number) => {
- const newPayload = produce(payload, (draft) => {
- draft.max_length = value
- })
- onChange(newPayload)
- }, [onChange, payload])
- return (
- <div>
- {!inFeaturePanel && (
- <Field
- title={t('appDebug.variableConfig.file.supportFileTypes')}
- >
- <div className='space-y-1'>
- {
- [SupportUploadFileTypes.document, SupportUploadFileTypes.image, SupportUploadFileTypes.audio, SupportUploadFileTypes.video].map((type: SupportUploadFileTypes) => (
- <FileTypeItem
- key={type}
- type={type as SupportUploadFileTypes.image | SupportUploadFileTypes.document | SupportUploadFileTypes.audio | SupportUploadFileTypes.video}
- selected={allowed_file_types.includes(type)}
- onToggle={handleSupportFileTypeChange}
- />
- ))
- }
- <FileTypeItem
- type={SupportUploadFileTypes.custom}
- selected={allowed_file_types.includes(SupportUploadFileTypes.custom)}
- onToggle={handleSupportFileTypeChange}
- customFileTypes={allowed_file_extensions?.map(item => `.${item}`)}
- onCustomFileTypesChange={handleCustomFileTypesChange}
- />
- </div>
- </Field>
- )}
- <Field
- title={t('appDebug.variableConfig.uploadFileTypes')}
- className='mt-4'
- >
- <div className='grid grid-cols-3 gap-2'>
- <OptionCard
- title={t('appDebug.variableConfig.localUpload')}
- selected={allowed_file_upload_methods.length === 1 && allowed_file_upload_methods.includes(TransferMethod.local_file)}
- onSelect={handleUploadMethodChange(TransferMethod.local_file)}
- />
- <OptionCard
- title="URL"
- selected={allowed_file_upload_methods.length === 1 && allowed_file_upload_methods.includes(TransferMethod.remote_url)}
- onSelect={handleUploadMethodChange(TransferMethod.remote_url)}
- />
- <OptionCard
- title={t('appDebug.variableConfig.both')}
- selected={allowed_file_upload_methods.includes(TransferMethod.local_file) && allowed_file_upload_methods.includes(TransferMethod.remote_url)}
- onSelect={handleUploadMethodChange(TransferMethod.all)}
- />
- </div>
- </Field>
- {isMultiple && (
- <Field
- className='mt-4'
- title={t('appDebug.variableConfig.maxNumberOfUploads')!}
- >
- <div>
- <div className='mb-1.5 text-text-tertiary body-xs-regular'>{t('appDebug.variableConfig.maxNumberTip', {
- imgLimit: formatFileSize(imgSizeLimit),
- docLimit: formatFileSize(docSizeLimit),
- audioLimit: formatFileSize(audioSizeLimit),
- videoLimit: formatFileSize(videoSizeLimit),
- })}</div>
- <InputNumberWithSlider
- value={max_length}
- min={1}
- max={10}
- onChange={handleMaxUploadNumLimitChange}
- />
- </div>
- </Field>
- )}
- {inFeaturePanel && !hideSupportFileType && (
- <Field
- title={t('appDebug.variableConfig.file.supportFileTypes')}
- className='mt-4'
- >
- <div className='space-y-1'>
- {
- [SupportUploadFileTypes.document, SupportUploadFileTypes.image, SupportUploadFileTypes.audio, SupportUploadFileTypes.video].map((type: SupportUploadFileTypes) => (
- <FileTypeItem
- key={type}
- type={type as SupportUploadFileTypes.image | SupportUploadFileTypes.document | SupportUploadFileTypes.audio | SupportUploadFileTypes.video}
- selected={allowed_file_types.includes(type)}
- onToggle={handleSupportFileTypeChange}
- />
- ))
- }
- <FileTypeItem
- type={SupportUploadFileTypes.custom}
- selected={allowed_file_types.includes(SupportUploadFileTypes.custom)}
- onToggle={handleSupportFileTypeChange}
- customFileTypes={allowed_file_extensions}
- onCustomFileTypesChange={handleCustomFileTypesChange}
- />
- </div>
- </Field>
- )}
- </div>
- )
- }
- export default React.memo(FileUploadSetting)
|