radiant-database_mailer-extension 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +159 -0
- data/Rakefile +120 -0
- data/app/controllers/admin/form_datas_controller.rb +77 -0
- data/app/controllers/database_mailer_processing.rb +19 -0
- data/app/helpers/admin/form_datas_helper.rb +57 -0
- data/app/models/form_data.rb +93 -0
- data/app/models/form_data_asset.rb +14 -0
- data/app/views/admin/form_datas/_export.html.haml +33 -0
- data/app/views/admin/form_datas/_filters.html.haml +27 -0
- data/app/views/admin/form_datas/index.html.haml +34 -0
- data/app/views/admin/form_datas/show.html.haml +49 -0
- data/config/routes.rb +7 -0
- data/database_mailer_extension.rb +31 -0
- data/db/migrate/001_create_form_datas.rb +16 -0
- data/db/migrate/002_add_data_columns.rb +13 -0
- data/db/migrate/20090722135916_create_form_data_assets.rb +21 -0
- data/features/datasets/database_mailer_dataset.rb +19 -0
- data/features/datasets/mailers_dataset.rb +69 -0
- data/features/fixtures/attachment.jpg +0 -0
- data/features/saving_emails_to_database.feature +45 -0
- data/features/step_definitions/admin_steps.rb +6 -0
- data/features/step_definitions/email_steps.rb +73 -0
- data/features/step_definitions/form_data_steps.rb +3 -0
- data/features/step_definitions/webrat_steps.rb +119 -0
- data/features/support/env.rb +28 -0
- data/features/support/paths.rb +25 -0
- data/lib/radiant-database_mailer-extension.rb +8 -0
- data/lib/tasks/database_mailer_extension_tasks.rake +31 -0
- data/public/javascripts/admin/database_mailer.js +73 -0
- data/public/stylesheets/sass/admin/database_mailer.sass +235 -0
- data/radiant-database_mailer-extension.gemspec +26 -0
- data/spec/controllers/form_datas_controller_spec.rb +272 -0
- data/spec/controllers/mail_controller_spec.rb +40 -0
- data/spec/helpers/form_datas_helper_spec.rb +5 -0
- data/spec/models/form_data_asset_spec.rb +11 -0
- data/spec/models/form_data_spec.rb +151 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/views/index.html.erb_spec.rb +25 -0
- metadata +139 -0
data/README.md
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
Database Mailer
|
2
|
+
===
|
3
|
+
|
4
|
+
About
|
5
|
+
---
|
6
|
+
|
7
|
+
A [Radiant][rd] Extension by [Aissac][ai] that adds database persistence to emailed forms. It works on top of the Radiant [Mailer Extension][rme] and the fields recorded to the database are user defined. The extension adds a tab to the Radiant admin interface allowing you to browse saved records.
|
8
|
+
|
9
|
+
Tested on Radiant 0.7.1, 0.8 and 0.9 RC1.
|
10
|
+
|
11
|
+
Check out the [screencast][rce]
|
12
|
+
|
13
|
+
Features
|
14
|
+
---
|
15
|
+
|
16
|
+
* Save posted form fields and entire mail message to the database
|
17
|
+
* Save e-mail attachments using paperclip
|
18
|
+
* Configurable save-to-database for mailer forms
|
19
|
+
* Add fields to be saved without loosing data
|
20
|
+
* Admin interface to browse saved records
|
21
|
+
* Export data to CSV and XLS
|
22
|
+
|
23
|
+
Important Notice!
|
24
|
+
---
|
25
|
+
|
26
|
+
The git branches on this repository hold stable versions of the extension for older versions of Radiant CMS. For example the _0.8_ branch is compatible with Radiant 0.8.
|
27
|
+
|
28
|
+
To checkout one of these branches:
|
29
|
+
|
30
|
+
git clone git://github.com/Aissac/radiant-database-mailer-extension.git vendor/extensions/database_mailer
|
31
|
+
cd vendor/extensions/database_mailer
|
32
|
+
git checkout -b <branch-name> origin/<remote-branch-name>
|
33
|
+
|
34
|
+
As an example if you're working on Radiant 0.8 you will need to checkout the 0.8 branch:
|
35
|
+
|
36
|
+
cd vendor/extensions/database_mailer
|
37
|
+
git checkout -b my_branch origin/0.8
|
38
|
+
|
39
|
+
Installation
|
40
|
+
---
|
41
|
+
|
42
|
+
Radiant Database Mailer Extension has three dependecies, the Radiant Mailer Extension, the `will_paginate` gem/plugin and the `paperclip` gem/plugin
|
43
|
+
|
44
|
+
Install the `mailer` extension:
|
45
|
+
|
46
|
+
git clone git://github.com/radiant/radiant-mailer-extension.git vendor/extensions/mailer
|
47
|
+
|
48
|
+
###Note
|
49
|
+
|
50
|
+
At the time being you will need Aissac's version of the [Radiant Mailer Extension][arme], as it incorporates sending e-mails with attachments.
|
51
|
+
|
52
|
+
the `will_paginate` gem/plugin:
|
53
|
+
|
54
|
+
git clone git://github.com/mislav/will_paginate.git vendor/plugins/will_paginate
|
55
|
+
|
56
|
+
or
|
57
|
+
|
58
|
+
sudo gem install will_paginate
|
59
|
+
|
60
|
+
and the `paperclip` gem/plugin
|
61
|
+
|
62
|
+
git clone git://github.com/thoughtbot/paperclip.git vendor/plugins/paperclip
|
63
|
+
|
64
|
+
or
|
65
|
+
|
66
|
+
sudo gem install paperclip
|
67
|
+
|
68
|
+
Next edit `config/environment.rb` and add desired fields to be recorded:
|
69
|
+
|
70
|
+
DATABASE_MAILER_COLUMNS = {
|
71
|
+
:name => :string,
|
72
|
+
:message => :text,
|
73
|
+
:email => :string
|
74
|
+
}
|
75
|
+
|
76
|
+
And finally add the [Database Mailer Extension][rdme]:
|
77
|
+
|
78
|
+
git clone git://github.com/Aissac/radiant-database-mailer-extension.git vendor/extensions/database_mailer
|
79
|
+
|
80
|
+
Migrate and update the extension:
|
81
|
+
|
82
|
+
rake radiant:extensions:database_mailer:migrate
|
83
|
+
rake radiant:extensions:database_mailer:update
|
84
|
+
|
85
|
+
Configuration
|
86
|
+
---
|
87
|
+
|
88
|
+
Adding fields to the `DATABASE_MAILER_COLUMNS` hash and re-running `rake radiant:extensions:database_mailer:migrate` nondestructively adds fields to be saved. Fields removed from the hash are not deleted.
|
89
|
+
|
90
|
+
Look at the Mailer Extension README for information on how to configure mail delivery.
|
91
|
+
|
92
|
+
If you set `save_to_database` to false in the Mailer config, saving to the database is skipped and just mail delivery takes place. Example (in the `mailer` page part):
|
93
|
+
|
94
|
+
subject: From the website of Whatever
|
95
|
+
from: noreply@example.com
|
96
|
+
redirect_to: /contact/thank-you
|
97
|
+
save_to_database: false
|
98
|
+
recipients:
|
99
|
+
- one@one.com
|
100
|
+
- two@two.com
|
101
|
+
|
102
|
+
Any attachments that the e-mail might have will be saved on the file system. They can be downloaded from the details page of every record.
|
103
|
+
|
104
|
+
If you want to take advantage of the blob field you need to create a `email` page part. The blob field keeps the sent version of the email.
|
105
|
+
|
106
|
+
Fields that are not specified by `DATABASE_MAILER_COLUMNS` are silently ignored.
|
107
|
+
|
108
|
+
Usage
|
109
|
+
---
|
110
|
+
|
111
|
+
Create your Mailer pages and make sure to use the same field names:
|
112
|
+
|
113
|
+
<r:mailer:form>
|
114
|
+
<label for="name">Name:</label><br/>
|
115
|
+
<r:mailer:text name="name" /><br/>
|
116
|
+
|
117
|
+
<label for="email">Email:</label><br/>
|
118
|
+
<r:mailer:text name="email" /><br/>
|
119
|
+
|
120
|
+
<label for="message">Message:</label><br/>
|
121
|
+
<r:mailer:textarea name="message" /> <br/>
|
122
|
+
|
123
|
+
<label for="attachment">Image:</label><br/>
|
124
|
+
<r:mailer:file name="attachment" /><br/>
|
125
|
+
|
126
|
+
<input type="submit" value="Send" />
|
127
|
+
</r:mailer:form>
|
128
|
+
|
129
|
+
Create the `mailer` page part:
|
130
|
+
|
131
|
+
subject: From the website of Whatever
|
132
|
+
from: noreply@example.com
|
133
|
+
redirect_to: /contact/thank-you
|
134
|
+
recipients:
|
135
|
+
- one@one.com
|
136
|
+
- two@two.com
|
137
|
+
|
138
|
+
Create an `email` page part (to take advantage of the blob field):
|
139
|
+
|
140
|
+
<r:mailer>
|
141
|
+
Name: <r:get name="name" />
|
142
|
+
Email: <r:get name="email" />
|
143
|
+
Message: <r:get name="message" />
|
144
|
+
</r:mailer>
|
145
|
+
|
146
|
+
Contributors
|
147
|
+
---
|
148
|
+
|
149
|
+
* Cristi Duma ([@cristi_duma][cd])
|
150
|
+
* Istvan Hoka ([@ihoka][ih])
|
151
|
+
|
152
|
+
[rd]: http://radiantcms.org/
|
153
|
+
[ai]: http://www.aissac.ro/
|
154
|
+
[rme]: http://github.com/radiant/radiant-mailer-extension
|
155
|
+
[arme]: http://github.com/Aissac/radiant-mailer-extension
|
156
|
+
[rdme]: http://blog.aissac.ro/radiant/database-mailer-extension/
|
157
|
+
[cd]: http://twitter.com/cristi_duma
|
158
|
+
[ih]: http://twitter.com/ihoka
|
159
|
+
[rce]:http://blog.aissac.ro/2010/03/16/episode-5-radiant-database-mailer-extension/
|
data/Rakefile
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# I think this is the one that should be moved to the extension Rakefile template
|
2
|
+
|
3
|
+
# In rails 1.2, plugins aren't available in the path until they're loaded.
|
4
|
+
# Check to see if the rspec plugin is installed first and require
|
5
|
+
# it if it is. If not, use the gem version.
|
6
|
+
|
7
|
+
# Determine where the RSpec plugin is by loading the boot
|
8
|
+
unless defined? RADIANT_ROOT
|
9
|
+
ENV["RAILS_ENV"] = "test"
|
10
|
+
case
|
11
|
+
when ENV["RADIANT_ENV_FILE"]
|
12
|
+
require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
|
13
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
14
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
|
15
|
+
else
|
16
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake'
|
21
|
+
require 'rake/rdoctask'
|
22
|
+
require 'rake/testtask'
|
23
|
+
|
24
|
+
rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
|
25
|
+
$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
|
26
|
+
require 'spec/rake/spectask'
|
27
|
+
# require 'spec/translator'
|
28
|
+
|
29
|
+
# Cleanup the RADIANT_ROOT constant so specs will load the environment
|
30
|
+
Object.send(:remove_const, :RADIANT_ROOT)
|
31
|
+
|
32
|
+
extension_root = File.expand_path(File.dirname(__FILE__))
|
33
|
+
|
34
|
+
task :default => :spec
|
35
|
+
task :stats => "spec:statsetup"
|
36
|
+
|
37
|
+
desc "Run all specs in spec directory"
|
38
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
39
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
40
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
41
|
+
end
|
42
|
+
|
43
|
+
namespace :spec do
|
44
|
+
desc "Run all specs in spec directory with RCov"
|
45
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
46
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
47
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
48
|
+
t.rcov = true
|
49
|
+
t.rcov_opts = ["--exclude", "spec/*,gems/*", "--rails"]
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Print Specdoc for all specs"
|
53
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
54
|
+
t.spec_opts = ["--format", "specdoc", "--dry-run"]
|
55
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
56
|
+
end
|
57
|
+
|
58
|
+
[:models, :controllers, :views, :helpers].each do |sub|
|
59
|
+
desc "Run the specs under spec/#{sub}"
|
60
|
+
Spec::Rake::SpecTask.new(sub) do |t|
|
61
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
62
|
+
t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Hopefully no one has written their extensions in pre-0.9 style
|
67
|
+
# desc "Translate specs from pre-0.9 to 0.9 style"
|
68
|
+
# task :translate do
|
69
|
+
# translator = ::Spec::Translator.new
|
70
|
+
# dir = RAILS_ROOT + '/spec'
|
71
|
+
# translator.translate(dir, dir)
|
72
|
+
# end
|
73
|
+
|
74
|
+
# Setup specs for stats
|
75
|
+
task :statsetup do
|
76
|
+
require 'code_statistics'
|
77
|
+
::STATS_DIRECTORIES << %w(Model\ specs spec/models)
|
78
|
+
::STATS_DIRECTORIES << %w(View\ specs spec/views)
|
79
|
+
::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
|
80
|
+
::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
|
81
|
+
::CodeStatistics::TEST_TYPES << "Model specs"
|
82
|
+
::CodeStatistics::TEST_TYPES << "View specs"
|
83
|
+
::CodeStatistics::TEST_TYPES << "Controller specs"
|
84
|
+
::CodeStatistics::TEST_TYPES << "Helper specs"
|
85
|
+
::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
|
86
|
+
end
|
87
|
+
|
88
|
+
namespace :db do
|
89
|
+
namespace :fixtures do
|
90
|
+
desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
|
91
|
+
task :load => :environment do
|
92
|
+
require 'active_record/fixtures'
|
93
|
+
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
|
94
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
|
95
|
+
Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
desc 'Generate documentation for the database_mailer extension.'
|
103
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
104
|
+
rdoc.rdoc_dir = 'rdoc'
|
105
|
+
rdoc.title = 'DatabaseMailerExtension'
|
106
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
107
|
+
rdoc.rdoc_files.include('README')
|
108
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
109
|
+
end
|
110
|
+
|
111
|
+
# For extensions that are in transition
|
112
|
+
desc 'Test the database_mailer extension.'
|
113
|
+
Rake::TestTask.new(:test) do |t|
|
114
|
+
t.libs << 'lib'
|
115
|
+
t.pattern = 'test/**/*_test.rb'
|
116
|
+
t.verbose = true
|
117
|
+
end
|
118
|
+
|
119
|
+
# Load any custom rakefiles for extension
|
120
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class Admin::FormDatasController < ApplicationController
|
2
|
+
|
3
|
+
require 'fastercsv'
|
4
|
+
before_filter :attach_assets
|
5
|
+
LIST_PARAMS_BASE = [:page, :sort_by, :sort_order]
|
6
|
+
EXPORT_COLUMNS = FormData::SORT_COLUMNS.sort - ["exported"] + ["blob"]
|
7
|
+
def index
|
8
|
+
|
9
|
+
@urls = FormData.find_all_group_by_url
|
10
|
+
filter_by_params(FormData::FILTER_COLUMNS)
|
11
|
+
respond_to do |format|
|
12
|
+
format.html {
|
13
|
+
@saved_items = FormData.form_paginate(list_params)
|
14
|
+
}
|
15
|
+
|
16
|
+
exported_at = Time.now
|
17
|
+
selected_export_columns = EXPORT_COLUMNS.reject{|k| params["export_#{k}"].blank?}
|
18
|
+
|
19
|
+
format.csv {
|
20
|
+
csv_string = FormData.export_csv(list_params, selected_export_columns, exported_at, !params[:include_all].blank?)
|
21
|
+
send_data csv_string,
|
22
|
+
:type => "text/csv",
|
23
|
+
:filename => "export_#{exported_at.strftime("%Y-%m-%d_%H-%M")}.csv",
|
24
|
+
:disposition => 'attachment'
|
25
|
+
}
|
26
|
+
format.xls {
|
27
|
+
xls_path = FormData.export_xls(list_params, selected_export_columns, exported_at, !params[:include_all].blank?)
|
28
|
+
send_file xls_path,
|
29
|
+
:type => "application/vnd.ms-excel",
|
30
|
+
:filename => "form_data_#{exported_at.strftime("%Y-%m-%d_%H-%M")}.xls",
|
31
|
+
:disposition => 'attachment'
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def show
|
37
|
+
@form_data = FormData.find(params[:id])
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
@form_data = FormData.find(params[:id])
|
42
|
+
@form_data.destroy
|
43
|
+
flash[:notice] = "Record deleted!"
|
44
|
+
redirect_to admin_form_datas_path
|
45
|
+
end
|
46
|
+
|
47
|
+
def list_params
|
48
|
+
@list_params ||= {}
|
49
|
+
end
|
50
|
+
helper_method :list_params
|
51
|
+
|
52
|
+
protected
|
53
|
+
def filter_by_params(args)
|
54
|
+
args = args + LIST_PARAMS_BASE
|
55
|
+
args.each do |arg|
|
56
|
+
list_params[arg] = params[:reset] ? params[arg] : params[arg] || cookies[arg]
|
57
|
+
end
|
58
|
+
list_params[:page] ||= "1"
|
59
|
+
|
60
|
+
update_list_params_cookies(args)
|
61
|
+
|
62
|
+
# pentru will_paginate
|
63
|
+
params[:page] = list_params[:page]
|
64
|
+
end
|
65
|
+
|
66
|
+
def update_list_params_cookies(args)
|
67
|
+
args.each do |key|
|
68
|
+
cookies[key] = { :value => list_params[key], :path => "/#{controller_path}" }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def attach_assets
|
73
|
+
include_stylesheet "admin/database_mailer"
|
74
|
+
include_javascript "admin/database_mailer"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module DatabaseMailerProcessing
|
2
|
+
|
3
|
+
def process_mail_with_database(mail, config)
|
4
|
+
if mail.valid?
|
5
|
+
page = mail.page
|
6
|
+
plain_body = (page.part( :email ) ? page.render_part( :email ) : page.render_part( :email_plain ))
|
7
|
+
|
8
|
+
if config[:save_to_database] || config[:save_to_database].nil?
|
9
|
+
fd = FormData.create(mail.data.merge(:url => mail.page.url, :blob => plain_body))
|
10
|
+
mail.data.each do |k, v|
|
11
|
+
if v.class.to_s == "Tempfile"
|
12
|
+
FormDataAsset.create(:form_data_id => fd.id, :field_name => k, :attachment => v)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
process_mail_without_database(mail, config)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Admin::FormDatasHelper
|
2
|
+
SORT_CYCLE = {'asc' => 'desc', 'desc' => 'none', 'none' => 'asc'}
|
3
|
+
|
4
|
+
def sortable_column_head(label, attribute)
|
5
|
+
current_order = (currently_sorting_by?(attribute) && %w(none asc desc).include?(list_params[:sort_order])) ? list_params[:sort_order] : 'none'
|
6
|
+
dom_class = currently_sorting_by?(attribute) ? "sort_#{current_order}" : nil
|
7
|
+
|
8
|
+
link_to(label,
|
9
|
+
params.merge(list_params).merge(:sort_by => attribute, :sort_order => SORT_CYCLE[current_order], :reset => 1),
|
10
|
+
:class => dom_class)
|
11
|
+
end
|
12
|
+
|
13
|
+
def filter_actions_tag
|
14
|
+
submit_tag("Filter") + content_tag('span', ' | ' + reset_filters_tag)
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset_filters_tag
|
18
|
+
link_to("Reset", :reset => 1)
|
19
|
+
end
|
20
|
+
|
21
|
+
def each_data_column(&block)
|
22
|
+
DATABASE_MAILER_COLUMNS.each_key do |key|
|
23
|
+
yield key
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def data_columns
|
28
|
+
DATABASE_MAILER_COLUMNS.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def date_format(timestamp)
|
32
|
+
timestamp && l(timestamp, :format => :long)
|
33
|
+
end
|
34
|
+
|
35
|
+
def filters_present(&block)
|
36
|
+
if (DATABASE_MAILER_COLUMNS.keys + [:url]).any? { |k| !list_params[k].blank?}
|
37
|
+
yield
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def current_filters
|
42
|
+
all_filters = DATABASE_MAILER_COLUMNS.keys + [:url]
|
43
|
+
all_filters.map do |k|
|
44
|
+
k unless list_params[k].blank?
|
45
|
+
end.compact.join(", ")
|
46
|
+
end
|
47
|
+
|
48
|
+
def export_columns
|
49
|
+
Admin::FormDatasController::EXPORT_COLUMNS
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def currently_sorting_by?(attribute)
|
55
|
+
list_params[:sort_by] == attribute.to_s
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'fastercsv'
|
2
|
+
require 'spreadsheet'
|
3
|
+
|
4
|
+
class FormData < ActiveRecord::Base
|
5
|
+
|
6
|
+
has_many :form_data_assets, :dependent => :destroy
|
7
|
+
|
8
|
+
SORT_COLUMNS = DATABASE_MAILER_COLUMNS.keys.map(&:to_s) + ['created_at', 'url', 'exported']
|
9
|
+
FILTER_COLUMNS = DATABASE_MAILER_COLUMNS.keys + [:url]
|
10
|
+
|
11
|
+
DATABASE_MAILER_COLUMNS.each_key do | col |
|
12
|
+
FormData.named_scope :"by_#{col}", lambda { |item|
|
13
|
+
{:conditions => ["LOWER(#{col}) LIKE ?", "%#{item.to_s.downcase}%"]}
|
14
|
+
}
|
15
|
+
end
|
16
|
+
named_scope :by_url, lambda{ |item| {:conditions => ["url = ?", item]}}
|
17
|
+
named_scope :not_exported, :conditions => {:exported => nil}
|
18
|
+
|
19
|
+
def self.form_paginate(params)
|
20
|
+
options = {
|
21
|
+
:page => params[:page],
|
22
|
+
:per_page => 10,
|
23
|
+
}
|
24
|
+
if SORT_COLUMNS.include?(params[:sort_by]) && %w(asc desc).include?(params[:sort_order])
|
25
|
+
options[:order] = "#{params[:sort_by]} #{params[:sort_order]}"
|
26
|
+
end
|
27
|
+
params.reject { |k, v| !FILTER_COLUMNS.include?(k) }.
|
28
|
+
inject(FormData) { |scope, pair| pair[1].blank? ? scope : scope.send(:"by_#{pair[0]}", pair[1]) }.
|
29
|
+
paginate(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.find_all_group_by_url
|
33
|
+
find(:all, :group => 'url', :select => 'url')
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find_for_export(params, export_all)
|
37
|
+
options = {}
|
38
|
+
if SORT_COLUMNS.include?(params[:sort_by]) && %w(asc desc).include?(params[:sort_order])
|
39
|
+
options[:order] = "#{params[:sort_by]} #{params[:sort_order]}"
|
40
|
+
end
|
41
|
+
|
42
|
+
initial = export_all ? FormData : FormData.not_exported
|
43
|
+
|
44
|
+
params.reject { |k, v| !FILTER_COLUMNS.include?(k) }.
|
45
|
+
inject(initial) { |scope, pair| pair[1].blank? ? scope : scope.send(:"by_#{pair[0]}", pair[1]) }.find(:all, :order => options[:order])
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.export_csv(params, selected_export_columns, exported_at, export_all=false)
|
49
|
+
@items = find_for_export(params, export_all)
|
50
|
+
|
51
|
+
FasterCSV.generate do |csv|
|
52
|
+
csv << selected_export_columns.map{|k| k.capitalize}
|
53
|
+
@items.each do |ei|
|
54
|
+
csv << selected_export_columns.map do |k|
|
55
|
+
formatting_for_csv(ei.send(k))
|
56
|
+
end
|
57
|
+
ei.exported = exported_at.to_s(:db)
|
58
|
+
ei.save
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.export_xls(params, selected_export_columns, exported_at, export_all=false)
|
64
|
+
items = find_for_export(params, export_all)
|
65
|
+
book = Spreadsheet::Workbook.new
|
66
|
+
sheet = book.create_worksheet :name => 'Form Data'
|
67
|
+
|
68
|
+
sheet.row(0).replace(selected_export_columns.map{|k| k.capitalize})
|
69
|
+
|
70
|
+
items.each_with_index do |item, i|
|
71
|
+
sheet.row(i+1).replace(selected_export_columns.map {|k| item.send(k)})
|
72
|
+
item.exported = exported_at.to_s(:db)
|
73
|
+
item.save
|
74
|
+
end
|
75
|
+
|
76
|
+
tmp_file = Tempfile.new("form_data")
|
77
|
+
book.write tmp_file
|
78
|
+
tmp_file.path
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.formatting_for_csv(item)
|
82
|
+
if Time === item
|
83
|
+
item.to_s(:db)
|
84
|
+
else
|
85
|
+
item.to_s.gsub(/\s/, ' ')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def initialize(params={})
|
90
|
+
data = params.dup.delete_if { |k, v| !self.class.column_names.include?(k.to_s) }
|
91
|
+
super(data)
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'paperclip'
|
2
|
+
|
3
|
+
class FormDataAsset < ActiveRecord::Base
|
4
|
+
belongs_to :form_data
|
5
|
+
|
6
|
+
has_attached_file :attachment, :styles => { :thumb => '100x100>' }
|
7
|
+
|
8
|
+
IMAGE_CONTENT_TYPES = ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg']
|
9
|
+
|
10
|
+
def image?
|
11
|
+
IMAGE_CONTENT_TYPES.include? attachment_content_type
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#x_filters
|
2
|
+
%a#x_expander.expand{:href => "javascript:;"} Export
|
3
|
+
#x_form{:style => "display:none"}
|
4
|
+
- form_tag(admin_form_datas_path, {:method => :get}) do
|
5
|
+
= list_params.map {|k,v| hidden_field_tag(k,v)}.join
|
6
|
+
%table.export
|
7
|
+
%tr
|
8
|
+
%td{:colspan => "2"} Choose the columns you want to export:
|
9
|
+
- export_columns.each do |ec|
|
10
|
+
%tr
|
11
|
+
%th= check_box_tag "export_#{ec}", ec, true
|
12
|
+
%td
|
13
|
+
%label{:for => "export_#{ec}"}
|
14
|
+
= ec.to_s.capitalize
|
15
|
+
%tr
|
16
|
+
%th= check_box_tag "include_all", "yes"
|
17
|
+
%td
|
18
|
+
%label{:for => "include_all"} Include allready exported
|
19
|
+
%tr
|
20
|
+
%td.sep{:colspan => "2"} Choose the format:
|
21
|
+
%tr
|
22
|
+
%th= radio_button_tag "format", "csv"
|
23
|
+
%td
|
24
|
+
%label{:for => "format_csv"} Comma separated values (CSV)
|
25
|
+
%tr
|
26
|
+
%th= radio_button_tag "format", "xls"
|
27
|
+
%td
|
28
|
+
%label{:for => "format_xls"} Microsoft Excel Sheet (XLS)
|
29
|
+
%tr
|
30
|
+
%th
|
31
|
+
%td
|
32
|
+
= submit_tag "Export"
|
33
|
+
%a.close{:href => "javascript:closeX()"} Close
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#filters
|
2
|
+
%a#expander.expand{:href => 'javascript:;'} Filter
|
3
|
+
#current_filters
|
4
|
+
- filters_present do
|
5
|
+
Applied filters:
|
6
|
+
= current_filters
|
7
|
+
= link_to 'Reset', :reset => 1
|
8
|
+
#form{:style => "display:none"}
|
9
|
+
- form_tag({}, {:method => :get}) do
|
10
|
+
= hidden_field_tag(:reset => 1)
|
11
|
+
%table.search
|
12
|
+
%tr
|
13
|
+
%th
|
14
|
+
%label{:for => "url"} URL:
|
15
|
+
%td
|
16
|
+
= select_tag("url", '<option value="">- All -</option>' + options_from_collection_for_select(@urls, "url", "url", list_params[:url]))
|
17
|
+
- each_data_column do |k|
|
18
|
+
%tr
|
19
|
+
%th
|
20
|
+
%label{:for => k}
|
21
|
+
= k.to_s.capitalize + ":"
|
22
|
+
%td
|
23
|
+
= text_field_tag k, list_params[k]
|
24
|
+
%tr
|
25
|
+
%th
|
26
|
+
%td= filter_actions_tag
|
27
|
+
%a.close{:href => "javascript:close()"} Close
|
@@ -0,0 +1,34 @@
|
|
1
|
+
.grey
|
2
|
+
#filtering
|
3
|
+
= render :partial => "filters"
|
4
|
+
= render :partial => "export"
|
5
|
+
#results
|
6
|
+
%table.results
|
7
|
+
%thead
|
8
|
+
%tr
|
9
|
+
%th.created_at= sortable_column_head "Created at", :created_at
|
10
|
+
%th.url= sortable_column_head "URL", :url
|
11
|
+
- each_data_column do |k|
|
12
|
+
%th= sortable_column_head k.to_s.capitalize, k
|
13
|
+
%th.exported= sortable_column_head "Exported", :exported
|
14
|
+
%th.actions Actions
|
15
|
+
%tbody
|
16
|
+
- @saved_items.each do |si|
|
17
|
+
%tr
|
18
|
+
%td= date_format(si.created_at)
|
19
|
+
%td= si.url
|
20
|
+
= data_columns.map { |k| "<td>#{si.send(k)}</td>" }
|
21
|
+
%td= si.exported ? date_format(si.exported) : "no"
|
22
|
+
%td.actions
|
23
|
+
= link_to "Show", admin_form_data_path(si)
|
24
|
+
= link_to 'Delete', admin_form_data_path(si.id), :method => :delete, :confirm => "Really delete record?"
|
25
|
+
- if @saved_items.empty?
|
26
|
+
%tr
|
27
|
+
%td{:colspan => data_columns.size + 2} No Results!
|
28
|
+
%tfoot
|
29
|
+
%tr
|
30
|
+
%th{:colspan => 4}
|
31
|
+
= page_entries_info @saved_items
|
32
|
+
%th{:colspan => "#{data_columns.size}"}
|
33
|
+
= will_paginate @saved_items, :inner_window => 1, :outer_window => 1
|
34
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
%h1 Form Data
|
3
|
+
|
4
|
+
#show.clearfix
|
5
|
+
#tab_control
|
6
|
+
#tabs.tabs
|
7
|
+
%a#details_lnk.tab.here{ :href => "#", :onclick => "show_details();" }
|
8
|
+
%span details
|
9
|
+
- unless @form_data
|
10
|
+
%a#attachments_lnk.tab{ :href => "#", :onclick => "show_attachments();" }
|
11
|
+
%span attachments
|
12
|
+
#pages.pages
|
13
|
+
#details.page
|
14
|
+
%table.result
|
15
|
+
%tr
|
16
|
+
%th Created_at
|
17
|
+
%td= date_format(@form_data.created_at)
|
18
|
+
%th Sent version of the email
|
19
|
+
%tr
|
20
|
+
%th URL:
|
21
|
+
%td= @form_data.url
|
22
|
+
%td{ :rowspan => "#{data_columns.size + 2}" }= simple_format(@form_data.blob)
|
23
|
+
- data_columns.each do |dc|
|
24
|
+
%tr
|
25
|
+
%th= dc.to_s.capitalize
|
26
|
+
%td= @form_data.send(dc)
|
27
|
+
%tr
|
28
|
+
%th Exported
|
29
|
+
%td= @form_data.exported? ? date_format(@form_data.exported) : "no"
|
30
|
+
- unless @form_data
|
31
|
+
#attachments.page{ :style => "display:none;"}
|
32
|
+
%table.attachments
|
33
|
+
%thead
|
34
|
+
%tr
|
35
|
+
%th Field Name
|
36
|
+
%th Link
|
37
|
+
%th Thumbnail
|
38
|
+
%tbody
|
39
|
+
- @form_data.form_data_assets.each do |att|
|
40
|
+
%tr
|
41
|
+
%td= att.field_name.blank? ? "Field:" : att.field_name.capitalize
|
42
|
+
%td
|
43
|
+
= link_to att.attachment_file_name, att.attachment.url
|
44
|
+
- if att.image?
|
45
|
+
%td
|
46
|
+
= image_tag att.attachment.url(:thumb)
|
47
|
+
- else
|
48
|
+
%td
|
49
|
+
= link_to "Back", admin_form_datas_path, :class => "back"
|