mercredi 25 août 2021

how to upload media file using fetch API and active storage to store media in rails?

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 = '&times;';
            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

Aucun commentaire:

Enregistrer un commentaire