Im using ROR, stymulus, cropperjs with active directory direct upload. Pictures of my project are on amazon s3 I want to allow user uploading pics in a form to crop them in the form before yo upload.
I followed this tutorial on drifting rub
It supposed to use direct upload to upload pics before the user completed the form, like this its possible to show a preview and crop.
The probléme i have is it work only in local, not on heroku in production.
here is my form:
<div class="field" data-controller='instant-upload cropper'
data-cropper-model-value='workshop'>
<label class="btn-cta" style="display:flex; margin-bottom: 20px; max-width: 40%;
margin-left: 0px">
Photo principale
<span style="display:none;">
<%= form.file_field :main_picture, 'data-instant-upload-target': 'input2',
'data-action': 'instant-upload#changed', :class => 'btn-cta', onchange: "validateFiles(this);",
data: { max_file_size: 5.megabytes }%>
</span>
</label>
<%= image_tag @workshop.main_picture.variant(resize_to_limit: [200, 200]),
width: 200, height: 200,
'data-instant-upload-target': 'image',
'data-cropper-target': 'image',
'data-action': 'instant-uploaded->cropper#changed' if @workshop.main_picture.attached? %>
<div style="margin-bottom: 30px">
<%= content_tag :img, nil, src: nil, width: 200, height: 200,
'data-instant-upload-target': 'image',
'data-cropper-target': 'image',
'data-action': 'instant-uploaded->cropper#changed' unless @workshop.main_picture.attached? %>
</div>
</div>
here is my cropper_controller.js:
import { Controller } from "stimulus"
import Cropper from "cropperjs"
import "cropperjs/dist/cropper.css"
export default class extends Controller {
static targets = ["image"]
static values = { model: String }
changed() {
let _this = this
new Cropper(this.imageTarget, {
crop(event) {
_this.crop_x().value = event.detail.x
_this.crop_y().value = event.detail.y
_this.crop_width().value = event.detail.width
_this.crop_height().value = event.detail.height
console.log("x" event.detail.x);
console.log("y" event.detail.y);
console.log("width" event.detail.width);
console.log("height" event.detail.height);
}
})
}
crop_x() {
if (this._crop_x == undefined) {
this._crop_x = document.createElement("input")
this._crop_x.name = `${this.modelValue}[crop_x]`
this._crop_x.type = "hidden"
this.imageTarget.parentNode.insertBefore(this._crop_x, this.imageTarget.nextSibling)
}
return this._crop_x
}
crop_y() {
if (this._crop_y == undefined) {
this._crop_y = document.createElement("input")
this._crop_y.name = `${this.modelValue}[crop_y]`
this._crop_y.type = "hidden"
this.imageTarget.parentNode.insertBefore(this._crop_y, this.imageTarget.nextSibling)
}
return this._crop_y
}
crop_width() {
if (this._crop_width == undefined) {
this._crop_width = document.createElement("input")
this._crop_width.name = `${this.modelValue}[crop_width]`
this._crop_width.type = "hidden"
this.imageTarget.parentNode.insertBefore(this._crop_width, this.imageTarget.nextSibling)
}
return this._crop_width
}
crop_height() {
if (this._crop_height == undefined) {
this._crop_height = document.createElement("input")
this._crop_height.name = `${this.modelValue}[crop_height]`
this._crop_height.type = "hidden"
this.imageTarget.parentNode.insertBefore(this._crop_height, this.imageTarget.nextSibling)
}
return this._crop_height
}
}
here is my instant_upload_controller.js:
import { Controller } from "stimulus"
import { DirectUpload } from "@rails/activestorage"
export default class extends Controller {
static targets = ["input2", "image"]
event() {
if (this._event == undefined) {
this._event = document.createEvent("CustomEvent")
this._event.initCustomEvent("instant-uploaded", true, true, null)
}
return this._event
}
changed() {
Array.from(this.input2Target.files).forEach(file => {
const upload = new DirectUpload(file, this.postURL())
upload.create((error, blob) => {
this.hiddenInput().value = blob.signed_id
// this.input2Target.type = "hidden"
this.imageTarget.src = `${this.getURL()}/${blob.signed_id}/${blob.filename}`
this.imageTarget.dispatchEvent(this.event())
console.log("changed passe")
})
})
}
hiddenInput() {
if (this._hiddenInput2 == undefined ) {
this._hiddenInput2 = document.createElement('input2')
this._hiddenInput2.name = this.input2Target.name
this._hiddenInput2.type = "hidden"
this.input2Target.parentNode.insertBefore(this._hiddenInput2, this.input2Target.nextSibling)
console.log("hiddenInput passe")
}
return this._hiddenInput2
}
postURL() {
console.log("posturl est appelé")
return '/rails/active_storage/direct_uploads'
}
getURL() {
console.log("geturl est appelé")
return '/rails/active_storage/blobs'
}
}
and there is how i defined the CORS in amazon s3 console
[ { "AllowedHeaders": [ "Origin", "Content-Type", "Content-MD5", "Content-Disposition" ], "AllowedMethods": [ "PUT", "GET" ], "AllowedOrigins": [ "https://site-name.herokuapp.com" ], "ExposeHeaders": [ "Origin", "Content-Type", "Content-MD5", "Content-Disposition" ], }]
I checked the console , i puted console log in all my js and everything looks working.
I checked the network in browser dev tool, and everything look similare in local and in prod and i dont have errors.
When i try upload a pics, the preview of the pic is working, just the crop windows dont open and in place i have the uploaded picture in big two times.
It make me think that the direct upload on amazon s3 work well. Its look like its the cropper module that dont work well on heroku. The cropper js file is on heroku, i can see it when i use the debug mode of dev tool in firefox.
Maybe heroku didnt installed or initialized well cropper.js.
I dont see any error message
Im blocked on this issue for two days, please if you have any idea of things i could check, things i could read, things i could try ...or if you passed by this issue, dont hesit to answer.
CodePudding user response:
Hey after struggling few days, i finally find the solution on drifting ruby website.
It dont work on heroku because we have to import the css in webpack. I had to add the following line in the layout
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>