Unverified Commit df26f825 authored by crazywoola's avatar crazywoola Committed by GitHub

Feature/support xlsx (#311)

parent dbe0c435
<svg width="24" height="26" viewBox="0 0 24 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_5938_919)">
<path d="M3 5.8C3 4.11984 3 3.27976 3.32698 2.63803C3.6146 2.07354 4.07354 1.6146 4.63803 1.32698C5.27976 1 6.11984 1 7.8 1H14L21 8V18.2C21 19.8802 21 20.7202 20.673 21.362C20.3854 21.9265 19.9265 22.3854 19.362 22.673C18.7202 23 17.8802 23 16.2 23H7.8C6.11984 23 5.27976 23 4.63803 22.673C4.07354 22.3854 3.6146 21.9265 3.32698 21.362C3 20.7202 3 19.8802 3 18.2V5.8Z" fill="#169951"/>
</g>
<g opacity="0.96">
<path d="M9.81332 16.4181C9.63132 17.5171 8.86832 18.0421 7.92332 18.0421C7.34232 18.0421 6.90132 17.8461 6.53732 17.4821C6.01232 16.9571 6.03332 16.2571 6.03332 15.5081C6.03332 14.7591 6.01232 14.0591 6.53732 13.5341C6.90132 13.1701 7.34232 12.9741 7.92332 12.9741C8.86832 12.9741 9.63132 13.4991 9.81332 14.5981H8.56732C8.49032 14.3181 8.33632 14.0661 7.93032 14.0661C7.70632 14.0661 7.53832 14.1571 7.44732 14.2761C7.33532 14.4231 7.25832 14.5981 7.25832 15.5081C7.25832 16.4181 7.33532 16.5931 7.44732 16.7401C7.53832 16.8591 7.70632 16.9501 7.93032 16.9501C8.33632 16.9501 8.49032 16.6981 8.56732 16.4181H9.81332Z" fill="white"/>
<path d="M13.8059 16.4741C13.8059 17.4891 12.9309 18.0421 11.8809 18.0421C11.1179 18.0421 10.4949 17.9021 9.99094 17.3841L10.7749 16.6001C11.0339 16.8591 11.4889 16.9501 11.8879 16.9501C12.3709 16.9501 12.6019 16.7891 12.6019 16.5021C12.6019 16.3831 12.5739 16.2851 12.5039 16.2081C12.4409 16.1451 12.3359 16.0961 12.1749 16.0751L11.5729 15.9911C11.1319 15.9281 10.7959 15.7811 10.5719 15.5501C10.3409 15.3121 10.2289 14.9761 10.2289 14.5491C10.2289 13.6391 10.9149 12.9741 12.0489 12.9741C12.7629 12.9741 13.3019 13.1421 13.7289 13.5691L12.9589 14.3391C12.6439 14.0241 12.2309 14.0451 12.0139 14.0451C11.5869 14.0451 11.4119 14.2901 11.4119 14.5071C11.4119 14.5701 11.4329 14.6611 11.5099 14.7381C11.5729 14.8011 11.6779 14.8641 11.8529 14.8851L12.4549 14.9691C12.9029 15.0321 13.2249 15.1721 13.4349 15.3821C13.7009 15.6411 13.8059 16.0121 13.8059 16.4741Z" fill="white"/>
<path d="M18.3124 13.0161L16.6604 18.0001H15.7504L14.1054 13.0161H15.3724L16.2124 15.8021L17.0384 13.0161H18.3124Z" fill="white"/>
</g>
<path opacity="0.5" d="M14 1L21 8H16C14.8954 8 14 7.10457 14 6V1Z" fill="white"/>
<defs>
<filter id="filter0_d_5938_919" x="1" y="0" width="22" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5938_919"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5938_919" result="shape"/>
</filter>
</defs>
</svg>
<svg width="24" height="26" viewBox="0 0 24 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_5938_927)">
<path d="M3 5.8C3 4.11984 3 3.27976 3.32698 2.63803C3.6146 2.07354 4.07354 1.6146 4.63803 1.32698C5.27976 1 6.11984 1 7.8 1H14L21 8V18.2C21 19.8802 21 20.7202 20.673 21.362C20.3854 21.9265 19.9265 22.3854 19.362 22.673C18.7202 23 17.8802 23 16.2 23H7.8C6.11984 23 5.27976 23 4.63803 22.673C4.07354 22.3854 3.6146 21.9265 3.32698 21.362C3 20.7202 3 19.8802 3 18.2V5.8Z" fill="#169951"/>
</g>
<path opacity="0.5" d="M14 1L21 8H16C14.8954 8 14 7.10457 14 6V1Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 12C17.5523 12 18 12.4477 18 13V18C18 18.5523 17.5523 19 17 19H7C6.44772 19 6 18.5523 6 18V13C6 12.4477 6.44772 12 7 12H17ZM11.5 13H7L7 15H11.5V13ZM12.5 18H17V16H12.5V18ZM11.5 16V18H7L7 16H11.5ZM12.5 15H17V13H12.5V15Z" fill="white" fill-opacity="0.96"/>
<defs>
<filter id="filter0_d_5938_927" x="1" y="0" width="22" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5938_927"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5938_927" result="shape"/>
</filter>
</defs>
</svg>
...@@ -100,6 +100,14 @@ ...@@ -100,6 +100,14 @@
background-image: url(../assets/unknow.svg); background-image: url(../assets/unknow.svg);
background-size: 32px; background-size: 32px;
} }
.fileIcon.csv {
background-image: url(../assets/csv.svg);
}
.fileIcon.xlsx,
.fileIcon.xls {
background-image: url(../assets/xlsx.svg);
}
.fileIcon.pdf { .fileIcon.pdf {
background-image: url(../assets/pdf.svg); background-image: url(../assets/pdf.svg);
} }
...@@ -168,4 +176,4 @@ ...@@ -168,4 +176,4 @@
.actionWrapper .buttonWrapper { .actionWrapper .buttonWrapper {
@apply flex items-center; @apply flex items-center;
display: none; display: none;
} }
\ No newline at end of file
'use client' 'use client'
import React, { useState, useRef, useEffect, useCallback } from 'react' import React, { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import type { File as FileEntity } from '@/models/datasets'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
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 { ToastContext } from '@/app/components/base/toast'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { upload } from '@/service/base' import { upload } from '@/service/base'
import cn from 'classnames'
import s from './index.module.css'
type IFileUploaderProps = { type IFileUploaderProps = {
file?: FileEntity; file?: FileEntity
onFileUpdate: (file?: FileEntity) => void; onFileUpdate: (file?: FileEntity) => void
} }
const ACCEPTS = [ const ACCEPTS = [
...@@ -23,9 +22,12 @@ const ACCEPTS = [ ...@@ -23,9 +22,12 @@ const ACCEPTS = [
'.md', '.md',
'.markdown', '.markdown',
'.txt', '.txt',
'.xls',
'.xlsx',
'.csv',
] ]
const MAX_SIZE = 15 * 1024 *1024 const MAX_SIZE = 15 * 1024 * 1024
const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => { const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -39,60 +41,55 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => { ...@@ -39,60 +41,55 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => {
const [uploading, setUploading] = useState(false) const [uploading, setUploading] = useState(false)
const [percent, setPercent] = useState(0) const [percent, setPercent] = useState(0)
const handleDragEnter = (e: DragEvent) => { // utils
e.preventDefault() const getFileType = (currentFile: File) => {
e.stopPropagation() if (!currentFile)
e.target !== dragRef.current && setDragging(true) return ''
}
const handleDragOver = (e: DragEvent) => { const arr = currentFile.name.split('.')
e.preventDefault() return arr[arr.length - 1]
e.stopPropagation()
} }
const handleDragLeave = (e: DragEvent) => { const getFileName = (name: string) => {
e.preventDefault() const arr = name.split('.')
e.stopPropagation() return arr.slice(0, -1).join()
e.target === dragRef.current && setDragging(false)
} }
const handleDrop = (e: DragEvent) => { const getFileSize = (size: number) => {
e.preventDefault() if (size / 1024 < 10)
e.stopPropagation() return `${(size / 1024).toFixed(2)}KB`
setDragging(false)
if (!e.dataTransfer) { return `${(size / 1024 / 1024).toFixed(2)}MB`
return
}
const files = [...e.dataTransfer.files]
if (files.length > 1) {
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.count') })
return;
}
onFileUpdate()
fileUpload(files[0])
} }
const selectHandle = () => { const isValid = (file: File) => {
if (fileUploader.current) { const { size } = file
fileUploader.current.click(); const ext = `.${getFileType(file)}`
} const isValidType = ACCEPTS.includes(ext)
if (!isValidType)
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.typeError') })
const isValidSize = size <= MAX_SIZE
if (!isValidSize)
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.size') })
return isValidType && isValidSize
} }
const removeFile = () => { const onProgress = useCallback((e: ProgressEvent) => {
if (fileUploader.current) { if (e.lengthComputable) {
fileUploader.current.value = '' const percent = Math.floor(e.loaded / e.total * 100)
setPercent(percent)
} }
setCurrentFile(undefined) }, [setPercent])
onFileUpdate() const abort = () => {
} const currentXHR = uploadPromise.current
const fileChangeHandle = (e: React.ChangeEvent<HTMLInputElement>) => { currentXHR.abort()
const currentFile = e.target.files?.[0]
onFileUpdate()
fileUpload(currentFile)
} }
const fileUpload = async (file?: File) => { const fileUpload = async (file?: File) => {
if (!file) { if (!file)
return return
}
if (!isValid(file)) { if (!isValid(file))
return return
}
setCurrentFile(file) setCurrentFile(file)
setUploading(true) setUploading(true)
const formData = new FormData() const formData = new FormData()
...@@ -105,7 +102,7 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => { ...@@ -105,7 +102,7 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => {
xhr: currentXHR, xhr: currentXHR,
data: formData, data: formData,
onprogress: onProgress, onprogress: onProgress,
}) as FileEntity; }) as FileEntity
onFileUpdate(result) onFileUpdate(result)
setUploading(false) setUploading(false)
} }
...@@ -113,69 +110,72 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => { ...@@ -113,69 +110,72 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => {
setUploading(false) setUploading(false)
// abort handle // abort handle
if (xhr.readyState === 0 && xhr.status === 0) { if (xhr.readyState === 0 && xhr.status === 0) {
if (fileUploader.current) { if (fileUploader.current)
fileUploader.current.value = '' fileUploader.current.value = ''
}
setCurrentFile(undefined) setCurrentFile(undefined)
return return
} }
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.failed') }) notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.failed') })
return
} }
} }
const onProgress = useCallback((e: ProgressEvent) => { const handleDragEnter = (e: DragEvent) => {
if (e.lengthComputable) { e.preventDefault()
const percent = Math.floor(e.loaded / e.total * 100) e.stopPropagation()
setPercent(percent) e.target !== dragRef.current && setDragging(true)
} }
}, [setPercent]) const handleDragOver = (e: DragEvent) => {
const abort = () => { e.preventDefault()
const currentXHR = uploadPromise.current e.stopPropagation()
currentXHR.abort();
} }
const handleDragLeave = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
e.target === dragRef.current && setDragging(false)
}
const handleDrop = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
setDragging(false)
if (!e.dataTransfer)
return
// utils const files = [...e.dataTransfer.files]
const getFileType = (currentFile: File) => { if (files.length > 1) {
if (!currentFile) { notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.count') })
return '' return
} }
const arr = currentFile.name.split('.') onFileUpdate()
return arr[arr.length-1] fileUpload(files[0])
} }
const getFileName = (name: string) => {
const arr = name.split('.') const selectHandle = () => {
return arr.slice(0, -1).join() if (fileUploader.current)
fileUploader.current.click()
} }
const getFileSize = (size: number) => { const removeFile = () => {
if (size / 1024 < 10) { if (fileUploader.current)
return `${(size / 1024).toFixed(2)}KB` fileUploader.current.value = ''
}
return `${(size / 1024 / 1024).toFixed(2)}MB` setCurrentFile(undefined)
onFileUpdate()
} }
const isValid = (file: File) => { const fileChangeHandle = (e: React.ChangeEvent<HTMLInputElement>) => {
const { size } = file const currentFile = e.target.files?.[0]
const ext = `.${getFileType(file)}` onFileUpdate()
const isValidType = ACCEPTS.includes(ext) fileUpload(currentFile)
if (!isValidType) {
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.typeError') })
}
const isValidSize = size <= MAX_SIZE;
if (!isValidSize) {
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.size') })
}
return isValidType && isValidSize;
} }
useEffect(() => { useEffect(() => {
dropRef.current?.addEventListener('dragenter', handleDragEnter); dropRef.current?.addEventListener('dragenter', handleDragEnter)
dropRef.current?.addEventListener('dragover', handleDragOver); dropRef.current?.addEventListener('dragover', handleDragOver)
dropRef.current?.addEventListener('dragleave', handleDragLeave); dropRef.current?.addEventListener('dragleave', handleDragLeave)
dropRef.current?.addEventListener('drop', handleDrop); dropRef.current?.addEventListener('drop', handleDrop)
return () => { return () => {
dropRef.current?.removeEventListener('dragenter', handleDragEnter); dropRef.current?.removeEventListener('dragenter', handleDragEnter)
dropRef.current?.removeEventListener('dragover', handleDragOver); dropRef.current?.removeEventListener('dragover', handleDragOver)
dropRef.current?.removeEventListener('dragleave', handleDragLeave); dropRef.current?.removeEventListener('dragleave', handleDragLeave)
dropRef.current?.removeEventListener('drop', handleDrop); dropRef.current?.removeEventListener('drop', handleDrop)
} }
}, []) }, [])
...@@ -202,7 +202,7 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => { ...@@ -202,7 +202,7 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => {
{currentFile && ( {currentFile && (
<div className={cn(s.file, uploading && s.uploading)}> <div className={cn(s.file, uploading && s.uploading)}>
{uploading && ( {uploading && (
<div className={s.progressbar} style={{ width: `${percent}%`}}/> <div className={s.progressbar} style={{ width: `${percent}%` }}/>
)} )}
<div className={cn(s.fileIcon, s[getFileType(currentFile)])}/> <div className={cn(s.fileIcon, s[getFileType(currentFile)])}/>
<div className={s.fileInfo}> <div className={s.fileInfo}>
...@@ -264,4 +264,4 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => { ...@@ -264,4 +264,4 @@ const FileUploader = ({ file, onFileUpdate }: IFileUploaderProps) => {
) )
} }
export default FileUploader; export default FileUploader
...@@ -292,6 +292,15 @@ ...@@ -292,6 +292,15 @@
background-image: url(../assets/pdf.svg); background-image: url(../assets/pdf.svg);
} }
.fileIcon.csv {
background-image: url(../assets/csv.svg);
}
.fileIcon.xlsx,
.fileIcon.xls {
background-image: url(../assets/xlsx.svg);
}
.fileIcon.html, .fileIcon.html,
.fileIcon.htm { .fileIcon.htm {
background-image: url(../assets/html.svg); background-image: url(../assets/html.svg);
...@@ -379,4 +388,4 @@ ...@@ -379,4 +388,4 @@
line-height: 28px; line-height: 28px;
color: #101828; color: #101828;
z-index: 10; z-index: 10;
} }
\ No newline at end of file
<svg width="24" height="26" viewBox="0 0 24 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_5938_919)">
<path d="M3 5.8C3 4.11984 3 3.27976 3.32698 2.63803C3.6146 2.07354 4.07354 1.6146 4.63803 1.32698C5.27976 1 6.11984 1 7.8 1H14L21 8V18.2C21 19.8802 21 20.7202 20.673 21.362C20.3854 21.9265 19.9265 22.3854 19.362 22.673C18.7202 23 17.8802 23 16.2 23H7.8C6.11984 23 5.27976 23 4.63803 22.673C4.07354 22.3854 3.6146 21.9265 3.32698 21.362C3 20.7202 3 19.8802 3 18.2V5.8Z" fill="#169951"/>
</g>
<g opacity="0.96">
<path d="M9.81332 16.4181C9.63132 17.5171 8.86832 18.0421 7.92332 18.0421C7.34232 18.0421 6.90132 17.8461 6.53732 17.4821C6.01232 16.9571 6.03332 16.2571 6.03332 15.5081C6.03332 14.7591 6.01232 14.0591 6.53732 13.5341C6.90132 13.1701 7.34232 12.9741 7.92332 12.9741C8.86832 12.9741 9.63132 13.4991 9.81332 14.5981H8.56732C8.49032 14.3181 8.33632 14.0661 7.93032 14.0661C7.70632 14.0661 7.53832 14.1571 7.44732 14.2761C7.33532 14.4231 7.25832 14.5981 7.25832 15.5081C7.25832 16.4181 7.33532 16.5931 7.44732 16.7401C7.53832 16.8591 7.70632 16.9501 7.93032 16.9501C8.33632 16.9501 8.49032 16.6981 8.56732 16.4181H9.81332Z" fill="white"/>
<path d="M13.8059 16.4741C13.8059 17.4891 12.9309 18.0421 11.8809 18.0421C11.1179 18.0421 10.4949 17.9021 9.99094 17.3841L10.7749 16.6001C11.0339 16.8591 11.4889 16.9501 11.8879 16.9501C12.3709 16.9501 12.6019 16.7891 12.6019 16.5021C12.6019 16.3831 12.5739 16.2851 12.5039 16.2081C12.4409 16.1451 12.3359 16.0961 12.1749 16.0751L11.5729 15.9911C11.1319 15.9281 10.7959 15.7811 10.5719 15.5501C10.3409 15.3121 10.2289 14.9761 10.2289 14.5491C10.2289 13.6391 10.9149 12.9741 12.0489 12.9741C12.7629 12.9741 13.3019 13.1421 13.7289 13.5691L12.9589 14.3391C12.6439 14.0241 12.2309 14.0451 12.0139 14.0451C11.5869 14.0451 11.4119 14.2901 11.4119 14.5071C11.4119 14.5701 11.4329 14.6611 11.5099 14.7381C11.5729 14.8011 11.6779 14.8641 11.8529 14.8851L12.4549 14.9691C12.9029 15.0321 13.2249 15.1721 13.4349 15.3821C13.7009 15.6411 13.8059 16.0121 13.8059 16.4741Z" fill="white"/>
<path d="M18.3124 13.0161L16.6604 18.0001H15.7504L14.1054 13.0161H15.3724L16.2124 15.8021L17.0384 13.0161H18.3124Z" fill="white"/>
</g>
<path opacity="0.5" d="M14 1L21 8H16C14.8954 8 14 7.10457 14 6V1Z" fill="white"/>
<defs>
<filter id="filter0_d_5938_919" x="1" y="0" width="22" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5938_919"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5938_919" result="shape"/>
</filter>
</defs>
</svg>
<svg width="24" height="26" viewBox="0 0 24 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_5938_927)">
<path d="M3 5.8C3 4.11984 3 3.27976 3.32698 2.63803C3.6146 2.07354 4.07354 1.6146 4.63803 1.32698C5.27976 1 6.11984 1 7.8 1H14L21 8V18.2C21 19.8802 21 20.7202 20.673 21.362C20.3854 21.9265 19.9265 22.3854 19.362 22.673C18.7202 23 17.8802 23 16.2 23H7.8C6.11984 23 5.27976 23 4.63803 22.673C4.07354 22.3854 3.6146 21.9265 3.32698 21.362C3 20.7202 3 19.8802 3 18.2V5.8Z" fill="#169951"/>
</g>
<path opacity="0.5" d="M14 1L21 8H16C14.8954 8 14 7.10457 14 6V1Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 12C17.5523 12 18 12.4477 18 13V18C18 18.5523 17.5523 19 17 19H7C6.44772 19 6 18.5523 6 18V13C6 12.4477 6.44772 12 7 12H17ZM11.5 13H7L7 15H11.5V13ZM12.5 18H17V16H12.5V18ZM11.5 16V18H7L7 16H11.5ZM12.5 15H17V13H12.5V15Z" fill="white" fill-opacity="0.96"/>
<defs>
<filter id="filter0_d_5938_927" x="1" y="0" width="22" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5938_927"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5938_927" result="shape"/>
</filter>
</defs>
</svg>
...@@ -75,6 +75,15 @@ ...@@ -75,6 +75,15 @@
.markdownIcon { .markdownIcon {
background-image: url(./assets/md.svg); background-image: url(./assets/md.svg);
} }
.xlsIcon {
background-image: url(./assets/xlsx.svg);
}
.xlsxIcon {
background-image: url(./assets/xlsx.svg);
}
.csvIcon {
background-image: url(./assets/csv.svg);
}
.statusItemDetail { .statusItemDetail {
@apply h-8 font-medium border border-gray-200 inline-flex items-center rounded-lg pl-3 pr-4 mr-2; @apply h-8 font-medium border border-gray-200 inline-flex items-center rounded-lg pl-3 pr-4 mr-2;
} }
......
...@@ -22,7 +22,7 @@ const translation = { ...@@ -22,7 +22,7 @@ const translation = {
title: 'Upload text file', title: 'Upload text file',
button: 'Drag and drop file, or', button: 'Drag and drop file, or',
browse: 'Browse', browse: 'Browse',
tip: 'Supports txt, html, markdown, and pdf.', tip: 'Supports txt, html, markdown, xlsx, xls, and pdf.',
validation: { validation: {
typeError: 'File type not supported', typeError: 'File type not supported',
size: 'File too large. Maximum is 15MB', size: 'File too large. Maximum is 15MB',
......
...@@ -22,7 +22,7 @@ const translation = { ...@@ -22,7 +22,7 @@ const translation = {
title: '上传文本文件', title: '上传文本文件',
button: '拖拽文件至此,或者', button: '拖拽文件至此,或者',
browse: '选择文件', browse: '选择文件',
tip: '已支持 TXT, HTML, Markdown, PDF', tip: '已支持 TXT, HTML, Markdown, PDF, XLSX, XLS',
validation: { validation: {
typeError: '文件类型不支持', typeError: '文件类型不支持',
size: '文件太大了,不能超过 15MB', size: '文件太大了,不能超过 15MB',
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment