117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
import { useDropzone } from 'react-dropzone'
|
|
import React, { useCallback, useMemo, useState } from 'react'
|
|
import {
|
|
MediaOption,
|
|
MEDIA_OPTIONS,
|
|
ImageController,
|
|
MEDIA_DROPZONE_OPTIONS
|
|
} from '../../controllers'
|
|
import { errorFeedback } from '../../types'
|
|
import { MediaInputPopover } from './MediaInputPopover'
|
|
|
|
export interface ImageUploadProps {
|
|
multiple?: boolean | undefined
|
|
onChange: (values: string[]) => void
|
|
}
|
|
export const ImageUpload = React.memo(
|
|
({ multiple = false, onChange }: ImageUploadProps) => {
|
|
const [mediaOption, setMediaOption] = useState<MediaOption>(
|
|
MEDIA_OPTIONS[0]
|
|
)
|
|
const handleOptionChange = useCallback(
|
|
(mo: MediaOption) => () => {
|
|
setMediaOption(mo)
|
|
},
|
|
[]
|
|
)
|
|
const handleUpload = useCallback(
|
|
async (acceptedFiles: File[]) => {
|
|
if (acceptedFiles.length) {
|
|
try {
|
|
const imageController = new ImageController(mediaOption)
|
|
const urls: string[] = []
|
|
for (let i = 0; i < acceptedFiles.length; i++) {
|
|
const file = acceptedFiles[i]
|
|
urls.push(await imageController.post(file))
|
|
}
|
|
onChange(urls)
|
|
} catch (error) {
|
|
errorFeedback(error)
|
|
}
|
|
}
|
|
},
|
|
[mediaOption, onChange]
|
|
)
|
|
const {
|
|
getRootProps,
|
|
getInputProps,
|
|
isDragActive,
|
|
acceptedFiles,
|
|
isFileDialogActive,
|
|
isDragAccept,
|
|
isDragReject,
|
|
fileRejections
|
|
} = useDropzone({
|
|
...MEDIA_DROPZONE_OPTIONS,
|
|
onDrop: handleUpload,
|
|
multiple: multiple
|
|
})
|
|
|
|
const dropzoneLabel = useMemo(
|
|
() =>
|
|
isFileDialogActive
|
|
? 'Select files in dialog'
|
|
: isDragActive
|
|
? isDragAccept
|
|
? 'Drop the files here...'
|
|
: isDragReject
|
|
? 'Drop the files here (one more more unsupported types)...'
|
|
: 'Drop the files here...'
|
|
: 'Click or drag files here',
|
|
[isDragAccept, isDragActive, isDragReject, isFileDialogActive]
|
|
)
|
|
|
|
return (
|
|
<div aria-label='upload featuredImageUrl' className='uploadBoxMain'>
|
|
<MediaInputPopover
|
|
acceptedFiles={acceptedFiles}
|
|
fileRejections={fileRejections}
|
|
/>
|
|
<div className='uploadBoxMainInside' {...getRootProps()} tabIndex={-1}>
|
|
<input id='featuredImageUrl-upload' {...getInputProps()} />
|
|
|
|
<span>{dropzoneLabel}</span>
|
|
<div
|
|
className='FiltersMainElement'
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className='dropdown dropdownMain'>
|
|
<button
|
|
className='btn dropdown-toggle btnMain btnMainDropdown'
|
|
aria-expanded='false'
|
|
data-bs-toggle='dropdown'
|
|
type='button'
|
|
>
|
|
Image Host: {mediaOption.name}
|
|
</button>
|
|
<div className='dropdown-menu dropdownMainMenu'>
|
|
{MEDIA_OPTIONS.map((mo) => {
|
|
return (
|
|
<div
|
|
key={mo.host}
|
|
onClick={handleOptionChange(mo)}
|
|
className='dropdown-item dropdownMainMenuItem'
|
|
>
|
|
{mo.name}
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
)
|