153 lines
4.5 KiB
JavaScript
153 lines
4.5 KiB
JavaScript
import { Controller } from '@hotwired/stimulus'
|
|
import Dropzone from 'dropzone'
|
|
Dropzone.autoDiscover = false
|
|
|
|
/* stimulusFetch: 'lazy' */
|
|
export default class extends Controller {
|
|
|
|
static targets = [
|
|
'dropzone',
|
|
'queue',
|
|
'previewTemplate',
|
|
'fieldsTemplate',
|
|
'fields',
|
|
'error',
|
|
'errorMessage',
|
|
'upload',
|
|
]
|
|
|
|
static values = {
|
|
endpoint: String,
|
|
maxFiles: Number,
|
|
maxFilesize: Number,
|
|
acceptedFiles: String,
|
|
chunking: Boolean,
|
|
language: Object,
|
|
params: Object,
|
|
uploads: Array,
|
|
error: String,
|
|
formName: String,
|
|
}
|
|
|
|
initialize() {
|
|
this.fieldsTemplate = this.fieldsTemplateTarget.innerHTML
|
|
}
|
|
|
|
connect () {
|
|
const dropzone = new Dropzone(this.dropzoneTarget, {
|
|
url: this.endpointValue,
|
|
withCredentials: true,
|
|
maxFiles: this.maxFilesValue,
|
|
maxFilesize: this.maxFilesizeValue,
|
|
acceptedFiles: this.acceptedFilesValue,
|
|
chunking: this.chunkingValue,
|
|
chunkSize: 10000000,
|
|
parallelUploads: 3,
|
|
retryChunks: true,
|
|
previewsContainer: this.queueTarget,
|
|
previewTemplate: this.previewTemplateTarget.innerHTML,
|
|
createImageThumbnails: true,
|
|
dictFileTooBig: this.languageValue.fileTooBig,
|
|
dictInvalidFileType: this.languageValue.invalidFileType,
|
|
dictMaxFilesExceeded: this.languageValue.maxFilesExceeded,
|
|
})
|
|
|
|
dropzone.on('addedfile', file => {
|
|
if (this.maxFilesValue > this.uploadsValue.length) {
|
|
this._removeFile(file.id)
|
|
return
|
|
}
|
|
this.errorValue = ''
|
|
const uploads = this.uploadsValue;
|
|
uploads.pop()
|
|
this.uploadsValue = uploads
|
|
})
|
|
|
|
dropzone.on('removedfile', file => {
|
|
this._removeFile(file.upload.uuid)
|
|
})
|
|
|
|
dropzone.on('maxfilesexceeded', file => {
|
|
this.errorValue = dropzone.options.dictMaxFilesExceeded
|
|
dropzone.removeFile(file);
|
|
})
|
|
|
|
dropzone.on('error', (file, errorMessage) => {
|
|
this.errorValue = errorMessage;
|
|
dropzone.removeFile(file)
|
|
})
|
|
|
|
dropzone.on('dragenter', () => {
|
|
this.errorValue = ''
|
|
})
|
|
|
|
dropzone.on('success', file => {
|
|
const response = JSON.parse(file.xhr.response)
|
|
const uploads = this.uploadsValue
|
|
uploads.push({
|
|
filename: response.filename,
|
|
originalFilename: response.originalFilename,
|
|
uploaderType: response.uploaderType,
|
|
size: response.size,
|
|
mimeType: response.mimeType,
|
|
fileId: file.upload.uuid
|
|
})
|
|
this.uploadsValue = uploads
|
|
window.dispatchEvent(new CustomEvent('dropzone', {
|
|
detail: 'success'
|
|
}))
|
|
})
|
|
|
|
dropzone.on('sending', () => {
|
|
window.dispatchEvent(new CustomEvent('dropzone', {
|
|
detail: 'uploading'
|
|
}))
|
|
})
|
|
}
|
|
|
|
errorValueChanged () {
|
|
if ('' === this.errorValue) {
|
|
this.errorTarget.classList.add('hidden')
|
|
} else {
|
|
this.errorMessageTarget.innerText = this.errorValue
|
|
this.errorTarget.classList.remove('hidden')
|
|
}
|
|
}
|
|
|
|
uploadsValueChanged (uploads) {
|
|
this.fieldsTarget.innerHTML = ''
|
|
uploads.forEach((upload, index) => {
|
|
const field = this.fieldsTemplate
|
|
.replace(/__formName__/g, this.formNameValue)
|
|
.replace(/__index__/g, index)
|
|
.replace(/__fileId__/g, upload.fileId)
|
|
.replace(/__originalFilename__/g, upload.originalFilename)
|
|
.replace(/__filename__/g, upload.filename)
|
|
.replace(/__mimeType__/g, upload.mimeType)
|
|
.replace(/__size__/g, upload.size)
|
|
this.fieldsTarget.insertAdjacentHTML('beforeend', field)
|
|
})
|
|
}
|
|
|
|
removeFile ({ params }) {
|
|
const fileId = params.fileid
|
|
this._removeFile(fileId)
|
|
}
|
|
|
|
_removeFile(fileId) {
|
|
this.uploadsValue = this.uploadsValue.filter(upload => {
|
|
return upload.fileId !== fileId
|
|
})
|
|
}
|
|
|
|
removeUpload (event) {
|
|
event.preventDefault()
|
|
this.uploadTargets.forEach(element => {
|
|
if (element.contains(event.target)) {
|
|
element.remove()
|
|
}
|
|
})
|
|
}
|
|
|
|
}
|