diff --git a/app/javascript/controllers/upload_controller.js b/app/javascript/controllers/upload_controller.js new file mode 100644 index 00000000..989041e0 --- /dev/null +++ b/app/javascript/controllers/upload_controller.js @@ -0,0 +1,56 @@ +import { Controller } from "@hotwired/stimulus" +import { Turbo } from "@hotwired/turbo-rails" +import { post } from "@rails/request.js" + +export default class extends Controller { + static targets = ["dropArea", "loader", "error", "form", "files"] + + connect() { + if (this.hasFilesTarget) { + this.filesTarget.onchange = () => { + this.dropAreaTarget.classList.add("hidden") + this.loaderTarget.classList.remove("hidden") + Turbo.navigator.submitForm(this.formTarget) + } + } + + this.dropAreaTarget.addEventListener("drop", this.handleDrop.bind(this)) + } + + disconnect() { + if (this.hasFilesTarget) { + this.filesTarget.onchange = null + } + this.dropAreaTarget.removeEventListener("drop", this.handleDrop.bind(this)) + } + + async handleDrop(e) { + this.dropAreaTarget.classList.add("hidden") + this.loaderTarget.classList.remove("hidden") + + const formData = new FormData(); + [...e.dataTransfer.files].forEach((file) => { + formData.append("files[]", file) + }) + + try { + const response = await post(this.formTarget.action + "?drag=1", { + body: formData, + responseKind: "turbo-stream" + }) + + if (response.ok) { + Turbo.visit("/shots") + } else { + const notificationsContainer = document.getElementById("notifications-container") + notificationsContainer.insertAdjacentHTML("beforeend", this.errorTarget.innerHTML) + } + } catch { + const notificationsContainer = document.getElementById("notifications-container") + notificationsContainer.insertAdjacentHTML("beforeend", this.errorTarget.innerHTML) + } finally { + this.loaderTarget.classList.add("hidden") + this.dropAreaTarget.classList.remove("hidden") + } + } +} \ No newline at end of file diff --git a/app/javascript/controllers/upload_drop_controller.js b/app/javascript/controllers/upload_drop_controller.js index 8420ef36..d3ae5a91 100644 --- a/app/javascript/controllers/upload_drop_controller.js +++ b/app/javascript/controllers/upload_drop_controller.js @@ -2,6 +2,7 @@ import { Controller } from "@hotwired/stimulus" export default class extends Controller { static targets = ["overlay"] + static outlets = ["upload"] connect() { this.bindEvents() @@ -12,7 +13,7 @@ export default class extends Controller { } bindEvents() { - ;["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => { + ["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => { document.addEventListener(eventName, this.preventDefaults, false) }) @@ -22,7 +23,7 @@ export default class extends Controller { } unbindEvents() { - ;["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => { + ["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => { document.removeEventListener(eventName, this.preventDefaults, false) }) @@ -52,14 +53,6 @@ export default class extends Controller { handleDrop(e) { this.hideOverlay(e) - - const uploadDropArea = document.getElementById("drop-area") - if (uploadDropArea) { - const dropEvent = new DragEvent("drop", { - dataTransfer: e.dataTransfer, - bubbles: true - }) - uploadDropArea.dispatchEvent(dropEvent) - } + this.uploadOutlet.handleDrop(e) } } \ No newline at end of file diff --git a/app/javascript/custom/index.js b/app/javascript/custom/index.js index 621004f3..05bccaff 100644 --- a/app/javascript/custom/index.js +++ b/app/javascript/custom/index.js @@ -1,4 +1,3 @@ import "custom/hljs" import "custom/skin" import "custom/time" -import "custom/upload" diff --git a/app/javascript/custom/upload.js b/app/javascript/custom/upload.js deleted file mode 100644 index 00584d8f..00000000 --- a/app/javascript/custom/upload.js +++ /dev/null @@ -1,56 +0,0 @@ -import { Turbo } from "@hotwired/turbo-rails" - -document.addEventListener("turbo:load", function () { - const dropArea = document.getElementById("drop-area") - - if (dropArea) { - const loader = document.getElementById("loader") - const notificationsContainer = document.getElementById("notifications-container") - const error = document.getElementById("upload-error") - const form = document.getElementById("shot-upload-form") - const token = document.getElementsByName("csrf-token")[0].content - - const handleDrop = (e) => { - dropArea.classList.add("hidden") - loader.classList.remove("hidden") - - let xhr = new XMLHttpRequest() - let formData = new FormData() - - xhr.open("POST", form.action + "?drag=1", true) - xhr.setRequestHeader("X-CSRF-Token", token) - xhr.addEventListener( - "readystatechange", - function () { - if (xhr.readyState == 4) { - loader.classList.add("hidden") - dropArea.classList.remove("hidden") - - if (xhr.status == 200) { - Turbo.visit("/shots") - } else { - notificationsContainer.insertAdjacentHTML("beforeend", error.innerHTML) - } - } - }, - false - ); - - [...e.dataTransfer.files].forEach((file) => { - formData.append("files[]", file) - }) - xhr.send(formData) - } - - const files = document.getElementById("files") - if (files) { - document.getElementById("files").onchange = function () { - dropArea.classList.add("hidden") - loader.classList.remove("hidden") - Turbo.navigator.submitForm(form) - } - } - - dropArea.addEventListener("drop", handleDrop, false) - } -}) diff --git a/app/views/shots/_upload_form.html.erb b/app/views/shots/_upload_form.html.erb index 61102d57..fd1f5cc8 100644 --- a/app/views/shots/_upload_form.html.erb +++ b/app/views/shots/_upload_form.html.erb @@ -1,37 +1,39 @@ - -
px-4 sm:px-0" data-panel-target="uploadForm"> -
-
-

- Upload one or more .shot, .json, or .csv files from Decent, Beanconqueror, Smart Espresso Profiler, Pressensor, or other compatible sources. -

-
-
- <%= form_with(url: { action: :create }, multipart: true, id: "shot-upload-form") do |f| %> -
-
- -
-
- - - -
- -

or drag and drop them here

+
+ +
px-4 sm:px-0" data-panel-target="uploadForm"> +
+
+

+ Upload one or more .shot, .json, or .csv files from Decent, Beanconqueror, Smart Espresso Profiler, Pressensor, or other compatible sources. +

+
+
+ <%= form_with(url: { action: :create }, multipart: true, data: { upload_target: "form" }) do |f| %> +
+
+ +
+
+ + + +
+ +

or drag and drop them here

+
-
- <% end %> + <% end %> +
diff --git a/app/views/shots/index.html.erb b/app/views/shots/index.html.erb index 8364db69..d09097e5 100644 --- a/app/views/shots/index.html.erb +++ b/app/views/shots/index.html.erb @@ -4,7 +4,7 @@ <% if Current.user && Current.user.shots.where("extract(year from start_time) = ?", 2024).exists? %> <%= render "yearly_brew_promo" %> <% end %> -
+