WIP: Implement uploads

This commit is contained in:
Björn Fromme
2023-09-18 17:56:33 +02:00
parent ce97017ac4
commit d6687c3ca4
51 changed files with 1123 additions and 168 deletions
+7 -2
View File
@@ -24,8 +24,13 @@ export default class extends Controller {
})
this.buttonTargets.forEach((element, index) => {
if (this.hasButtonActiveClass) {
element.classList.toggle(this.buttonActiveClass, activeTab === index)
if (false === this.hasButtonActiveClass) {
return
}
if (activeTab === index) {
element.classList.add(...this.buttonActiveClasses)
} else {
element.classList.remove(...this.buttonActiveClasses)
}
})
}
@@ -0,0 +1,63 @@
import { Controller } from '@hotwired/stimulus'
import { useFetch } from '../mixins/use_fetch'
import Dropzone from 'dropzone'
import 'dropzone/dist/dropzone.css'
Dropzone.autoDiscover = false
/* stimulusFetch: 'lazy' */
export default class extends Controller {
static targets = [
'dropzone',
]
static values = {
endpointUpload: String,
endpointDelete: String,
maxFiles: Number,
maxFilesize: Number,
acceptedFiles: String,
chunking: Boolean,
params: Object,
}
connect () {
useFetch(this)
const dropzone = new Dropzone(this.dropzoneTarget, {
url: this.endpointUploadValue,
withCredentials: true,
maxFiles: this.maxFilesValue,
maxFilesize: this.maxFilesizeValue,
acceptedFiles: this.acceptedFilesValue,
chunking: this.chunkingValue,
chunkSize: 10000000,
parallelUploads: 3,
retryChunks: true,
disablePreviews: false,
createImageThumbnails: true,
autoProcessQueue: true,
addRemoveLinks: true,
})
dropzone.on('sending', (file, xhr, formData) => {
if (this.hasParamsValue) {
let keys = Object.keys(this.paramsValue)
keys.forEach(key => {
formData.append(key, this.paramsValue[key])
})
}
formData.append('uuid', file.upload.uuid)
formData.append('originalFilename', file.name)
window.dispatchEvent(new CustomEvent('dropzone:uploading'))
})
dropzone.on('queuecomplete', () => {
window.dispatchEvent(new CustomEvent('dropzone:complete'))
})
dropzone.on('removedfile', (file) => {
fetch(`${this.endpointDeleteValue}?uuid=${file.upload.uuid}`, { method: 'delete', credentials: 'include' })
})
}
}
-152
View File
@@ -1,152 +0,0 @@
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()
}
})
}
}