app/javascript/satis/controllers/attachment_upload_controller.js in satis-2.1.49 vs app/javascript/satis/controllers/attachment_upload_controller.js in satis-2.1.50

- old
+ new

@@ -1,45 +1,67 @@ import { Controller } from "@hotwired/stimulus" +import { post } from "@rails/request.js" export default class AttachmentUploadController extends Controller { - static targets = ["input"] + static targets = ["button"] + static values = { + url: String, + parameterName: String + } + connect() { this.createFileInput() this.addEventListeners() } + disconnect() { + this.fileInput.removeEventListener("change", this.handleChange.bind(this)) + this.element.removeEventListener("dragover", this.handleDragOver.bind(this)) + this.element.removeEventListener("dragleave", this.handleDragLeave.bind(this)) + this.element.removeEventListener("dragenter", this.handleDragEnter.bind(this)) + this.element.removeEventListener("drop", this.handleDrop.bind(this)) + } + createFileInput() { + // Mimic rails - this hiddenInput should prevent "old" files from being deleted + const hiddenInput = document.createElement("input") + hiddenInput.setAttribute("name", `${this.parameterNameValue}[]`) + hiddenInput.setAttribute("type", "hidden") + hiddenInput.setAttribute("autocomplete", "off") + + this.element.closest('form').appendChild(hiddenInput) + const input = document.createElement("input") - input.setAttribute("name", this.data.get("param-name") || "file") + + input.setAttribute("name", `${this.parameterNameValue}[]`) input.setAttribute("type", "file") input.setAttribute("multiple", "multiple") input.style.display = "none" - this.element.appendChild(input) - this.fileInput = input - if (!this.data.has("param-name")) { - console.warn(this.element, "has no data-upload-param attribute, uploads may not work") - } + this.element.closest('form').appendChild(input) + this.fileInput = input } addEventListeners() { - this.element.addEventListener("click", this.handleClick.bind(this)) this.fileInput.addEventListener("change", this.handleChange.bind(this)) this.element.addEventListener("dragover", this.handleDragOver.bind(this)) this.element.addEventListener("dragleave", this.handleDragLeave.bind(this)) this.element.addEventListener("dragenter", this.handleDragEnter.bind(this)) this.element.addEventListener("drop", this.handleDrop.bind(this)) } handleClick(event) { - event.preventDefault() this.fileInput.click() } handleChange(event) { - this.upload(event.target.files) + if (this.hasUrlValue) { + this.upload(event.target.files) + } else { + this.buttonTarget.innerHTML = `${event.target.files.length} files selected` + } } handleDragOver(event) { event.preventDefault() this.element.classList.add("dragging") @@ -57,53 +79,33 @@ handleDrop(event) { event.preventDefault() this.element.classList.remove("dragging") if (event.dataTransfer.files.length > 0) { - this.upload(event.dataTransfer.files) + if (this.hasUrlValue) { + this.upload(event.dataTransfer.files) + } else { + this.buttonTarget.innerHTML = `${event.dataTransfer.files.length} files selected` + } } } upload(files) { // Only proceed if files are selected if (files.length === 0) return let formData = new FormData() - if (this.data.has("extra-data")) { - for (let [key, value] of Object.entries(JSON.parse(this.data.get("extra-data")))) { - formData.append(key, value) - } - } for (let i = 0; i < files.length; i++) { - formData.append(this.data.get("param-name"), files[i]) + formData.append("attachments", files[i]) } this.element.classList.add("uploading") - fetch(this.data.get("url"), { - method: 'POST', + post(this.urlValue, { body: formData, - headers: { - 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content, - 'Accept': 'text/html, application/json' - }, - redirect: 'follow' // Important: follow redirects - }).then((response) => { - // Check if the response is a redirect - if (response.type === 'opaqueredirect' || response.redirected) { - window.location.href = response.url - return - } - - if (response.ok) { - this.element.classList.remove("uploading") - window.location.reload(true) - } else { - throw new Error(response.statusText) - } - }).catch((error) => { - console.log(error) + responseKind: 'turbo-stream' + }).then(html => { this.element.classList.remove("uploading") }) } }