Skip to content

Commit

Permalink
Rewrite upload with stimulus
Browse files Browse the repository at this point in the history
  • Loading branch information
miharekar committed Dec 29, 2024
1 parent 428ae79 commit 92eec26
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 99 deletions.
56 changes: 56 additions & 0 deletions app/javascript/controllers/upload_controller.js
Original file line number Diff line number Diff line change
@@ -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")
}
}
}
15 changes: 4 additions & 11 deletions app/javascript/controllers/upload_drop_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ["overlay"]
static outlets = ["upload"]

connect() {
this.bindEvents()
Expand All @@ -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)
})

Expand All @@ -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)
})

Expand Down Expand Up @@ -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)
}
}
1 change: 0 additions & 1 deletion app/javascript/custom/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import "custom/hljs"
import "custom/skin"
import "custom/time"
import "custom/upload"
56 changes: 0 additions & 56 deletions app/javascript/custom/upload.js

This file was deleted.

62 changes: 32 additions & 30 deletions app/views/shots/_upload_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
<div id="upload-error" class="hidden">
<%= render Notification.new(type: "alert", heading: "Something went wrong") %>
</div>
<div class="<%= "hidden" unless show_form %> px-4 sm:px-0" data-panel-target="uploadForm">
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<p class="text-neutral-600 dark:text-neutral-400">
Upload one or more .shot, .json, or .csv files from Decent, Beanconqueror, Smart Espresso Profiler, Pressensor, or other compatible sources.
</p>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<%= form_with(url: { action: :create }, multipart: true, id: "shot-upload-form") do |f| %>
<div class="overflow-hidden rounded-md">
<div class="p-4 bg-white inset-shadow-sm dark:bg-neutral-900">
<div id="loader" class="justify-center hidden px-6 py-10 border-2 border-dashed rounded-md border-neutral-300 dark:border-neutral-600">
<%= inline_svg_tag "logo-loading.svg", class: "logo-loading mx-auto w-auto h-14 stroke-neutral-500 text-neutral-500 dark:text-neutral-400 dark:stroke-neutral-400" %>
</div>
<div id="drop-area" class="flex justify-center px-6 border-2 border-dashed rounded-md py-9 border-neutral-300 dark:border-neutral-600">
<div class="flex flex-col text-center gap-y-1">
<svg class="w-10 h-10 mx-auto text-neutral-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<div class="flex text-sm text-neutral-600 dark:text-neutral-300">
<label class="relative font-medium bg-white rounded-md cursor-pointer dark:bg-neutral-900 text-oxford-blue-600 dark:text-oxford-blue-400 hover:text-oxford-blue-500 dark:hover:text-oxford-blue-600 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-oxford-blue-500" for="files">
<span>Select your files</span>
<%= file_field_tag "files", multiple: true, name: "files[]", class: "hidden" %>
</label>
<p class="pl-1">or drag and drop them here</p>
<div id="shot-upload-form" data-controller="upload">
<div class="hidden" data-upload-target="error">
<%= render Notification.new(type: "alert", heading: "Something went wrong") %>
</div>
<div class="<%= "hidden" unless show_form %> px-4 sm:px-0" data-panel-target="uploadForm">
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<p class="text-neutral-600 dark:text-neutral-400">
Upload one or more .shot, .json, or .csv files from Decent, Beanconqueror, Smart Espresso Profiler, Pressensor, or other compatible sources.
</p>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<%= form_with(url: { action: :create }, multipart: true, data: { upload_target: "form" }) do |f| %>
<div class="overflow-hidden rounded-md">
<div class="p-4 bg-white inset-shadow-sm dark:bg-neutral-900">
<div class="justify-center hidden px-6 py-10 border-2 border-dashed rounded-md border-neutral-300 dark:border-neutral-600" data-upload-target="loader">
<%= inline_svg_tag "logo-loading.svg", class: "logo-loading mx-auto w-auto h-14 stroke-neutral-500 text-neutral-500 dark:text-neutral-400 dark:stroke-neutral-400" %>
</div>
<div class="flex justify-center px-6 border-2 border-dashed rounded-md py-9 border-neutral-300 dark:border-neutral-600" data-upload-target="dropArea">
<div class="flex flex-col text-center gap-y-1">
<svg class="w-10 h-10 mx-auto text-neutral-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<div class="flex text-sm text-neutral-600 dark:text-neutral-300">
<label class="relative font-medium bg-white rounded-md cursor-pointer dark:bg-neutral-900 text-oxford-blue-600 dark:text-oxford-blue-400 hover:text-oxford-blue-500 dark:hover:text-oxford-blue-600 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-oxford-blue-500" for="files">
<span>Select your files</span>
<%= file_field_tag "files", multiple: true, name: "files[]", class: "hidden", data: { upload_target: "files" } %>
</label>
<p class="pl-1">or drag and drop them here</p>
</div>
</div>
</div>
</div>
</div>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
</div>
2 changes: 1 addition & 1 deletion app/views/shots/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<% if Current.user && Current.user.shots.where("extract(year from start_time) = ?", 2024).exists? %>
<%= render "yearly_brew_promo" %>
<% end %>
<div class="flex flex-col mx-auto my-6 gap-y-6 max-w-7xl sm:px-6 lg:px-8" data-controller="panel upload-drop">
<div class="flex flex-col mx-auto my-6 gap-y-6 max-w-7xl sm:px-6 lg:px-8" data-controller="panel upload-drop" data-upload-drop-upload-outlet="#shot-upload-form">
<div data-upload-drop-target="overlay" class="hidden fixed inset-0 bg-oxford-blue-600/30 backdrop-blur-sm z-50 items-center justify-center">
<div class="text-center">
<h3 class="text-2xl font-medium text-white mb-2">
Expand Down

0 comments on commit 92eec26

Please sign in to comment.