Compare commits

...

119 Commits

Author SHA1 Message Date
StyleZhang
d6c08ca6ac merge main 2023-06-19 17:39:59 +08:00
StyleZhang
586c90c984 merge main 2023-06-19 17:35:14 +08:00
Joel
511de822d7 fix: file array not sync 2023-06-19 15:54:43 +08:00
JzoNg
93f8fe8406 feat: file upload 2023-06-16 16:11:59 +08:00
JzoNg
3f9af702a2 feat: update style of uploader 2023-06-16 16:11:59 +08:00
StyleZhang
68eb3126e7 fix: document list sync 2023-06-16 15:49:48 +08:00
StyleZhang
6cebdb3ccb fix: delete document in document detail page 2023-06-16 15:43:04 +08:00
jyong
dd1edab89b fix ai_block type 2023-06-16 15:33:08 +08:00
StyleZhang
b668d06ca9 fix: no data source bounding 2023-06-16 14:51:02 +08:00
jyong
03c69feda4 return empty result 2023-06-16 14:42:05 +08:00
jyong
76f9694fae return empty result 2023-06-16 14:35:45 +08:00
jyong
6634274151 Fix the issue of decoding a non-UTF-8 encoded file using UTF-8 2023-06-16 12:03:51 +08:00
StyleZhang
ba1fa57dc3 fix: notion file type in document list 2023-06-16 11:24:43 +08:00
StyleZhang
1d860cd85b fix: dataset document list 2023-06-16 10:58:50 +08:00
jyong
d658ea8a8b Merge remote-tracking branch 'origin/feat/dataset-notion-import' into feat/dataset-notion-import 2023-06-16 10:02:59 +08:00
jyong
4c727d0de1 fetch document list 2023-06-16 10:02:45 +08:00
StyleZhang
a7cf7d6f41 fix: data source deleted 2023-06-16 09:53:39 +08:00
jyong
af5190d017 fix keyword issue 2023-06-15 19:11:02 +08:00
StyleZhang
ea36f95c81 fix: dataset document list timer 2023-06-15 18:02:54 +08:00
jyong
477030330c fix notion auth failed 2023-06-15 16:36:31 +08:00
jyong
476e2c5157 Merge branch 'main' into feat/dataset-notion-import 2023-06-15 16:30:16 +08:00
jyong
598336b209 fix notion auth failed 2023-06-15 15:25:19 +08:00
jyong
fefa3482de fix sync source info update 2023-06-15 15:03:28 +08:00
StyleZhang
58d769b34e fix: data-source-notion 2023-06-15 14:10:57 +08:00
StyleZhang
3e6320fc11 fix: account-setting member 2023-06-15 13:49:43 +08:00
StyleZhang
a090767491 fix: header-nav 2023-06-15 13:33:37 +08:00
jyong
9da3cc6c2e query block's parent page 2023-06-15 13:01:42 +08:00
jyong
9e84233029 query block's parent page 2023-06-15 12:53:28 +08:00
jyong
147ad5b579 delete all block type page and database 2023-06-15 11:52:00 +08:00
StyleZhang
5c355f4406 fix: notion-page-selector 2023-06-15 11:25:47 +08:00
StyleZhang
f571d7e728 fix: notion-page-selector 2023-06-15 10:44:30 +08:00
jyong
fa3522dcef add notion page icon to document 2023-06-14 18:22:50 +08:00
jyong
780f4c72f8 add notion page icon to document 2023-06-14 18:15:57 +08:00
StyleZhang
80a3d5772d add progress-bar 2023-06-14 17:46:43 +08:00
jyong
779312a3f9 add notion page icon to document 2023-06-14 17:37:17 +08:00
jyong
26ad00fff9 add notion page icon to document 2023-06-14 17:12:51 +08:00
jyong
c6918fbcab Merge remote-tracking branch 'origin/feat/dataset-notion-import' into feat/dataset-notion-import 2023-06-14 17:10:49 +08:00
JzoNg
10b9688689 fix: notion page re-segementation 2023-06-14 17:00:43 +08:00
jyong
110b5b015f Merge branch 'main' into feat/dataset-notion-import 2023-06-14 16:50:25 +08:00
JzoNg
6f9fd44589 fix: re-segmentation 2023-06-14 16:16:31 +08:00
JzoNg
1b3028d7fb fix: file icon 2023-06-14 15:46:50 +08:00
StyleZhang
3cbd57f392 fix: notion-icon in dataset document list 2023-06-14 15:39:45 +08:00
StyleZhang
4a4ed8c5bd fix notion icon in embedding process 2023-06-14 15:33:47 +08:00
StyleZhang
677aec942a dataset document list add notion icon 2023-06-14 15:29:50 +08:00
JzoNg
9291325128 fix: icon of notion page in step three 2023-06-14 15:20:26 +08:00
JzoNg
75e302eb93 feat: add proccess of data embedding 2023-06-14 14:56:40 +08:00
jyong
3cf48c8f64 add notion page icon to document 2023-06-14 14:56:19 +08:00
jyong
ecf421d241 add notion page icon to document 2023-06-14 14:27:28 +08:00
jyong
32985421fa add get index estimate by batch 2023-06-14 14:13:17 +08:00
jyong
5e6dc98788 add get index estimate by batch 2023-06-14 12:53:36 +08:00
jyong
aaa0a8d150 Merge remote-tracking branch 'origin/feat/dataset-notion-import' into feat/dataset-notion-import 2023-06-14 12:39:21 +08:00
jyong
0789642a32 add get index estimate by batch 2023-06-14 12:39:10 +08:00
JzoNg
cc9955189e feat: add status batch 2023-06-14 12:36:59 +08:00
StyleZhang
b1a0f150f1 fix: dataset notion icon 2023-06-14 11:24:08 +08:00
StyleZhang
0c51b42350 fix: notion page type 2023-06-14 11:06:50 +08:00
jyong
4354b6803b add get index estimate by batch 2023-06-14 10:00:11 +08:00
JzoNg
44fcd1c1ef feat: embedding process 2023-06-13 23:19:37 +08:00
jyong
47b299f52e add mutil upload batch 2023-06-13 22:23:43 +08:00
JzoNg
0cbb3c1508 feat: data source display 2023-06-13 18:56:42 +08:00
JzoNg
2b9f394a22 feat: add type for notion info list 2023-06-13 18:01:06 +08:00
StyleZhang
56bebe04e3 fix: notion-page-selector 2023-06-13 17:35:18 +08:00
jyong
703075b10c add document index status 2023-06-13 16:14:30 +08:00
StyleZhang
1d9f1fdbdb fix: notion-page-selector 2023-06-13 16:04:25 +08:00
jyong
7e11aab412 map exist values 2023-06-13 15:43:55 +08:00
jyong
ff594cdcd1 add dataset index status 2023-06-13 10:50:35 +08:00
jyong
4b039eadc6 add dataset index status 2023-06-13 10:43:48 +08:00
StyleZhang
3c589c44c6 fix: dataset document notion-page-selector-modal 2023-06-12 17:45:39 +08:00
StyleZhang
94b112fc6b feat: dataset document add notion-page-selector-modal 2023-06-12 17:03:33 +08:00
jyong
1f37a3a7ea init param 2023-06-12 15:36:31 +08:00
jyong
686e2efe96 fix database mode issue 2023-06-12 13:30:45 +08:00
StyleZhang
d965a280c1 fix: notion-page-selector preview 2023-06-12 10:04:54 +08:00
jyong
8f55352c7b add notion image referer 2023-06-09 20:38:41 +08:00
JzoNg
cd04225419 feat: support notion page preview 2023-06-09 18:33:24 +08:00
StyleZhang
1ee00cba97 fix: notion-page-selector 2023-06-09 17:54:13 +08:00
JzoNg
6b884ab253 Merge branch 'main' into tp 2023-06-09 16:17:59 +08:00
StyleZhang
7104fba05d fix: notion-page-selector preview & setting 2023-06-09 15:36:11 +08:00
StyleZhang
111813c7c2 feat: notion-page-selector 2023-06-09 15:14:58 +08:00
StyleZhang
68daf79f12 feat: notion-page-selector 2023-06-09 15:09:08 +08:00
jyong
cca2ba95c1 add notion customer icon 2023-06-09 13:53:21 +08:00
jyong
270c3d7b6b notion icon allow none 2023-06-09 11:17:26 +08:00
jyong
5097aa229a notion icon allow none 2023-06-09 11:06:03 +08:00
jyong
2809406ab9 notion icon allow none 2023-06-09 10:57:15 +08:00
jyong
6e5b66ddca notion icon format 2023-06-09 10:36:32 +08:00
jyong
e4d52c508c add notion parent id and icon support 2023-06-09 10:11:15 +08:00
jyong
7fc97ae7a1 add notion parent id and icon support 2023-06-09 10:01:38 +08:00
jyong
d8d27a49b7 add notion parent id and icon support 2023-06-09 01:14:12 +08:00
JzoNg
3b2b819985 feat: notion import in step one 2023-06-08 22:59:40 +08:00
JzoNg
761febc788 Merge branch 'main' into tp 2023-06-08 17:17:51 +08:00
StyleZhang
4814d6ea0d feat: add notion-page-selector 2023-06-08 16:52:08 +08:00
StyleZhang
62a5a1ea4f fix: setting page data source sync and remove notion connection 2023-06-08 11:12:14 +08:00
jyong
ed5b80e97a fix notion connection disable 2023-06-08 11:09:43 +08:00
jyong
651781f227 add notion table support 2023-06-08 00:26:22 +08:00
jyong
7241253a36 add notion table support 2023-06-07 22:27:18 +08:00
StyleZhang
d3713c5122 feat: setting add notion data source 2023-06-07 17:52:57 +08:00
jyong
c7cbe3ba66 support mutil notion workspace 2023-06-07 16:37:55 +08:00
jyong
ef56fe3176 update notion page title 2023-06-07 15:16:12 +08:00
jyong
8a05f53ca1 update notion response 2023-06-07 10:53:41 +08:00
jyong
c9487caf52 update data source type 2023-06-07 09:34:54 +08:00
jyong
581e906897 clean document when import notion not selected 2023-06-06 23:09:53 +08:00
jyong
b41a476620 merge file and notion indexing-estimate 2023-06-06 21:14:08 +08:00
jyong
e0c1d94fcc add db migrations 2023-06-06 19:59:06 +08:00
jyong
e08af0a69c add redirect_uri 2023-06-06 16:35:57 +08:00
jyong
a1aee4e714 add integration dataset and document sync from notion 2023-06-06 00:27:55 +08:00
Jyong
a842f1c251 add notion sync task 2023-06-05 22:54:01 +08:00
Jyong
6cc4f47d4f add notion sync 2023-06-05 22:18:56 +08:00
Jyong
a5a6119709 Merge branch 'main' into feat/dataset-notion-import
# Conflicts:
#	api/controllers/console/datasets/datasets_document.py
#	api/services/dataset_service.py
2023-06-01 23:36:16 +08:00
Jyong
c77029e63e Merge branch 'main' into feat/dataset-notion-import 2023-06-01 22:45:48 +08:00
Jyong
ff1aadf9d3 add notion sync 2023-06-01 22:36:21 +08:00
Jyong
8c6f5addfd fix notion import bugs 2023-05-30 01:00:05 +08:00
Jyong
1268f3bbfe add data source binding init and check dataset index status 2023-05-28 23:36:47 +08:00
Jyong
42c4ab7344 add data source binding init and check dataset index status 2023-05-28 23:34:23 +08:00
Jyong
f1f5d45d2e support mutil files and notion pages 2023-05-25 23:15:36 +08:00
Jyong
e2ef272f48 support notion import documents 2023-05-25 00:15:54 +08:00
Jyong
201d9943bb Merge branch 'main' into feat/dataset-notion-import 2023-05-23 23:54:50 +08:00
Jyong
3a98c636fd add notion import indexing estimate interface 2023-05-22 23:22:31 +08:00
Jyong
dbd2babb05 notion index estimate 2023-05-22 21:18:58 +08:00
Jyong
d834deceff add data source integrate list api
add disable and enable integrate api
add pre-import notion pages api
2023-05-18 23:48:56 +08:00
Jyong
6e725e2ed4 add data source binding and notion auth and callback 2023-05-18 00:22:08 +08:00
Jyong
f7539ce4c5 add notion auth binding 2023-05-17 00:35:08 +08:00
8 changed files with 289 additions and 201 deletions

View File

@@ -1,5 +1,5 @@
.fileUploader {
@apply mb-9;
@apply mb-6;
}
.fileUploader .title {
@apply mb-2;
@@ -9,14 +9,14 @@
color: #344054;
}
.fileUploader .tip {
@apply mt-2;
font-weight: 400;
font-size: 12px;
line-height: 26px;
line-height: 18px;
color: #667085;
}
.uploader {
@apply relative box-border flex justify-center items-center;
@apply relative box-border flex justify-center items-center mb-2;
flex-direction: column;
max-width: 640px;
height: 80px;
background: #F9FAFB;
@@ -25,7 +25,7 @@
font-weight: 400;
font-size: 14px;
line-height: 20px;
color: #667085;
color: #344054;
}
.uploader.dragging {
background: #F5F8FF;
@@ -38,8 +38,7 @@
width: 100%;
height: 100%;
}
.uploader::before {
content: '';
.uploader .uploadIcon {
display: block;
margin-right: 8px;
width: 24px;
@@ -53,14 +52,16 @@
}
.file {
@apply box-border relative flex items-center;
padding: 21px 24px 21px 64px;
@apply box-border relative flex items-center justify-between;
padding: 8px 12px 8px 8px;
max-width: 640px;
height: 80px;
background: #F9FAFB;
border: 1px solid #F2F4F7;
border-radius: 12px;
height: 40px;
background: #ffffff;
border: 0.5px solid #EAECF0;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
overflow: hidden;
cursor: pointer;
}
.progressbar {
position: absolute;
@@ -69,36 +70,25 @@
height: 100%;
background-color: #F2F4F7;
}
.file:hover {
background: #F5F8FF;
border: 1px solid #D1E0FF;
}
.file:hover .actionWrapper .buttonWrapper {
display: flex;
align-items: center;
}
.file:hover .actionWrapper .divider {
display: block;
}
.file.uploading,
.file.uploading:hover {
background: #FCFCFD;
border: 1px solid #EAECF0;
border: 0.5px solid #EAECF0;
}
.file.uploading:hover .actionWrapper .percent {
padding: 8px;
.file.active {
background: #F5F8FF;
border: 1px solid #D1E0FF;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
}
.file.uploading:hover .actionWrapper .buttonWrapper {
display: flex;
align-items: center;
.file:hover {
background: #F5F8FF;
border: 1px solid #D1E0FF;
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
}
.fileIcon {
@apply w-8 h-8 bg-center bg-no-repeat;
position: absolute;
top: 24px;
left: 24px;
@apply shrink-0 w-6 h-6 mr-2 bg-center bg-no-repeat;
background-image: url(../assets/unknow.svg);
background-size: 32px;
background-size: 24px;
}
.fileIcon.csv {
background-image: url(../assets/csv.svg);
@@ -126,7 +116,7 @@
background-image: url(../assets/json.svg);
}
.fileInfo {
@apply grow;
@apply grow flex items-center;
z-index: 1;
overflow: hidden;
text-overflow: ellipsis;
@@ -134,46 +124,35 @@
}
.filename {
font-weight: 500;
font-size: 14px;
line-height: 20px;
}
.name {
font-size: 13px;
line-height: 18px;
color: #1D2939;
line-height: 20px;
}
.extension {
color: #667085;
line-height: 20px;
}
.fileExtraInfo {
color: #667085;
.size {
@apply ml-3;
font-weight: 400;
font-size: 12px;
line-height: 18px;
color: #667085;
}
.actionWrapper {
@apply flex items-center shrink-0;
z-index: 1;
}
.actionWrapper .percent {
font-size: 16px;
line-height: 24px;
font-weight: 400;
font-size: 13px;
line-height: 18px;
color: #344054;
}
.actionWrapper .divider {
display: none;
margin: 0 8px;
width: 1px;
height: 16px;
background: #FEE4E2;
}
.actionWrapper .remove {
width: 32px;
height: 32px;
display: none;
width: 24px;
height: 24px;
background: center no-repeat url(../assets/trash.svg);
background-size: 16px;
cursor: pointer;
}
.actionWrapper .buttonWrapper {
@apply flex items-center;
display: none;
.file:hover .actionWrapper .remove {
display: block;
}

View File

@@ -6,14 +6,15 @@ import cn from 'classnames'
import s from './index.module.css'
import type { File as FileEntity } from '@/models/datasets'
import { ToastContext } from '@/app/components/base/toast'
import Button from '@/app/components/base/button'
import { upload } from '@/service/base'
type IFileUploaderProps = {
file?: FileEntity
fileList: FileEntity[]
prepareFileList: (files: any[]) => void
onFileUpdate: (fileItem: any, progress: number, list: any[]) => void
onPreview: (file: FileEntity) => void
titleClassName?: string
onFileUpdate: (file?: FileEntity) => void
}
const ACCEPTS = [
@@ -29,8 +30,15 @@ const ACCEPTS = [
]
const MAX_SIZE = 15 * 1024 * 1024
const BATCH_COUNT = 5
const FileUploader = ({ file, onFileUpdate, titleClassName }: IFileUploaderProps) => {
const FileUploader = ({
fileList,
prepareFileList,
onFileUpdate,
onPreview,
titleClassName,
}: IFileUploaderProps) => {
const { t } = useTranslation()
const { notify } = useContext(ToastContext)
const [dragging, setDragging] = useState(false)
@@ -42,6 +50,9 @@ const FileUploader = ({ file, onFileUpdate, titleClassName }: IFileUploaderProps
const [uploading, setUploading] = useState(false)
const [percent, setPercent] = useState(0)
// TODO
const fileListRef = useRef<any>(null)
// utils
const getFileType = (currentFile: File) => {
if (!currentFile)
@@ -50,10 +61,6 @@ const FileUploader = ({ file, onFileUpdate, titleClassName }: IFileUploaderProps
const arr = currentFile.name.split('.')
return arr[arr.length - 1]
}
const getFileName = (name: string) => {
const arr = name.split('.')
return arr.slice(0, -1).join()
}
const getFileSize = (size: number) => {
if (size / 1024 < 10)
return `${(size / 1024).toFixed(2)}KB`
@@ -77,6 +84,7 @@ const FileUploader = ({ file, onFileUpdate, titleClassName }: IFileUploaderProps
const onProgress = useCallback((e: ProgressEvent) => {
if (e.lengthComputable) {
const percent = Math.floor(e.loaded / e.total * 100)
// updateFileItem
setPercent(percent)
}
}, [setPercent])
@@ -84,42 +92,93 @@ const FileUploader = ({ file, onFileUpdate, titleClassName }: IFileUploaderProps
const currentXHR = uploadPromise.current
currentXHR.abort()
}
const fileUpload = async (file?: File) => {
if (!file)
return
const selectHandle = () => {
if (fileUploader.current)
fileUploader.current.click()
}
// TODO
const removeFile = () => {
if (fileUploader.current)
fileUploader.current.value = ''
if (!isValid(file))
return
setCurrentFile(undefined)
// onFileUpdate()
}
setCurrentFile(file)
setUploading(true)
const fileUpload = (fileItem: any) => {
const fileListCopy = fileListRef.current
const formData = new FormData()
formData.append('file', file)
// store for abort
const currentXHR = new XMLHttpRequest()
uploadPromise.current = currentXHR
try {
const result = await upload({
xhr: currentXHR,
data: formData,
onprogress: onProgress,
}) as FileEntity
onFileUpdate(result)
setUploading(false)
}
catch (xhr: any) {
setUploading(false)
// abort handle
if (xhr.readyState === 0 && xhr.status === 0) {
if (fileUploader.current)
fileUploader.current.value = ''
setCurrentFile(undefined)
return
formData.append('file', fileItem.file)
const onProgress = (e: ProgressEvent) => {
if (e.lengthComputable) {
const percent = Math.floor(e.loaded / e.total * 100)
onFileUpdate(fileItem, percent, fileListCopy)
}
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.failed') })
}
console.log('fff1', fileListCopy)
return upload({
xhr: new XMLHttpRequest(),
data: formData,
onprogress: onProgress,
})
.then((res: FileEntity) => {
const completeFile = {
fileID: fileItem.fileID,
file: res,
}
console.log('fff2', fileListCopy)
onFileUpdate(completeFile, 100, fileListCopy)
return Promise.resolve({ ...completeFile })
})
.catch((err) => {
console.log(err)
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.failed') })
onFileUpdate(fileItem, -2, fileListCopy)
return Promise.resolve({ ...fileItem })
})
.finally()
}
const uploadBatchFiles = (bFiles: any) => {
bFiles.forEach((bf: any) => (bf.progress = 0))
return Promise.all(bFiles.map((bFile: any) => fileUpload(bFile)))
}
const uploadMultipleFiles = async (files: any) => {
const length = files.length
let start = 0
let end = 0
while (start < length) {
if (start + BATCH_COUNT > length)
end = length
else
end = start + BATCH_COUNT
const bFiles = files.slice(start, end)
await uploadBatchFiles(bFiles)
start = end
}
}
const initialUpload = (files: any) => {
if (!files.length)
return false
const preparedFiles = files.map((file: any, index: number) => {
const fileItem = {
fileID: `file${index}-${Date.now()}`,
file,
progress: -1,
}
return fileItem
})
prepareFileList(preparedFiles)
// TODO fix filelist copy
fileListRef.current = preparedFiles
uploadMultipleFiles(preparedFiles)
}
const fileChangeHandle = (e: React.ChangeEvent<HTMLInputElement>) => {
const files = [...(e.target.files ?? [])].filter(file => isValid(file))
initialUpload(files)
}
const handleDragEnter = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
@@ -134,6 +193,7 @@ const FileUploader = ({ file, onFileUpdate, titleClassName }: IFileUploaderProps
e.stopPropagation()
e.target === dragRef.current && setDragging(false)
}
// TODO
const handleDrop = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
@@ -150,23 +210,6 @@ const FileUploader = ({ file, onFileUpdate, titleClassName }: IFileUploaderProps
fileUpload(files[0])
}
const selectHandle = () => {
if (fileUploader.current)
fileUploader.current.click()
}
const removeFile = () => {
if (fileUploader.current)
fileUploader.current.value = ''
setCurrentFile(undefined)
onFileUpdate()
}
const fileChangeHandle = (e: React.ChangeEvent<HTMLInputElement>) => {
const currentFile = e.target.files?.[0]
onFileUpdate()
fileUpload(currentFile)
}
useEffect(() => {
dropRef.current?.addEventListener('dragenter', handleDragEnter)
dropRef.current?.addEventListener('dragover', handleDragOver)
@@ -184,83 +227,107 @@ const FileUploader = ({ file, onFileUpdate, titleClassName }: IFileUploaderProps
<div className={s.fileUploader}>
<input
ref={fileUploader}
id="fileUploader"
style={{ display: 'none' }}
type="file"
id="fileUploader"
multiple
accept={ACCEPTS.join(',')}
onChange={fileChangeHandle}
/>
<div className={cn(s.title, titleClassName)}>{t('datasetCreation.stepOne.uploader.title')}</div>
<div ref={dropRef}>
{!currentFile && !file && (
<div className={cn(s.uploader, dragging && s.dragging)}>
<span>{t('datasetCreation.stepOne.uploader.button')}</span>
<label className={s.browse} onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.browse')}</label>
{dragging && <div ref={dragRef} className={s.draggingCover}/>}
<div ref={dropRef} className={cn(s.uploader, dragging && s.dragging)}>
<div className='flex justify-center items-center h-6 mb-2'>
<span className={s.uploadIcon}/>
<span>{t('datasetCreation.stepOne.uploader.button')}</span>
<label className={s.browse} onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.browse')}</label>
</div>
<div className={s.tip}>{t('datasetCreation.stepOne.uploader.tip')}</div>
{dragging && <div ref={dragRef} className={s.draggingCover}/>}
</div>
<div className={s.fileList}>
{fileList.map(fileItem => (
<div
// onClick={() => onPreview(currentFile)}
className={cn(
s.file,
fileItem.progress < 100 && s.uploading,
// s.active,
)}
>
{fileItem.progress < 100 && (
<div className={s.progressbar} style={{ width: `${percent}%` }}/>
)}
<div className={s.fileInfo}>
<div className={cn(s.fileIcon, s[getFileType(fileItem.file)])}/>
<div className={s.filename}>{fileItem.file.name}</div>
<div className={s.size}>{getFileSize(fileItem.file.size)}</div>
</div>
<div className={s.actionWrapper}>
{fileItem.progress < 100 && (
<div className={s.percent}>{`${fileItem.progress}%`}</div>
)}
{fileItem.progress === 100 && (
<div className={s.remove} onClick={removeFile}/>
)}
</div>
</div>
))}
{currentFile && (
<div
// onClick={() => onPreview(currentFile)}
className={cn(
s.file,
uploading && s.uploading,
// s.active,
)}
>
{uploading && (
<div className={s.progressbar} style={{ width: `${percent}%` }}/>
)}
<div className={s.fileInfo}>
<div className={cn(s.fileIcon, s[getFileType(currentFile)])}/>
<div className={s.filename}>{currentFile.name}</div>
<div className={s.size}>{getFileSize(currentFile.size)}</div>
</div>
<div className={s.actionWrapper}>
{uploading && (
<div className={s.percent}>{`${percent}%`}</div>
)}
{!uploading && (
<div className={s.remove} onClick={removeFile}/>
)}
</div>
</div>
)}
</div>
{currentFile && (
<div className={cn(s.file, uploading && s.uploading)}>
{/* TODO */}
{false && !currentFile && fileList[0] && (
<div
// onClick={() => onPreview(currentFile)}
className={cn(
s.file,
uploading && s.uploading,
s.active,
)}
>
{uploading && (
<div className={s.progressbar} style={{ width: `${percent}%` }}/>
)}
<div className={cn(s.fileIcon, s[getFileType(currentFile)])}/>
<div className={s.fileInfo}>
<div className={s.filename}>
<span className={s.name}>{getFileName(currentFile.name)}</span>
<span className={s.extension}>{`.${getFileType(currentFile)}`}</span>
</div>
<div className={s.fileExtraInfo}>
<span className={s.size}>{getFileSize(currentFile.size)}</span>
<span className={s.error}></span>
</div>
<div className={cn(s.fileIcon, s[getFileType(fileList[0])])}/>
<div className={s.filename}>{fileList[0].name}</div>
<div className={s.size}>{getFileSize(fileList[0].size)}</div>
</div>
<div className={s.actionWrapper}>
{uploading && (
<>
<div className={s.percent}>{`${percent}%`}</div>
<div className={s.divider}/>
<div className={s.buttonWrapper}>
<Button className={cn(s.button, 'ml-2 !h-8 bg-white')} onClick={abort}>{t('datasetCreation.stepOne.uploader.cancel')}</Button>
</div>
</>
<div className={s.percent}>{`${percent}%`}</div>
)}
{!uploading && (
<>
<div className={s.buttonWrapper}>
<Button className={cn(s.button, 'ml-2 !h-8 bg-white')} onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.change')}</Button>
<div className={s.divider}/>
<div className={s.remove} onClick={removeFile}/>
</div>
</>
<div className={s.remove} onClick={removeFile}/>
)}
</div>
</div>
)}
{!currentFile && file && (
<div className={cn(s.file)}>
<div className={cn(s.fileIcon, s[file.extension])}/>
<div className={s.fileInfo}>
<div className={s.filename}>
<span className={s.name}>{getFileName(file.name)}</span>
<span className={s.extension}>{`.${file.extension}`}</span>
</div>
<div className={s.fileExtraInfo}>
<span className={s.size}>{getFileSize(file.size)}</span>
<span className={s.error}></span>
</div>
</div>
<div className={s.actionWrapper}>
<div className={s.buttonWrapper}>
<Button className={cn(s.button, 'ml-2 !h-8 bg-white')} onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.change')}</Button>
<div className={s.divider}/>
<div className={s.remove} onClick={removeFile}/>
</div>
</div>
</div>
)}
<div className={s.tip}>{t('datasetCreation.stepOne.uploader.tip')}</div>
</div>
)
}

View File

@@ -8,7 +8,7 @@ import StepOne from './step-one'
import StepTwo from './step-two'
import StepThree from './step-three'
import { DataSourceType } from '@/models/datasets'
import type { DataSet, File, createDocumentResponse } from '@/models/datasets'
import type { DataSet, createDocumentResponse } from '@/models/datasets'
import { fetchDataSource, fetchTenantInfo } from '@/service/common'
import { fetchDataDetail } from '@/service/datasets'
import type { DataSourceNotionPage } from '@/models/common'
@@ -30,7 +30,7 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
const [dataSourceType, setDataSourceType] = useState<DataSourceType>(DataSourceType.FILE)
const [step, setStep] = useState(1)
const [indexingTypeCache, setIndexTypeCache] = useState('')
const [file, setFile] = useState<File | undefined>()
const [fileList, setFiles] = useState<any[]>([])
const [result, setResult] = useState<createDocumentResponse | undefined>()
const [hasError, setHasError] = useState(false)
@@ -39,9 +39,20 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
setNotionPages(value)
}
const updateFile = (file?: File) => {
setFile(file)
// TODO
const updateFileList = (preparedFiles: any) => {
console.log('preparedFiles', preparedFiles)
setFiles(preparedFiles)
}
const updateFile = (fileItem: any, progress: number, list: any[]) => {
const targetIndex = list.findIndex((file: any) => file.fileID === fileItem.fileID)
list[targetIndex] = {
...fileItem,
progress,
}
setFiles([...list])
}
const updateIndexingTypeCache = (type: string) => {
setIndexTypeCache(type)
}
@@ -104,7 +115,8 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
dataSourceType={dataSourceType}
dataSourceTypeDisable={!!detail?.data_source_type}
changeType={setDataSourceType}
file={file}
files={fileList}
updateFileList={updateFileList}
updateFile={updateFile}
notionPages={notionPages}
updateNotionPages={updateNotionPages}
@@ -116,7 +128,7 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
indexingType={detail?.indexing_technique || ''}
datasetId={datasetId}
dataSourceType={dataSourceType}
file={file}
files={fileList}
notionPages={notionPages}
onStepChange={changeStep}
updateIndexingTypeCache={updateIndexingTypeCache}

View File

@@ -1,5 +1,5 @@
'use client'
import React, { useState } from 'react'
import React, { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import cn from 'classnames'
import FilePreview from '../file-preview'
@@ -16,12 +16,13 @@ import { useDatasetDetailContext } from '@/context/dataset-detail'
type IStepOneProps = {
datasetId?: string
dataSourceType?: DataSourceType
dataSourceType: DataSourceType
dataSourceTypeDisable: Boolean
hasConnection: boolean
onSetting: () => void
file?: File
updateFile: (file?: File) => void
files: any[]
updateFileList: (files: any[]) => void
updateFile: (fileItem: any, progress: number, list: any[]) => void
notionPages?: any[]
updateNotionPages: (value: any[]) => void
onStepChange: () => void
@@ -54,11 +55,13 @@ const StepOne = ({
hasConnection,
onSetting,
onStepChange,
file,
files,
updateFileList,
updateFile,
notionPages = [],
updateNotionPages,
}: IStepOneProps) => {
const [currentFile, setCurrentFile] = useState<File | undefined>()
const { dataset } = useDatasetDetailContext()
const [showModal, setShowModal] = useState(false)
const [showFilePreview, setShowFilePreview] = useState(true)
@@ -68,17 +71,32 @@ const StepOne = ({
const hidePreview = () => setShowFilePreview(false)
const modalShowHandle = () => setShowModal(true)
const modalCloseHandle = () => setShowModal(false)
const updateCurrentFile = (file: File) => {
setCurrentFile(file)
}
const hideFilePreview = () => {
setCurrentNotionPage(undefined)
}
const updateCurrentPage = (page: Page) => {
setCurrentNotionPage(page)
}
const hideNotionPagePreview = () => {
setCurrentNotionPage(undefined)
}
// TODO
const nextDisabled = useMemo(() => {
if (!files.length)
return true
console.log(files)
console.log(files.some(file => file.progress !== 100))
if (files.some(file => file.progress !== 100))
return true
return false
}, [files])
const shouldShowDataSourceTypeList = !datasetId || (datasetId && !dataset?.data_source_type)
return (
@@ -103,7 +121,8 @@ const StepOne = ({
if (dataSourceTypeDisable)
return
changeType(DataSourceType.FILE)
hidePreview()
hideFilePreview()
hideNotionPagePreview()
}}
>
<span className={cn(s.datasetIcon)} />
@@ -119,7 +138,8 @@ const StepOne = ({
if (dataSourceTypeDisable)
return
changeType(DataSourceType.NOTION)
hidePreview()
hideFilePreview()
hideNotionPagePreview()
}}
>
<span className={cn(s.datasetIcon, s.notion)} />
@@ -138,8 +158,14 @@ const StepOne = ({
}
{dataSourceType === DataSourceType.FILE && (
<>
<FileUploader onFileUpdate={updateFile} file={file} titleClassName={(!shouldShowDataSourceTypeList) ? 'mt-[30px] !mb-[44px] !text-lg !font-semibold !text-gray-900' : undefined} />
<Button disabled={!file} className={s.submitButton} type='primary' onClick={onStepChange}>{t('datasetCreation.stepOne.button')}</Button>
<FileUploader
fileList={files}
prepareFileList={updateFileList}
onFileUpdate={updateFile}
onPreview={updateCurrentFile}
titleClassName={(!shouldShowDataSourceTypeList) ? 'mt-[30px] !mb-[44px] !text-lg !font-semibold !text-gray-900' : undefined}
/>
<Button disabled={nextDisabled} className={s.submitButton} type='primary' onClick={onStepChange}>{t('datasetCreation.stepOne.button')}</Button>
</>
)}
{dataSourceType === DataSourceType.NOTION && (
@@ -164,7 +190,7 @@ const StepOne = ({
</div>
<EmptyDatasetCreationModal show={showModal} onHide={modalCloseHandle} />
</div>
{file && showFilePreview && <FilePreview file={file} hidePreview={hidePreview} />}
{currentFile && <FilePreview file={currentFile} hidePreview={hideFilePreview} />}
{currentNotionPage && <NotionPagePreview currentPage={currentNotionPage} hidePreview={hideNotionPagePreview} />}
</div>
)

View File

@@ -36,7 +36,7 @@ type StepTwoProps = {
datasetId?: string
indexingType?: string
dataSourceType: DataSourceType
file?: File
files: File[]
notionPages?: Page[]
onStepChange?: (delta: number) => void
updateIndexingTypeCache?: (type: string) => void
@@ -62,7 +62,7 @@ const StepTwo = ({
datasetId,
indexingType,
dataSourceType,
file,
files,
notionPages = [],
onStepChange,
updateIndexingTypeCache,
@@ -212,8 +212,7 @@ const StepTwo = ({
info_list: {
data_source_type: dataSourceType,
file_info_list: {
// TODO multi files
file_ids: [file?.id || ''],
file_ids: files.map(file => file.id),
},
},
indexing_technique: getIndexing_technique(),
@@ -254,8 +253,7 @@ const StepTwo = ({
} as CreateDocumentReq
if (dataSourceType === DataSourceType.FILE) {
params.data_source.info_list.file_info_list = {
// TODO multi files
file_ids: [file?.id || ''],
file_ids: files.map(file => file.id),
}
}
if (dataSourceType === DataSourceType.NOTION)
@@ -529,15 +527,21 @@ const StepTwo = ({
<Link className='text-[#155EEF]' href={`/datasets/${datasetId}/settings`}>{t('datasetCreation.stepTwo.datasetSettingLink')}</Link>
</div>
)}
{/* TODO multi files */}
<div className={s.source}>
<div className={s.sourceContent}>
{dataSourceType === DataSourceType.FILE && (
<>
<div className='mb-2 text-xs font-medium text-gray-500'>{t('datasetCreation.stepTwo.fileSource')}</div>
<div className='flex items-center text-sm leading-6 font-medium text-gray-800'>
<span className={cn(s.fileIcon, file && s[file.extension])} />
{getFileName(file?.name || '')}
<span className={cn(s.fileIcon, files.length && s[files[0].extension])} />
{getFileName(files[0].name || '')}
{files.length > 1 && (
<span className={s.sourceCount}>
<span>{t('datasetCreation.stepTwo.other')}</span>
<span>{files.length - 1}</span>
<span>{t('datasetCreation.stepTwo.fileUnit')}</span>
</span>
)}
</div>
</>
)}

View File

@@ -85,7 +85,7 @@ const DocumentSettings = ({ datasetId, documentId }: DocumentSettingsProps) => {
indexingType={indexingTechnique || ''}
isSetting
documentDetail={documentDetail}
file={documentDetail.data_source_info.upload_file}
files={[documentDetail.data_source_info.upload_file]}
onSave={saveHandler}
onCancel={cancelHandler}
/>

View File

@@ -23,7 +23,7 @@ const translation = {
title: 'Upload text file',
button: 'Drag and drop file, or',
browse: 'Browse',
tip: 'Supports txt, html, markdown, xlsx, and pdf.',
tip: 'Supports txt, html, markdown, xlsx, and pdf. Max 10MB each.',
validation: {
typeError: 'File type not supported',
size: 'File too large. Maximum is 15MB',

View File

@@ -23,7 +23,7 @@ const translation = {
title: '上传文本文件',
button: '拖拽文件至此,或者',
browse: '选择文件',
tip: '已支持 TXT, HTML, Markdown, PDF, XLSX',
tip: '已支持 TXT HTML Markdown PDF XLSX,每个文件不超过 10 MB。',
validation: {
typeError: '文件类型不支持',
size: '文件太大了,不能超过 15MB',