Austin Story

Ruby, Rails and Javascript Blog

Powered by Genesis

Changing Show and Edit Actions in Mercury.js for PDF preview

October 26, 2013 By Austin Story 1 Comment

In the mercury-rails/wickedpdf application, I wanted to make a simple additions to limit the pages that people can go to.

I wanted the index page to display a tiny image representation of the pdf they have and then have an edit, pdf preview and destroy option.

I could have done this through a route, but i figured that it is best to just keep it in my index. My table loop is below. The preview just takes the template and appends .pdf at the end. The edit link apends /editor before the template/id so that it opens up the mercury rails.

[code]
% @templates.each do |template| %>
<tr>
<td><%= template.name %></td>
<td><%= link_to ‘Preview PDF’, "/templates/#{template.id}.pdf", :target => "_blank" %></td>–>
<td><%= link_to ‘Edit’, "/editor/templates/" + template.id.to_s %></td>
<!–<td><= link_to ‘Edit’, edit_template_path(template) %></td>–>
<td><%= link_to ‘Destroy’, template, method: :delete, data: { confirm: ‘Are you sure, this is not reversible?’ } %></td>
</tr>
<% end %>
[/code]

Now that part was pretty easy. The next step is fairly straightfoward too. I liked the way the ‘Preview’ button functioned, so I edited that button in mercury.js to look like this.

[code]
preview: [‘Preview PDF’, ‘Preview this page’],
[/code]

Then at the end of our mercury.js file I added an event that binds an action to the preview button

[code]
$(window).bind(‘mercury:ready’, function() {
$(‘.mercury-preview-button’).click(function() {
alert(‘foo’);
});
});
[/code]

Now that this looks like we want and the foo is alerting when we click the Preview PDF button, we just have to change the alert to redirect and
When i click that button after adding the code, foo alerts.

Then change the above code to

[code]
$(window).bind(‘mercury:ready’, function() {
$(‘.mercury-preview-button’).click(function() {
//grabs the last item in the request URL which is our template id
var template_id = window.location.pathname.split("/").pop();
var path = ‘/templates/’ + template_id + ‘.pdf’;
window.open(path, ‘_blank’)
});
});
[/code]

This opens a new window for when the Preview PDF button is clicked that has the PDF representation of our edited document. This feels like a hack, but when i renamed mercury.js to have a .erb and used @template.id I was getting some weird errors that I didn’t want to spend time tracing down. The request ID is coming through in the URL and we already have security in place to prevent URL hacking, so this gives us the functionality we want.

Our final bind event for mercury.js that allows for custom saving and pdf redirection looks like this.

[code]
$(window).bind(‘mercury:ready’, function() {
var link = $(‘#mercury_iframe’).contents().find(‘#edit_link’);
Mercury.saveURL = link.data(‘save-url’);
link.hide();

//opens new page when Preview PDF is clicked in mercury.js
$(‘.mercury-preview-button’).click(function() {
//grabs the last item in the request URL which is our template id
var template_id = window.location.pathname.split("/").pop();
var path = ‘/templates/’ + template_id + ‘.pdf’;
window.open(path, ‘_blank’)
});
});

//redirects after a save
$(window).bind(‘mercury:saved’, function() {
alert(‘Template Saved!’);
});

[/code]

Filed Under: Programming, Ruby on Rails Tagged With: jquery, Mercury-js, ruby on Rails, wicked-pdf, wickedpdf

Integrating Wicked-pdf, Paperclip and Mercury Rails for an editable web document that can be exported to PDF

October 11, 2013 By Austin Story 4 Comments

So i’m creating an editable web document that can be displayed as a PDF using mercury-rails, paperclip and wicked-pdf

gemfile

[code]
#PDF Editing Region

#WYSIWIG Editor
gem ‘mercury-rails’

#PDF Printing
gem ‘wkhtmltopdf-binary’
gem ‘wicked_pdf’

#Image uploading
gem ‘paperclip’
gem ‘aws-sdk
[/code]

Mercury

After you save this we have to run a migration for Mercury-rails
[code]bundle
rails g mercury:install
rake mercury_engine:install:migrations
rake db:migrate[/code]

Now that we have mercury rails installed, you should be able to go to any location in your app and view it with a WYSIWIG editor by prepending /editor to the request.

I am assuming that you will be using this to setup some sort of template relationship with users and that users is already created. So next step is to create the template.

[code]
rails generate scaffold templates

class CreateTemplates < ActiveRecord::Migration
def change
create_table :templates do |t|
t.string :name
t.integer :user_id
t.text :content
t.timestamps
end
end
end
[/code]

User has many templates
tempalates belong to user

Since I only want users to be able to edit templates using mercury, i’m going to limit change the routes in mecury. The routing file that mounts the mercury engine (mount Mercury::Engine => ‘/’) produces the following

[code]
get ‘/editor(/*requested_uri)(.:format)’, :to => ‘mercury#edit’
get ‘/mercury/:type/:resource(.:format)’, :to => ‘mercury#resource’
get ‘/mercury/snippets/:name/options(.:format)’, :to => ‘mercury#snippet_options’
get ‘/mercury/snippets/:name/preview(.:format)’, :to => ‘mercury#snippet_preview’
[/code]

So, to limit this to just the templates, replace the requested_uri with templates

[code]

get ‘/editor/templates/:id(.:format)’, :to => ‘mercury#edit’
get ‘/mercury/:type/:resource(.:format)’, :to => ‘mercury#resource’
get ‘/mercury/snippets/:name/options(.:format)’, :to => ‘mercury#snippet_options’
get ‘/mercury/snippets/:name/preview(.:format)’, :to => ‘mercury#snippet_preview’
[/code]

This will also prevent people from poking around your site trying to exploit any holes that may or may not be in mercury rails

Now we need to create a content editable image, In app/views/templates, open up show.html.erb and add this, which gives you a hard coded semi-representation of an 8.5 by 11 area.

[code]
<div id="template_content" class="mercury-region" data-type="editable" contenteditable=true and data-mercury=full style="margin: 25px 30px; height: 900px; width:670px; border-color: 5px solid black;">

<%= raw @template.content%>

</div>
[/code]

Now, we need to add the ability to save when the save button is clicked. Go into your templates_controller and change update to be this
[code]
template = Template.find(params[:id])
template.content = params[:content][:template_content][:value]
template.save!
render text: ""
[/code]

Add Paperclip

Adding paperclip is really a cinch.

First give mercury the ability to use images

[code]rails generate mercury:install:images
bundle install[/code]

First install image magic on your machine, I use ubuntu so
[code]
sudo apt-get update
sudo apt-get install imagemagick[/code]

Now this is installed, create an Amazon Web Services (AWS) S3 account. Create a bucket and an amazon ID. Give the ID full priveldges to that AWS bucket.

Now, create a yaml file in config/ called s3.yml. You can have multiple ones for productiona and development (which is advisable if you plan to run test suites for this)

[code]
development:
access_key_id: gibberish
secret_access_key: longer-more-secret-gibberish
[/code]

Now go to your app/models/mercury/images.rb and change the has_attatched_file to this
[code]
has_attached_file :image, :styles => { :medium => "300×300>", :thumb => "100×100>" },
:storage => :s3,
:s3_protocol => ‘https’,
:s3_credentials => "#{Rails.root}/config/s3.yml",
:path => ":attachment/:id/:style/:filename",
:url => ":attachment/:id/:style/:filename",
:bucket => ‘some-amazon-bucket’
[/code]

Magically, you will now be able to upload images to your content when you save it.

Adding Wicked-PDF

Now is the last part, being able to append .pdf to your images to get this to print out pdfs.

Add support for PDF in config/initializers/mime_types.rb
[code]Mime::Type.register "application/pdf", :pdf[/code]

Then change your show action of the templates_controller to this

[code]def show
@template = Template.find(params[:id])

respond_to do |format|
format.html # show.html.erb
format.json { render json: @template }
format.pdf do
render :pdf => "file.pdf"
end
end
end
[/code]

Last, add a file to app/views/templates called show.pdf.erb with this line of code in it
[code]
<%= raw @template.content%>
[/code]

Assuming that you have followed all the steps and I didn’t forget anything you should now have a webpage with content that you can edit, save, upload images to and save as a pdf. Enjoy!

Resources
Mercury-Rails Railscast
S3 and Paperclip

Possible additional steps (or posts in the future)
Adding liquid templating to this for variables
Scrubbing the raw html for any ruby references

Filed Under: Programming, Ruby on Rails Tagged With: mercury, mercury-rails, paperclip, ruby, ruby on Rails, web document editor, web editor, wicked-pdf

Categories

  • AngularJS
  • Books
  • Devise
  • Elasticsearch
  • ES6
  • Information Security
  • Integrations
  • Javascript
  • Linux
  • Minitest
  • PhoneGap
  • Programming
  • React
  • Redux
  • Ruby
  • Ruby on Rails
  • Stripe
  • Testing
  • Theory
  • TypeScript
  • Uncategorized
  • Vue
  • Webpack