I'm trying to store the image or video file in the database and along with image and video, i have some data to store.
I'm using fetch api to post the data and using ActiveStorage to store the image and video files. I have stored the text data to the database but unable to store the image and video files. Here below is the Section model
class Section < ApplicationRecord
belongs_to :layout,dependent: :destroy
has_many :media, through: :section_multimedia
has_many :section_multimedia, dependent: :destroy
has_one_attached :mediadata
end
Below is the show page along with javascript included
.border
.row
.col-md-9
.p-3
button#imageModalButton.btn.btn-primary type="button" data-toggle="modal" data-target="#imageModal" <b>Design Layout</b>
= link_to "Preview", preview_layout_layout_path ,:class=>"btn btn-danger mx-3"
/ Here goes the overview of saved layout
. style="position:relative; background-color: #3C506F;height:500px; overflow:auto; "
-@section.each do |sect|
.border id="hello#{sect.id}" style="position:absolute; height:#{sect.height}px; top:#{sect.position.split(",")[0]}px; left:#{sect.position.split(",")[1]}px; width:#{sect.width}px;" #{sect.sectiontitle}
end
.col-3.border-left
.row
.col-md-12
= text_field_tag 'search', nil, class: "form-control search col-11", placeholder: "Search.."
i.fa.fa-file-search
= render 'layouts/gallery'
#imageModal.modal.fade aria-hidden="true" aria-labelledby="exampleModalLabel" role="dialog" tabindex="-1"
.modal-dialog.modal-lg role="document"
.modal-content style="width:800px"
.row.bg-dark
.col-md-4
button.btn.btn-outline-primary#add-section Add Section
.col-md-4
button.btn.btn-outline-success#save-layout Save
.col-md-4
button.btn.btn-outline-danger data-dismiss="modal" type="button" Cancel
.d-flex id="canvas" style="position:relative;background-color: black;height:500px; overflow:auto;"
-if !@section.nil?
. style="position:relative; background-color: #3C506F;height:500px; overflow:auto; "
-@section.each do |sect|
= image_tag(sect.mediadata) if sect.mediadata.attached?
.border id="sect#{sect.id}" class="custom" style="position:absolute; height:#{sect.height}px; top:#{sect.position.split(",")[0]}px; left:#{sect.position.split(",")[1]}px; width:#{sect.width}px;" #{sect.sectiontitle}
end
css:
.section{
height:250px;
width :400px;
}
.custom:hover{
background:#E4E5E6;
}
javascript:
let canvas = document.getElementById('canvas')
let addSectionBtn = document.getElementById('add-section')
canvas.className= "row"
canvas.setAttribute("height","100%")
var position
var dimension
var count =#{@section.count}+1
addSectionBtn.addEventListener('click',(event)=>{
let sectiondiv = document.createElement("div");
let mediadiv = document.createElement("div");
let input = document.createElement("input")
let closebtn = document.createElement("button");
let img = document.createElement("img");
sectiondiv.setAttribute("id","section"+count);
closebtn.className ='btn btn-outline-danger close'
closebtn.setAttribute("value","close"+count);
sectiondiv.className = "border absolute section ui-widget-content"
mediadiv.appendChild(closebtn)
sectiondiv.appendChild(mediadiv)
mediadiv.setAttribute("id","media"+count)
img.className = "absolute"
img.setAttribute("id","image"+count);
img.setAttribute("height","100%")
img.setAttribute("width","100%")
closebtn.setAttribute("id","close"+count)
canvas.appendChild(sectiondiv)
closebtn.innerHTML = '×';
mediadiv.appendChild(input)
input.setAttribute("class","file-input")
input.setAttribute("name","mediadata")
sectiondiv.appendChild(img);
input.setAttribute("id","input"+count)
input.setAttribute("type","file")
input.setAttribute("accept","image/*,video/*")
input.setAttribute("onchange","PreviewFile(this.id)")
$("#section"+count).resizable();
$("#section"+count).draggable();
let sections = document.querySelectorAll(".section");
for(var i=0;i<sections.length;i++){
sections[i].addEventListener('click',(event)=>{
var id = event.target.id.split("section")[1]
})
}
// logic to remove the section from the layout
let closebtns = document.querySelectorAll('.close');
for(var i=0;i<closebtns.length;i++){
closebtns[i].addEventListener('click',(event)=>{
var id=event.target.id.split("close")[1]
$("#section"+id).remove()
})
}
count++
})
function PreviewFile (id){
var file = document.getElementById(id).files;
if(file.length > 0){
var fileReader = new FileReader();
fileReader.onload = function(event){
document.getElementById("image"+id.split("input")[1]).setAttribute("src",event.target.result)
$("#"+id).hide()
$("#closebtn"+id.split("input")[1]).hide()
}
fileReader.readAsDataURL(file[0]);
}
}
let savebtn = document.getElementById('save-layout')
// Saving layout sections using jquery
savebtn.addEventListener('click',(event)=>{
// setting logic to get the updated position and dimension of each section
var position = []
var dimension = []
let allSections =[]
let filesId = []
let layout_id = window.location.href.split("/layouts/")[1]
let sections = document.querySelectorAll('.section')
var inputElementArr = document.querySelectorAll('.file-input')
var allimage = []
sections.forEach((section)=>{
var file = document.getElementById("input"+section.id.split("section")[1]).files
position.push($("#"+section.id).position())
dimension.push(($("#"+section.id).height())*$("#"+section.id).width())
allSections.push(section.id)
allimage.push(file[0])
var temp = {sectionid:section.id,dimension: ($("#"+section.id).height())*$("#"+section.id).width(),position : $("#"+section.id).position() }
if (file){
temp.file = file[0]
}
allimage.push(temp)
})
storeData(allSections,position,dimension,allimage,layout_id);
})
function storeData(allSections ,position ,dimension,allimage,layout_id){
let data =[]
// setting section data in data variable as objects
for(var i=0; i < allSections.length; i++){
var height = $("#"+allSections[i]).height()
var width = $("#"+allSections[i]).width()
data.push({sectiontitle: allSections[i], description: "this is "+i, position: position[i].top+","+position[i].left, height: height, width: width, mediadata: allimage[i], layout_id: layout_id})
}
//console.log("DATA :",data)
//Sending each section data to the sectionController
data.forEach((data)=>{
post('http://localhost:3000/sections',data).then((response)=>{
console.log(response)
}).catch((e)=>{
console.log(e)
})
})
// => Array of Objects representing Band objects with IDs set
swal("Success!", "Layout Design Saved!", "success");
}
// FetchWrapper by sajan Dhakal
function get(url) {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
credentials: 'same-origin',
};
return fetch(url, requestOptions).then(handleResponse);
}
// post method to call fetch API
function post(url, body) {
var token = $('meta[name="csrf-token"]').attr('content');
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': token
},
body: JSON.stringify(body),
};
return fetch(url, requestOptions);
}
function put(url, body) {
const requestOptions = {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
};
return fetch(url, requestOptions).then(handleResponse);
}
function patch(url, body) {
const requestOptions = {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
};
return fetch(url, requestOptions).then(handleResponse);
}
// prefixed with underscored because delete is a reserved word in javascript
function _delete(url) {
const requestOptions = {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
};
return fetch(url, requestOptions).then(handleResponse);
}
// helper functions
function handleResponse(response) {
return response.text().then((text) => {
try {
const data = text && JSON.parse(text);
if (!response.ok) {
if (response.status === 401) {
const error = { code: response.status, detail: response.statusText };
return Promise.reject(error);
}
const error = {
code: (data && data.code) || response.status,
detail: (data && data.detail) || response.statusText,
};
return Promise.reject(error);
}
return data;
} catch (e) {
const error = { code: 500, detail: 'something went wrong' };
return Promise.reject(error);
}
});
}
This is the Section controller
class SectionsController < ApplicationController
def create
binding.pry
@section = Section.new(section_params)
respond_to do |format|
if @section.save!
format.html { redirect_to layouts_path, notice: "Sections Created Successfully" }
format.js
format.json { render json: @section,status: :created, location: @section}
else
# format.html { render :new, alert:"Unable to create new "}
format.json { render json: @section.errors, status: :unprocessable_entity }
end
end
end
private
def section_params
params.require(:section).permit(:sectiontitle,:description, :position,:height,:width,:mediadata,:layout_id)
end
end