feat: Upload a folder to knowledgebase (#17026)

Co-authored-by: Silow9 <soulskytony@gmail.com>
This commit is contained in:
Silow 2025-04-28 15:31:22 +08:00 committed by GitHub
parent 5de01c1444
commit ea150dc336
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 81 additions and 35 deletions

View File

@ -196,22 +196,68 @@ const FileUploader = ({
e.stopPropagation() e.stopPropagation()
e.target === dragRef.current && setDragging(false) e.target === dragRef.current && setDragging(false)
} }
type FileWithPath = {
relativePath?: string
} & File
const traverseFileEntry = useCallback(
(entry: any, prefix = ''): Promise<FileWithPath[]> => {
return new Promise((resolve) => {
if (entry.isFile) {
entry.file((file: FileWithPath) => {
file.relativePath = `${prefix}${file.name}`
resolve([file])
})
}
else if (entry.isDirectory) {
const reader = entry.createReader()
const entries: any[] = []
const read = () => {
reader.readEntries(async (results: FileSystemEntry[]) => {
if (!results.length) {
const files = await Promise.all(
entries.map(ent =>
traverseFileEntry(ent, `${prefix}${entry.name}/`),
),
)
resolve(files.flat())
}
else {
entries.push(...results)
read()
}
})
}
read()
}
else {
resolve([])
}
})
},
[],
)
const handleDrop = useCallback((e: DragEvent) => { const handleDrop = useCallback(
e.preventDefault() async (e: DragEvent) => {
e.stopPropagation() e.preventDefault()
setDragging(false) e.stopPropagation()
if (!e.dataTransfer) setDragging(false)
return if (!e.dataTransfer) return
const nested = await Promise.all(
let files = [...e.dataTransfer.files] as File[] Array.from(e.dataTransfer.items).map((it) => {
if (notSupportBatchUpload) const entry = (it as any).webkitGetAsEntry?.()
files = files.slice(0, 1) if (entry) return traverseFileEntry(entry)
const f = it.getAsFile?.()
const validFiles = files.filter(isValid) return f ? Promise.resolve([f]) : Promise.resolve([])
initialUpload(validFiles) }),
}, [initialUpload, isValid, notSupportBatchUpload]) )
let files = nested.flat()
if (notSupportBatchUpload) files = files.slice(0, 1)
const valid = files.filter(isValid)
initialUpload(valid)
},
[initialUpload, isValid, notSupportBatchUpload, traverseFileEntry],
)
const selectHandle = () => { const selectHandle = () => {
if (fileUploader.current) if (fileUploader.current)
fileUploader.current.click() fileUploader.current.click()

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Textdatei hochladen', title: 'Textdatei hochladen',
button: 'Datei hierher ziehen oder', button: 'Dateien und Ordner hierher ziehen oder klicken',
browse: 'Durchsuchen', browse: 'Durchsuchen',
tip: 'Unterstützt {{supportTypes}}. Maximal {{size}}MB pro Datei.', tip: 'Unterstützt {{supportTypes}}. Maximal {{size}}MB pro Datei.',
validation: { validation: {

View File

@ -35,7 +35,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Upload file', title: 'Upload file',
button: 'Drag and drop file, or', button: 'Drag and drop file or folder, or',
browse: 'Browse', browse: 'Browse',
tip: 'Supports {{supportTypes}}. Max {{size}}MB each.', tip: 'Supports {{supportTypes}}. Max {{size}}MB each.',
validation: { validation: {

View File

@ -27,7 +27,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Cargar archivo', title: 'Cargar archivo',
button: 'Arrastra y suelta el archivo, o', button: 'Arrastre y suelte archivos o carpetas, o',
browse: 'Buscar', browse: 'Buscar',
tip: 'Soporta {{supportTypes}}. Máximo {{size}}MB cada uno.', tip: 'Soporta {{supportTypes}}. Máximo {{size}}MB cada uno.',
validation: { validation: {

View File

@ -27,7 +27,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'بارگذاری فایل', title: 'بارگذاری فایل',
button: 'کشیدن و رها کردن فایل، یا', button: 'فایل ها یا پوشه ها را بکشید و رها کنید یا',
browse: 'مرور', browse: 'مرور',
tip: 'پشتیبانی از {{supportTypes}}. حداکثر {{size}}MB هر کدام.', tip: 'پشتیبانی از {{supportTypes}}. حداکثر {{size}}MB هر کدام.',
validation: { validation: {

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Télécharger le fichier texte', title: 'Télécharger le fichier texte',
button: 'Glisser et déposer le fichier, ou', button: 'Faites glisser et déposez des fichiers ou des dossiers, ou',
browse: 'Parcourir', browse: 'Parcourir',
tip: 'Prend en charge {{supportTypes}}. Max {{size}}MB chacun.', tip: 'Prend en charge {{supportTypes}}. Max {{size}}MB chacun.',
validation: { validation: {

View File

@ -27,7 +27,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'फ़ाइल अपलोड करें', title: 'फ़ाइल अपलोड करें',
button: 'फ़ाइल खींचें और छोड़ें, या', button: 'फ़ाइलों या फ़ोल्डरों को खींचें और छोड़ें, या',
browse: 'ब्राउज़ करें', browse: 'ब्राउज़ करें',
tip: 'समर्थित {{supportTypes}}। प्रत्येक अधिकतम {{size}}MB।', tip: 'समर्थित {{supportTypes}}। प्रत्येक अधिकतम {{size}}MB।',
validation: { validation: {

View File

@ -27,7 +27,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Carica file', title: 'Carica file',
button: 'Trascina e rilascia il file, o', button: 'Trascina e rilascia file o cartelle, oppure',
browse: 'Sfoglia', browse: 'Sfoglia',
tip: 'Supporta {{supportTypes}}. Max {{size}}MB ciascuno.', tip: 'Supporta {{supportTypes}}. Max {{size}}MB ciascuno.',
validation: { validation: {

View File

@ -30,7 +30,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'テキストファイルをアップロード', title: 'テキストファイルをアップロード',
button: 'ファイルをドラッグ&ドロップするか', button: 'ファイルまたはフォルダをドラッグアンドドロップする',
browse: '参照', browse: '参照',
tip: '{{supportTypes}}をサポートしています。1つあたりの最大サイズは{{size}}MBです。', tip: '{{supportTypes}}をサポートしています。1つあたりの最大サイズは{{size}}MBです。',
validation: { validation: {

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: '텍스트 파일 업로드', title: '텍스트 파일 업로드',
button: '파일을 끌어다 놓거나', button: '파일이나 폴더를 끌어서 놓기',
browse: '찾아보기', browse: '찾아보기',
tip: '{{supportTypes}}을(를) 지원합니다. 파일당 최대 크기는 {{size}}MB입니다.', tip: '{{supportTypes}}을(를) 지원합니다. 파일당 최대 크기는 {{size}}MB입니다.',
validation: { validation: {

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Prześlij plik tekstowy', title: 'Prześlij plik tekstowy',
button: 'Przeciągnij i upuść plik lub', button: 'Przeciągnij i upuść pliki lub foldery lub',
browse: 'Przeglądaj', browse: 'Przeglądaj',
tip: 'Obsługuje {{supportTypes}}. Maksymalnie {{size}}MB każdy.', tip: 'Obsługuje {{supportTypes}}. Maksymalnie {{size}}MB każdy.',
validation: { validation: {

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Enviar arquivo de texto', title: 'Enviar arquivo de texto',
button: 'Arraste e solte o arquivo, ou', button: 'Arraste e solte arquivos ou pastas, ou',
browse: 'Navegar', browse: 'Navegar',
tip: 'Suporta {{supportTypes}}. Máximo de {{size}}MB cada.', tip: 'Suporta {{supportTypes}}. Máximo de {{size}}MB cada.',
validation: { validation: {

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Încărcați fișier text', title: 'Încărcați fișier text',
button: 'Trageți și fixați fișierul, sau', button: 'Trageți și plasați fișiere sau foldere sau',
browse: 'Răsfoire', browse: 'Răsfoire',
tip: 'Acceptă {{supportTypes}}. Maxim {{size}}MB fiecare.', tip: 'Acceptă {{supportTypes}}. Maxim {{size}}MB fiecare.',
validation: { validation: {

View File

@ -27,7 +27,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Загрузить файл', title: 'Загрузить файл',
button: 'Перетащите файл или', button: 'Перетащите файлы или папки или',
browse: 'Обзор', browse: 'Обзор',
tip: 'Поддерживаются {{supportTypes}}. Максимум {{size}} МБ каждый.', tip: 'Поддерживаются {{supportTypes}}. Максимум {{size}} МБ каждый.',
validation: { validation: {

View File

@ -32,7 +32,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Naloži datoteko', title: 'Naloži datoteko',
button: 'Povleci in spusti datoteko ali', button: 'Povleci in spusti datoteke ali mape oz',
browse: 'Prebrskaj', browse: 'Prebrskaj',
tip: 'Podprti tipi datotek: {{supportTypes}}. Največ {{size}}MB na datoteko.', tip: 'Podprti tipi datotek: {{supportTypes}}. Največ {{size}}MB na datoteko.',
validation: { validation: {

View File

@ -32,7 +32,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'อัปโหลดไฟล์', title: 'อัปโหลดไฟล์',
button: 'ลากและวางไฟล์ หรือ', button: 'ลากและวางไฟล์หรือโฟลเดอร์หรือ',
browse: 'เล็ม', browse: 'เล็ม',
tip: 'รองรับ {{supportTypes}} สูงสุด {{size}}MB แต่ละตัว', tip: 'รองรับ {{supportTypes}} สูงสุด {{size}}MB แต่ละตัว',
validation: { validation: {

View File

@ -27,7 +27,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Dosya yükle', title: 'Dosya yükle',
button: 'Dosyayı sürükleyip bırakın veya', button: 'Dosyaları veya klasörleri sürükleyip bırakın veya',
browse: 'Göz atın', browse: 'Göz atın',
tip: 'Destekler {{supportTypes}}. Her biri en fazla {{size}}MB.', tip: 'Destekler {{supportTypes}}. Her biri en fazla {{size}}MB.',
validation: { validation: {

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Завантажити текстовий файл', title: 'Завантажити текстовий файл',
button: 'Перетягніть файл або', button: 'Перетягніть файли або папки або',
browse: 'Оберіть', browse: 'Оберіть',
tip: 'Підтримуються {{supportTypes}}. Максимум {{size}} МБ кожен.', tip: 'Підтримуються {{supportTypes}}. Максимум {{size}} МБ кожен.',
validation: { validation: {

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: 'Tải lên tệp văn bản', title: 'Tải lên tệp văn bản',
button: 'Kéo và thả tệp, hoặc', button: 'Kéo và thả các tập tin hoặc thư mục, hoặc',
browse: 'Chọn tệp', browse: 'Chọn tệp',
tip: 'Hỗ trợ {{supportTypes}}. Tối đa {{size}}MB mỗi tệp.', tip: 'Hỗ trợ {{supportTypes}}. Tối đa {{size}}MB mỗi tệp.',
validation: { validation: {

View File

@ -35,7 +35,7 @@ const translation = {
}, },
uploader: { uploader: {
title: '上传文本文件', title: '上传文本文件',
button: '拖拽文件至此,或者', button: '拖拽文件或文件夹至此,或者',
browse: '选择文件', browse: '选择文件',
tip: '已支持 {{supportTypes}},每个文件不超过 {{size}}MB。', tip: '已支持 {{supportTypes}},每个文件不超过 {{size}}MB。',
validation: { validation: {

View File

@ -22,7 +22,7 @@ const translation = {
}, },
uploader: { uploader: {
title: '上傳文字檔案', title: '上傳文字檔案',
button: '拖拽檔案至此,或者', button: '拖拽檔案或檔案夾至此,或者',
browse: '選擇檔案', browse: '選擇檔案',
tip: '已支援 {{supportTypes}},每個檔案不超過 {{size}}MB。', tip: '已支援 {{supportTypes}},每個檔案不超過 {{size}}MB。',
validation: { validation: {