-
Notifications
You must be signed in to change notification settings - Fork 0
/
proposalr.rb
155 lines (134 loc) · 4.26 KB
/
proposalr.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# encoding: UTF-8
require 'rubygems'
require 'sinatra'
require 'pdfkit'
require 'cgi'
require 'json'
require 'pony'
require 'data_mapper'
require 'dm-timestamps'
# require 'ruby-debug'
# remove the env condition if your prod environment has the file
# Heroku deployment doesn't facilitate secret config files like this.
require_relative './basic_auth_credentials' unless settings.environment == :production
use Rack::Auth::Basic, "Restricted Area" do |username, password|
[username, password] == [
ENV['USERNAME'] || settings.username,
ENV['PASSWORD'] || settings.password]
end
if settings.environment == :development
require './local_email_settings'
else
set :email_username, ENV['SENDGRID_USERNAME']
set :email_password, ENV['SENDGRID_PASSWORD']
set :email_service, ENV['EMAIL_SERVICE']
set :email_domain, ENV['SENDGRID_DOMAIN']
end
database_path = ENV["DATABASE_URL"] || ("sqlite3:///#{Dir.pwd}/%s.sqlite3" % settings.environment.to_s)
DataMapper.setup(:default, database_path)
class Document
include DataMapper::Resource
property :id, Serial
property :filename, String, :required => true
property :serialized_data, Text, :required => true
property :created_at, DateTime
property :updated_at, DateTime
end
DataMapper.auto_upgrade!
# docs index
get '/' do
@docs = Document.all(:order => [ :updated_at.desc ])
erb :index
end
# delete a doc
get '/delete/:id' do |id|
doc = Document.get(id)
(doc && doc.destroy) ? 200 : 409
end
# show a doc for editing
get %r{(\d+)} do |id|
content_type :json
doc = Document.get(id)
doc ? doc.serialized_data : 409
end
# download/show a doc in specified format
post %r{^/(pdf|html)$} do |format|
filename = params.delete('filename')
output(filename, format, params)
end
# save a doc
post '/save' do
id = params.delete('document_id')
doc = Document.first_or_new :id => (id.blank? ? nil : id)
doc.filename = params.delete('filename')
doc.serialized_data = params.empty? ? nil : params.to_json
doc.save ? [200, doc.id.to_s] : [500, doc.errors.values.join('<br/>')]
end
#email a pdf
post '/email' do
filename = params.delete('filename')
filename << '.pdf'
html = build_html(params, filename)
html = html.gsub(/src=\"\/images\//, 'src="file://'+`pwd`+'/public/images/')
kit = PDFKit.new html
begin
Pony.mail({
:to => params[:email_to],
:from => 'no-reply@%s' % ENV['URL'],
:subject => "Your Proposalr Document - %s" % filename,
:attachments => {filename => kit.to_pdf},
:body => 'Attached.',
:port => '587',
:via => :smtp,
:via_options => {
:address => 'smtp.' + settings.email_service,
:port => '587',
:enable_starttls_auto => true,
:user_name => settings.email_username,
:password => settings.email_password,
:authentication => :plain,
:domain => settings.email_domain}
});
rescue => e
puts e.message
e.message
end
end
private
def output(filename, format, params)
html = build_html(params, filename)
case format
when 'pdf'
html = html.gsub(/src=\"\/images\//, 'src="file://'+`pwd`+'/public/images/')
pdf_out_memory(html, filename)
else
html
end
end
def pdf_out_memory(html, filename)
kit = PDFKit.new html
headers({
'Content-Disposition' => "attachment; filename=#{filename}.pdf",
'Content-Type' => 'application/pdf'})
kit.to_pdf
end
def build_html(params, filename)
sections = {}
params.each do |name, value|
next unless name.match /^output/
next if name.match /meta$/
meta = JSON.parse( CGI::unescape( params[name+'_meta'] ) )
heading = meta['hide_title'] ? '' : "<h3>#{meta['title']}</h3>"
style = meta['style'] ? " style='#{meta['style']}'" : ''
content = value.split(/\r?\n/).compact.join('<br/>')
content.gsub!(/(«[^\W]*»)/, '<span style="color:red">\1</span>')
sections[meta['sort'].to_i] = "<p%s>%s%s</p>" % [style, heading, content]
end
head = '<head><title>%s</title></head>' % filename
'<html>%s<body style="font-family:times"><div>%s</div></body></html>' % [
head,
sections.sort.map {|k,v| v}.join('</div><div>')]
end
def show_hash(hash)
hash.map{|k,v| '<strong>%s</strong>:%s' % [k,v || CGI::escapeHTML(v)]}.sort.join('<hr/>')
end