spree_mail 0.40.0.3 → 0.40.0.4
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 +4 -4
- data/Rakefile +23 -87
- data/app/controllers/admin/emails_controller.rb +15 -39
- data/app/controllers/admin/subscribers_controller.rb +21 -41
- data/app/controllers/emails_controller.rb +11 -10
- data/app/controllers/subscribers_controller.rb +6 -5
- data/app/model/email.rb +8 -17
- data/app/model/subscriber.rb +5 -11
- data/app/validators/email_validator.rb +1 -1
- data/app/views/admin/emails/_form.html.erb +8 -16
- data/app/views/admin/emails/edit.html.erb +1 -1
- data/app/views/admin/emails/index.html.erb +25 -20
- data/app/views/admin/emails/new.html.erb +1 -1
- data/app/views/admin/emails/show.html.erb +5 -5
- data/app/views/admin/subscribers/_form.html.erb +2 -2
- data/app/views/admin/subscribers/_options.html.erb +2 -2
- data/app/views/admin/subscribers/edit.html.erb +1 -1
- data/app/views/admin/subscribers/index.html.erb +27 -25
- data/app/views/admin/subscribers/new.html.erb +1 -1
- data/app/views/admin/subscribers/show.html.erb +1 -1
- data/app/views/hooks/_footer_left.html.erb +1 -1
- data/app/views/hooks/_subscriber_static_content.html.erb +1 -1
- data/app/views/layouts/email.html.erb +7 -7
- data/app/views/subscribers/_fields.html.erb +1 -1
- data/app/views/subscribers/show.html.erb +4 -4
- data/config/locales/en.yml +18 -21
- data/config/routes.rb +1 -1
- data/lib/spree_mail.rb +8 -0
- data/lib/spree_mail/has_token.rb +27 -0
- data/lib/spree_mail/version.rb +1 -1
- metadata +46 -30
data/README.md
CHANGED
@@ -14,7 +14,7 @@ To create a spree mail demo app, run the following:
|
|
14
14
|
rails new spree_mail_example
|
15
15
|
cd spree_mail_example
|
16
16
|
echo "gem 'spree', '0.40.2'" >> Gemfile
|
17
|
-
echo "gem 'spree_mail', '0.40.0.
|
17
|
+
echo "gem 'spree_mail', '0.40.0.4'" >> Gemfile
|
18
18
|
rm public/index.html
|
19
19
|
bundle install
|
20
20
|
rake spree:install spree_mail:install db:migrate db:seed
|
@@ -22,9 +22,9 @@ To create a spree mail demo app, run the following:
|
|
22
22
|
|
23
23
|
Or all at once:
|
24
24
|
|
25
|
-
rails new spree_mail_example; cd spree_mail_example; echo "gem 'spree', '0.40.2'" >> Gemfile; echo "gem 'spree_mail', '0.40.0.
|
25
|
+
rails new spree_mail_example; cd spree_mail_example; echo "gem 'spree', '0.40.2'" >> Gemfile; echo "gem 'spree_mail', '0.40.0.4'" >> Gemfile; rm public/index.html; bundle install; rake spree:install spree_mail:install db:migrate db:seed
|
26
26
|
|
27
|
-
`rake db:sample` if you want to...
|
27
|
+
`rake spree_sample:install db:sample` if you want to...
|
28
28
|
|
29
29
|
Then start the server with `rails s`
|
30
30
|
|
@@ -42,7 +42,7 @@ Before sending, you may need to create an action_mailer initializer.
|
|
42
42
|
To Do
|
43
43
|
-----
|
44
44
|
|
45
|
-
* Write
|
45
|
+
* Write more tests
|
46
46
|
* Write a rake task that converts current users to subscribers
|
47
47
|
* Add checkbox on user signup: 'sign up for our mailing list'
|
48
48
|
* Add user help to email form
|
data/Rakefile
CHANGED
@@ -1,94 +1,30 @@
|
|
1
|
-
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rake'
|
10
|
+
require 'rake/rdoctask'
|
2
11
|
require 'rake/testtask'
|
12
|
+
|
3
13
|
Bundler::GemHelper.install_tasks
|
4
14
|
|
5
|
-
Rake::TestTask.new do |t|
|
6
|
-
t.libs <<
|
15
|
+
Rake::TestTask.new(:test) do |t|
|
16
|
+
t.libs << 'lib'
|
17
|
+
t.libs << 'test'
|
7
18
|
t.pattern = 'test/**/*_test.rb'
|
8
|
-
t.verbose =
|
19
|
+
t.verbose = false
|
9
20
|
end
|
10
21
|
|
22
|
+
task :default => :test
|
11
23
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# require File.expand_path('../test/test_helper', __FILE__)
|
20
|
-
# Dir["test/**/*.rb"].reject{|file| file.match(/test_helper/) != nil }.each do |file|
|
21
|
-
# puts "Loading #{file}"
|
22
|
-
# load file
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
#end
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
desc "Default Task"
|
31
|
-
task :default => [ :test ]
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
# TODO: pull in the spree/core/Rakefile bits that set up for testing
|
41
|
-
desc "Regenerates a Rails 3 app for testing"
|
42
|
-
task :test_app do
|
43
|
-
# TODO - this path requires a certain directory structure -- need
|
44
|
-
# to think about how to refactor
|
45
|
-
|
46
|
-
|
47
|
-
files = `gem contents spree`.split("\n").select{|file| file.match("test_app_generator")}
|
48
|
-
if files.length == 1
|
49
|
-
require files.first
|
50
|
-
class SpreeMailTestAppGenerator < Spree::Generators::TestAppGenerator
|
51
|
-
def tweak_gemfile
|
52
|
-
append_file "Gemfile" ,
|
53
|
-
<<-gems
|
54
|
-
gem 'activemerchant'
|
55
|
-
gem 'spree_core', '>=0.40.2'
|
56
|
-
gem 'spree_auth', '>=0.40.2'
|
57
|
-
gem 'spree_mail', :path => "#{File.dirname(__FILE__)}"
|
58
|
-
gems
|
59
|
-
end
|
60
|
-
|
61
|
-
def install_spree_gems
|
62
|
-
|
63
|
-
puts "-----------------------------------------"
|
64
|
-
puts "Installing gems..."
|
65
|
-
`bundle install --gemfile=spec/test_app/Gemfile`
|
66
|
-
puts "-----------------------------------------"
|
67
|
-
|
68
|
-
inside "test_app" do
|
69
|
-
run 'rake spree_core:install'
|
70
|
-
run 'rake spree_auth:install'
|
71
|
-
run 'rake spree_mail:install'
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def migrate_db
|
76
|
-
run_migrations
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
SpreeMailTestAppGenerator.start
|
81
|
-
|
82
|
-
puts "spec/test_app created. "
|
83
|
-
|
84
|
-
else
|
85
|
-
puts "Failed: Could not find lib/generators/spree/test_app_generator.rb"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
namespace :test_app do
|
90
|
-
desc 'Rebuild test database'
|
91
|
-
task :rebuild_db do
|
92
|
-
system("cd spec/test_app && rake db:drop db:migrate RAILS_ENV=test")
|
93
|
-
end
|
94
|
-
end
|
24
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
25
|
+
rdoc.rdoc_dir = 'rdoc'
|
26
|
+
rdoc.title = 'SpreeMail'
|
27
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
28
|
+
rdoc.rdoc_files.include('README.rdoc')
|
29
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
30
|
+
end
|
@@ -2,18 +2,12 @@ class Admin::EmailsController < Admin::BaseController
|
|
2
2
|
|
3
3
|
resource_controller
|
4
4
|
|
5
|
-
before_filter :check_json_authenticity, :only => :index
|
6
5
|
before_filter :get_subscribers, :only => [:new, :create, :edit, :update]
|
7
6
|
|
8
|
-
index.response do |wants|
|
9
|
-
wants.html { render :action => :index }
|
10
|
-
wants.json { render :json => json_data }
|
11
|
-
end
|
12
7
|
destroy.success.wants.js { render_js_for_destroy }
|
13
8
|
|
14
|
-
|
15
9
|
def deliver
|
16
|
-
@email =
|
10
|
+
@email = object
|
17
11
|
sent, count = @email.deliver!
|
18
12
|
if sent
|
19
13
|
flash[:notice] = t('delivery_success', count)
|
@@ -23,39 +17,21 @@ class Admin::EmailsController < Admin::BaseController
|
|
23
17
|
redirect_to admin_email_path(@email)
|
24
18
|
end
|
25
19
|
|
26
|
-
|
27
|
-
|
28
20
|
private
|
29
|
-
|
30
|
-
## Allow different formats of json data to suit different ajax calls
|
31
|
-
#def json_data
|
32
|
-
# json_format = params[:json_format] or 'default'
|
33
|
-
# case json_format
|
34
|
-
# when 'basic'
|
35
|
-
# collection.map {|u| {'id' => u.id, 'name' => u.email}}.to_json
|
36
|
-
# else
|
37
|
-
# collection.to_json(:include =>
|
38
|
-
# {:bill_address => {:include => [:state, :country]},
|
39
|
-
# :ship_address => {:include => [:state, :country]}})
|
40
|
-
# end
|
41
|
-
#end
|
42
|
-
|
43
|
-
def get_subscribers
|
44
|
-
@subscribers = Subscriber.active
|
45
|
-
end
|
46
21
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@
|
22
|
+
def get_subscribers
|
23
|
+
@subscribers = Subscriber.active
|
24
|
+
end
|
25
|
+
|
26
|
+
def object
|
27
|
+
@object ||= Email.find_by_token(params[:id])
|
28
|
+
end
|
29
|
+
|
30
|
+
def collection
|
31
|
+
params[:search] ||= {}
|
32
|
+
params[:search][:meta_sort] ||= "subject.asc"
|
33
|
+
@search = end_of_association_chain.metasearch(params[:search])
|
34
|
+
@collection = @search.paginate(:per_page => Spree::Config[:admin_products_per_page], :page => params[:page])
|
59
35
|
end
|
60
|
-
|
36
|
+
|
61
37
|
end
|
@@ -2,13 +2,6 @@ class Admin::SubscribersController < Admin::BaseController
|
|
2
2
|
|
3
3
|
resource_controller
|
4
4
|
|
5
|
-
before_filter :check_json_authenticity, :only => :index
|
6
|
-
|
7
|
-
#index.response do |wants|
|
8
|
-
# wants.html { render :action => :index }
|
9
|
-
# wants.json { render :json => json_data }
|
10
|
-
#end
|
11
|
-
|
12
5
|
destroy.success.wants.js { render_js_for_destroy }
|
13
6
|
|
14
7
|
create.response do |wants|
|
@@ -22,9 +15,9 @@ class Admin::SubscribersController < Admin::BaseController
|
|
22
15
|
def resubscribe
|
23
16
|
@subscriber = object
|
24
17
|
if @subscriber.resubscribe!
|
25
|
-
flash[:notice] = t(
|
18
|
+
flash[:notice] = t('resubscribe_success')
|
26
19
|
else
|
27
|
-
flash[:error] = t(
|
20
|
+
flash[:error] = t('resubscribe_failed')
|
28
21
|
end
|
29
22
|
redirect_to request.referer
|
30
23
|
end
|
@@ -32,47 +25,34 @@ class Admin::SubscribersController < Admin::BaseController
|
|
32
25
|
def unsubscribe
|
33
26
|
@subscriber = object
|
34
27
|
if @subscriber.unsubscribe!
|
35
|
-
flash[:notice] = t(
|
28
|
+
flash[:notice] = t('unsubscribe_success')
|
36
29
|
else
|
37
|
-
flash[:error] = t(
|
30
|
+
flash[:error] = t('unsubscribe_failed')
|
38
31
|
end
|
39
32
|
redirect_to request.referer
|
40
33
|
end
|
41
34
|
|
42
35
|
def unsubscribed
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@search.order ||= "ascend_by_name"
|
47
|
-
|
48
|
-
@subscribers = @collection = @search.do_search.unsubscribed.paginate(:per_page => Spree::Config[:admin_products_per_page], :page => params[:page])
|
36
|
+
params[:search] ||= {}
|
37
|
+
params[:search][:unsubscribed_at_is_not_null] = true
|
38
|
+
@subscribers = collection
|
49
39
|
render :template => 'admin/subscribers/index'
|
50
40
|
end
|
51
41
|
|
52
|
-
|
53
42
|
private
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
# case json_format
|
59
|
-
# when 'basic'
|
60
|
-
# collection.map {|u| {'id' => u.id, 'name' => u.email}}.to_json
|
61
|
-
# else
|
62
|
-
# collection.to_json(:include =>
|
63
|
-
# {:bill_address => {:include => [:state, :country]},
|
64
|
-
# :ship_address => {:include => [:state, :country]}})
|
65
|
-
# end
|
66
|
-
#end
|
67
|
-
|
68
|
-
def collection
|
69
|
-
return @collection if @collection.present?
|
70
|
-
@search = Subscriber.searchlogic(params[:search])
|
43
|
+
|
44
|
+
def object
|
45
|
+
@object ||= Subscriber.find_by_token(params[:id])
|
46
|
+
end
|
71
47
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
48
|
+
def collection
|
49
|
+
params[:search] ||= {}
|
50
|
+
params[:search][:meta_sort] ||= "name.asc"
|
51
|
+
unless params[:search].has_key?(:unsubscribed_at_is_not_null)
|
52
|
+
params[:search][:unsubscribed_at_is_null] = true
|
53
|
+
end
|
54
|
+
@search = end_of_association_chain.metasearch(params[:search])
|
55
|
+
@collection = @search.paginate(:per_page => Spree::Config[:admin_products_per_page], :page => params[:page])
|
56
|
+
end
|
76
57
|
|
77
|
-
|
78
|
-
end
|
58
|
+
end
|
@@ -4,16 +4,17 @@ class EmailsController < Spree::BaseController
|
|
4
4
|
include ActionView::Helpers::TextHelper
|
5
5
|
|
6
6
|
def show
|
7
|
-
@subscriber = Subscriber.find_by_token(params[:
|
8
|
-
@email
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
@subscriber = Subscriber.find_by_token(params[:subscriber])
|
8
|
+
@email = Email.find_by_token(params[:email])
|
9
|
+
if @email.recipients.include?(@subscriber.email)
|
10
|
+
@email_subject = @email.render(:subject, @subscriber)
|
11
|
+
@text = @email.render(:body, @subscriber)
|
12
|
+
@base_url = "http://#{Spree::Config[:site_url]}"
|
13
|
+
render :layout => 'email', :text => simple_format(@text)
|
14
|
+
else
|
15
|
+
flash[:error] = t('unintened_email_view')
|
16
|
+
redirect_to new_subscriber_path
|
17
|
+
end
|
17
18
|
end
|
18
19
|
|
19
20
|
end
|
@@ -16,21 +16,22 @@ class SubscribersController < Spree::BaseController
|
|
16
16
|
def create
|
17
17
|
@subscriber = Subscriber.new(params[:subscriber])
|
18
18
|
if @subscriber.valid? && @subscriber.save
|
19
|
-
flash[:notice] =
|
19
|
+
flash[:notice] = t('subscribe_thanks')
|
20
20
|
redirect_to new_subscriber_path
|
21
21
|
else
|
22
|
-
flash[:error] =
|
22
|
+
flash[:error] = t('subscribe_failed')
|
23
23
|
render :action => 'new'
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
def unsubscribe
|
28
28
|
if @subscriber.email == params[:subscriber][:email] && @subscriber.unsubscribe!
|
29
|
-
flash[:notice] =
|
29
|
+
flash[:notice] = t('unsubscribe_success_public')
|
30
|
+
redirect_to new_subscriber_path
|
30
31
|
else
|
31
|
-
flash[:error] =
|
32
|
+
flash[:error] = t('unsubscribe_failed_public')
|
33
|
+
redirect_to subscriber_path(@subscriber)
|
32
34
|
end
|
33
|
-
redirect_to new_subscriber_path
|
34
35
|
end
|
35
36
|
|
36
37
|
private
|
data/app/model/email.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
class Email < ActiveRecord::Base
|
2
|
-
|
2
|
+
|
3
|
+
include SpreeMail::HasToken
|
4
|
+
|
3
5
|
validates :to, :presence => true
|
4
6
|
validates :subject, :presence => true
|
5
7
|
validates :body, :presence => true
|
6
8
|
|
7
|
-
before_create :set_token
|
8
|
-
|
9
9
|
def to=(value)
|
10
10
|
value = {} unless value.is_a? Hash
|
11
11
|
value.delete("0")
|
@@ -25,6 +25,10 @@ class Email < ActiveRecord::Base
|
|
25
25
|
def recipient_list
|
26
26
|
recipients.join(", ")
|
27
27
|
end
|
28
|
+
|
29
|
+
def render(attribute, subscriber)
|
30
|
+
Mustache.render(self.send(attribute), subscriber.attributes)
|
31
|
+
end
|
28
32
|
|
29
33
|
def deliver!
|
30
34
|
count = 0
|
@@ -37,20 +41,7 @@ class Email < ActiveRecord::Base
|
|
37
41
|
end
|
38
42
|
return 0 < count, count
|
39
43
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def render(attribute, subscriber)
|
44
|
-
Mustache.render(self.send(attribute), subscriber.attributes)
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def set_token
|
50
|
-
write_attribute :token, Digest::SHA1.hexdigest(Time.now.to_s)
|
51
|
-
end
|
52
|
-
|
53
|
-
|
44
|
+
|
54
45
|
class << self
|
55
46
|
|
56
47
|
def new(parameters={})
|
data/app/model/subscriber.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
class Subscriber < ActiveRecord::Base
|
2
2
|
|
3
|
-
|
3
|
+
include SpreeMail::HasToken
|
4
4
|
|
5
|
+
# ?? Do we need these scopes anywhere else
|
6
|
+
# -> DRY (Later task)
|
5
7
|
scope :active, where("unsubscribed_at IS NULL").order(:name)
|
6
8
|
scope :unsubscribed, where("unsubscribed_at IS NOT NULL").order(:name)
|
7
9
|
|
8
10
|
validates :name, :presence => true
|
9
11
|
validates :email, :email => true, :uniqueness => true
|
10
|
-
|
11
|
-
before_create :set_token
|
12
|
-
|
12
|
+
|
13
13
|
def active?
|
14
14
|
unsubscribed_at.to_s.empty?
|
15
15
|
end
|
@@ -29,11 +29,5 @@ class Subscriber < ActiveRecord::Base
|
|
29
29
|
def email=(value)
|
30
30
|
write_attribute :email, value.strip.downcase
|
31
31
|
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def set_token
|
36
|
-
write_attribute :token, Digest::SHA1.hexdigest(Time.now.to_s)
|
37
|
-
end
|
38
|
-
|
32
|
+
|
39
33
|
end
|
@@ -15,6 +15,6 @@ class EmailValidator < ActiveModel::EachValidator
|
|
15
15
|
rescue Exception => e
|
16
16
|
r = false
|
17
17
|
end
|
18
|
-
record.errors[attribute] << (options[:message] || I18n.t(
|
18
|
+
record.errors[attribute] << (options[:message] || I18n.t('invalid_email', :scope => [:activerecord, :errors, :messages])) unless r
|
19
19
|
end
|
20
20
|
end
|
@@ -1,13 +1,10 @@
|
|
1
1
|
<%- locals = {:f => f} %>
|
2
2
|
|
3
3
|
<% content_for :head do %>
|
4
|
-
<%= stylesheet_link_tag 'admin/spree_mail' %>
|
5
|
-
|
4
|
+
<%= stylesheet_link_tag 'admin/spree_mail' %>
|
6
5
|
<script type="text/javascript">
|
7
|
-
//<![CDATA[
|
8
|
-
|
6
|
+
//<![CDATA[
|
9
7
|
$(document).ready(function() {
|
10
|
-
|
11
8
|
$('div.selection a').click(function(evt) {
|
12
9
|
evt.preventDefault();
|
13
10
|
var a = $(this);
|
@@ -22,20 +19,15 @@
|
|
22
19
|
break;
|
23
20
|
}
|
24
21
|
});
|
25
|
-
|
26
22
|
$('div.selection li').click(function(evt) {
|
27
23
|
if (evt.target.type == 'checkbox') return true;
|
28
24
|
evt.preventDefault();
|
29
25
|
var cb = $(this).find('input[type=checkbox]');
|
30
26
|
cb.attr('checked', cb.is(':checked') ? false : true);
|
31
27
|
});
|
32
|
-
|
33
28
|
});
|
34
|
-
|
35
|
-
|
36
29
|
//]]>
|
37
|
-
</script>
|
38
|
-
|
30
|
+
</script>
|
39
31
|
<% end %>
|
40
32
|
|
41
33
|
<%= hook :admin_email_form_fields, locals do %>
|
@@ -44,9 +36,9 @@
|
|
44
36
|
|
45
37
|
<div class="selection left">
|
46
38
|
|
47
|
-
<h3><%= t(
|
48
|
-
<%= link_to t(
|
49
|
-
<%= link_to t(
|
39
|
+
<h3><%= t('select_subscribers') %>:</h3>
|
40
|
+
<%= link_to t('select_all'), "#select-all" %> /
|
41
|
+
<%= link_to t('deselect_all'), "#deselect-all" %>
|
50
42
|
<ul class="select">
|
51
43
|
<% @subscribers.each do |subscriber| %>
|
52
44
|
<li class="checkbox">
|
@@ -60,7 +52,7 @@
|
|
60
52
|
|
61
53
|
<div class="right">
|
62
54
|
|
63
|
-
<h3><%= t(
|
55
|
+
<h3><%= t('message_details')%></h3>
|
64
56
|
<%= f.field_container :subject do %>
|
65
57
|
<%= f.label :subject, t("subject") %><br />
|
66
58
|
<%= f.text_field :subject, :class => "title" %>
|
@@ -68,7 +60,7 @@
|
|
68
60
|
<% end %>
|
69
61
|
|
70
62
|
<%= f.field_container :body do %>
|
71
|
-
<%= f.label :body, t(
|
63
|
+
<%= f.label :body, t('message_body') %><br />
|
72
64
|
<%= f.text_area :body %>
|
73
65
|
<%= error_message_on :email, :body %>
|
74
66
|
<% end %>
|
@@ -3,22 +3,22 @@
|
|
3
3
|
<div class='toolbar'>
|
4
4
|
<ul class='actions'>
|
5
5
|
<li>
|
6
|
-
<p><%= button_link_to t(
|
6
|
+
<p><%= button_link_to t('new_email'), new_object_url, :icon => 'add' %></p>
|
7
7
|
</li>
|
8
8
|
</ul>
|
9
9
|
<br class='clear' />
|
10
10
|
</div>
|
11
11
|
|
12
12
|
|
13
|
-
<h1><%= t(
|
13
|
+
<h1><%= t('listing_emails') %></h1>
|
14
14
|
|
15
15
|
|
16
16
|
<table class="index">
|
17
17
|
<thead>
|
18
18
|
<tr>
|
19
19
|
<%= hook :admin_emails_index_headers do %>
|
20
|
-
<th><%=
|
21
|
-
<th><%=
|
20
|
+
<th><%= sort_link @search, :subject, t('subject') %></th>
|
21
|
+
<th><%= sort_link @search, :body, t('message_body') %></th>
|
22
22
|
<th><%= hook :admin_emails_index_header_actions %></th>
|
23
23
|
<% end %>
|
24
24
|
</tr>
|
@@ -44,21 +44,26 @@
|
|
44
44
|
|
45
45
|
<%= will_paginate(:previous_label => "« #{t('previous')}", :next_label => "#{t('next')} »") %>
|
46
46
|
|
47
|
-
|
48
47
|
<% content_for :sidebar do %>
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
48
|
+
<div class="box">
|
49
|
+
<h3><%= t('search') %></h3>
|
50
|
+
|
51
|
+
<% @email = Email.metasearch %>
|
52
|
+
<%= form_for [:admin, @email] do |f| %>
|
53
|
+
<%- locals = {:f => f} %>
|
54
|
+
<%= hook :admin_emails_index_search, locals do %>
|
55
|
+
<p>
|
56
|
+
<label><%= t 'to' %></label><br />
|
57
|
+
<%= f.text_field :to_like, :size => 25 %>
|
58
|
+
</p>
|
59
|
+
<p>
|
60
|
+
<label><%= t 'subject' %></label><br />
|
61
|
+
<%= f.text_field :subject_like, :size => 25 %>
|
62
|
+
</p>
|
62
63
|
<% end %>
|
63
|
-
|
64
|
-
|
64
|
+
<%= hook :admin_emails_index_search_buttons, locals do %>
|
65
|
+
<p><%= button t('search') %></p>
|
66
|
+
<% end %>
|
67
|
+
<% end %>
|
68
|
+
</div>
|
69
|
+
<% end %>
|
@@ -1,20 +1,20 @@
|
|
1
1
|
<%= render 'admin/shared/spree_mail_sub_nav' %>
|
2
2
|
|
3
|
-
<h1><%= t(
|
3
|
+
<h1><%= t('show_email') %></h1>
|
4
4
|
|
5
|
-
<h5><%= t(
|
5
|
+
<h5><%= t('to') %>: (<%= @email.recipients.length %>)</h5>
|
6
6
|
<p><%= @email.recipient_list %></p>
|
7
7
|
|
8
|
-
<h5><%= t(
|
8
|
+
<h5><%= t('subject') %>:</h5>
|
9
9
|
<p><%= @email.subject %></p>
|
10
10
|
|
11
|
-
<h5><%= t(
|
11
|
+
<h5><%= t('body') %>:</h5>
|
12
12
|
<%= simple_format @email.body %>
|
13
13
|
|
14
14
|
<hr/>
|
15
15
|
|
16
16
|
<p>
|
17
|
-
<%= link_to (image_tag("admin/icons/email.png") + " " + t(
|
17
|
+
<%= link_to (image_tag("admin/icons/email.png") + " " + t('send')), deliver_admin_email_path(@email) %>
|
18
18
|
<%= link_to_edit @email %> <%= t('or') %>
|
19
19
|
<%= link_to t('back'), collection_url %>
|
20
20
|
</p>
|
@@ -5,13 +5,13 @@
|
|
5
5
|
<%= render "shared/error_messages", :target => @subscriber %>
|
6
6
|
|
7
7
|
<%= f.field_container :name do %>
|
8
|
-
<%= f.label :name, t(
|
8
|
+
<%= f.label :name, t('name') %><br />
|
9
9
|
<%= f.text_field :name, :class => 'title' %>
|
10
10
|
<%= error_message_on :subscriber, :name %>
|
11
11
|
<% end %>
|
12
12
|
|
13
13
|
<%= f.field_container :email do %>
|
14
|
-
<%= f.label :email, t(
|
14
|
+
<%= f.label :email, t('email') %><br />
|
15
15
|
<%= f.text_field :email, :class => 'title' %>
|
16
16
|
<%= error_message_on :subscriber, :email %>
|
17
17
|
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if subscriber.active? %>
|
2
|
-
<%= link_to t(
|
2
|
+
<%= link_to t('unsubscribe'), unsubscribe_admin_subscriber_path(subscriber) %>
|
3
3
|
<% else %>
|
4
|
-
<%= link_to t(
|
4
|
+
<%= link_to t('resubscribe'), resubscribe_admin_subscriber_path(subscriber) %>
|
5
5
|
<% end %>
|
@@ -5,11 +5,11 @@
|
|
5
5
|
<li>
|
6
6
|
<p>
|
7
7
|
<% if controller.action_name == 'unsubscribed' %>
|
8
|
-
<%= button_link_to t(
|
8
|
+
<%= button_link_to t('view_all_subscribers'), admin_subscribers_path %>
|
9
9
|
<% else %>
|
10
|
-
<%= button_link_to t(
|
10
|
+
<%= button_link_to t('view_unsubscribed'), unsubscribed_admin_subscribers_path %>
|
11
11
|
<% end %>
|
12
|
-
<%= button_link_to t(
|
12
|
+
<%= button_link_to t('new_subscriber'), new_object_url, :icon => 'add' %>
|
13
13
|
</p>
|
14
14
|
</li>
|
15
15
|
</ul>
|
@@ -17,15 +17,15 @@
|
|
17
17
|
</div>
|
18
18
|
|
19
19
|
|
20
|
-
<h1><%= t(
|
20
|
+
<h1><%= t('listing_subscribers') %></h1>
|
21
21
|
|
22
22
|
|
23
23
|
<table class="index">
|
24
24
|
<thead>
|
25
25
|
<tr>
|
26
26
|
<%= hook :admin_subscribers_index_headers do %>
|
27
|
-
<th><%=
|
28
|
-
<th><%=
|
27
|
+
<th><%= sort_link @search, :name, t('name') %></th>
|
28
|
+
<th><%= sort_link @search, :email, t('email') %></th>
|
29
29
|
<th><%= hook :admin_subscribers_index_header_actions %></th>
|
30
30
|
<% end %>
|
31
31
|
</tr>
|
@@ -54,23 +54,25 @@
|
|
54
54
|
|
55
55
|
|
56
56
|
<% content_for :sidebar do %>
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
<
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
57
|
+
<div class="box">
|
58
|
+
<h3><%= t('search') %></h3>
|
59
|
+
|
60
|
+
<% @subscriber = Subscriber.metasearch %>
|
61
|
+
<%= form_for [:admin, @subscriber] do |f| %>
|
62
|
+
<%- locals = {:f => f} %>
|
63
|
+
<%= hook :admin_subscribers_index_search, locals do %>
|
64
|
+
<p>
|
65
|
+
<label><%= t 'name' %></label><br />
|
66
|
+
<%= f.text_field :name_like, :size => 25 %>
|
67
|
+
</p>
|
68
|
+
<p>
|
69
|
+
<label><%= t 'email' %></label><br />
|
70
|
+
<%= f.text_field :email_like, :size => 25 %>
|
71
|
+
</p>
|
72
|
+
<% end %>
|
73
|
+
<%= hook :admin_subscribers_index_search_buttons, locals do %>
|
74
|
+
<p><%= button t('search') %></p>
|
74
75
|
<% end %>
|
75
|
-
|
76
|
-
|
76
|
+
<% end %>
|
77
|
+
</div>
|
78
|
+
<% end %>
|
@@ -1 +1 @@
|
|
1
|
-
<%= link_to t(
|
1
|
+
<%= link_to t('sign_up_for_our_newsletter'), new_subscriber_path %>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
<td><%= link_to image_tag(@base_url + Spree::Config[:logo], :alt => Spree::Config[:site_name], :style => "border: 0"), root_url %></td>
|
24
24
|
<td align="right">
|
25
25
|
<p><%= l @email.created_at, :format => "%B %d, %Y" %></p>
|
26
|
-
<p><b><%= t(
|
26
|
+
<p><b><%= t('subject') %>:</b> <%= @email_subject %></p>
|
27
27
|
</td>
|
28
28
|
</tr>
|
29
29
|
<tr>
|
@@ -36,8 +36,8 @@
|
|
36
36
|
<tr>
|
37
37
|
<td>
|
38
38
|
<p style="font-size: 12px;"><%= t :received_in_error, :site_name => Spree::Config[:site_name] %></p>
|
39
|
-
<p style="font-size: 12px;"><%= t(
|
40
|
-
<p style="font-size: 12px;"><%= t(
|
39
|
+
<p style="font-size: 12px;"><%= t('contact') %>: <b><%= mail_to @email.from, @email.from, :style => "color: #5b8fb1;" %></b></p>
|
40
|
+
<p style="font-size: 12px;"><%= t('unsubscribe_text', :site_name => Spree::Config[:site_name]) %> <%= link_to t('click_here'), subscriber_url(@subscriber.token), :style => "color: #5b8fb1;" %></p>
|
41
41
|
<h4 style="padding: 10px 0; margin: 0; border-top: 1px solid #e0e0e0;">
|
42
42
|
<%= link_to Spree::Config[:site_name], root_url, :style => "color: #5b8fb1;" %>
|
43
43
|
</h4>
|
@@ -59,10 +59,10 @@
|
|
59
59
|
<td align="right">
|
60
60
|
<p style="font-size: 12px">
|
61
61
|
<% if @link_to_browser %>
|
62
|
-
<%= link_to t(
|
63
|
-
<%= t(
|
62
|
+
<%= link_to t('click_here'), @link_to_browser, :style => "color: #5b8fb1;" %>
|
63
|
+
<%= t('view_in_browser') %>
|
64
64
|
<% else %>
|
65
|
-
<%= t(
|
65
|
+
<%= t('visit_online') %>
|
66
66
|
<%= link_to Spree::Config[:site_url], root_url, :style => "color: #5b8fb1;" %>
|
67
67
|
<% end %>
|
68
68
|
</p>
|
@@ -71,7 +71,7 @@
|
|
71
71
|
<tr>
|
72
72
|
<td colspan="2" align="center">
|
73
73
|
<br/>
|
74
|
-
<p style="font-size: 11px; color: #999;"><%= t(
|
74
|
+
<p style="font-size: 11px; color: #999;"><%= t('message_sent_to_from_on',
|
75
75
|
:to => @subscriber.email,
|
76
76
|
:from => @email.from,
|
77
77
|
:on => l(@email.created_at, :format => "%b %d, %Y at %I:%M:%S %p")) %>.</p>
|
@@ -1,6 +1,6 @@
|
|
1
|
-
<h1><%= t(
|
1
|
+
<h1><%= t('unsubscribe_title') %></h1>
|
2
2
|
|
3
|
-
<p><%= t(
|
3
|
+
<p><%= t('unsubscribe_mail') %>:</p>
|
4
4
|
|
5
5
|
<% token = Digest::SHA1.hexdigest(Time.now.to_s) %>
|
6
6
|
<%= form_for @subscriber, :url => unsubscribe_subscriber_path(@subscriber.token) do |form| %>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<%= form.hidden_field :token, :value => token %>
|
11
11
|
</p>
|
12
12
|
<p>
|
13
|
-
<%= form.submit t(
|
14
|
-
<%= link_to t(
|
13
|
+
<%= form.submit t('unsubscribe') %> or
|
14
|
+
<%= link_to t('cancel'), root_path %>
|
15
15
|
</p>
|
16
16
|
<% end %>
|
data/config/locales/en.yml
CHANGED
@@ -24,7 +24,7 @@ en:
|
|
24
24
|
show_email: Show Email
|
25
25
|
new_email: New Email
|
26
26
|
editing_email: Editing Email
|
27
|
-
|
27
|
+
unintened_email_view: This email was not intended for you.
|
28
28
|
emails: Emails
|
29
29
|
|
30
30
|
to: To
|
@@ -32,35 +32,32 @@ en:
|
|
32
32
|
body: Body
|
33
33
|
subject: Subject
|
34
34
|
message_body: Message Body
|
35
|
+
contact: Contact
|
35
36
|
|
36
37
|
delivery_success: Your email was successfully sent!
|
37
38
|
delivery_failed: Sorry, your email could not be sent.
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
visit_online: "visit us online at"
|
40
|
+
unsubscribe_text: If you would like to Unsubscribe
|
41
|
+
click_here: Click here
|
42
|
+
view_in_browser: to view this email in your browser
|
43
|
+
visit_online: visit us online at
|
44
|
+
|
45
|
+
received_in_error: "This is a message from the %{site_name} if you believe you have received this in error please let us know."
|
46
46
|
message_sent_to_from_on: "This message was sent to %{to} from %{from} on %{on}."
|
47
47
|
|
48
|
+
unsubscribe_title: Unsubscribe from our Mailing List
|
49
|
+
unsubscribe_mail: Please enter your email address below
|
50
|
+
unsubscribe: Unsubscribe
|
48
51
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
select_subscribers: "Select subscribers"
|
54
|
-
select_all: "Select All"
|
55
|
-
deselect_all: "Deselect All"
|
56
|
-
message_details: "Message Details"
|
57
|
-
|
58
|
-
sign_up_for_our_newsletter: "Sign up for our newsletter"
|
59
|
-
|
60
|
-
newsletter_text_signup: "Lorem Ipsum dolor sit amet..."
|
52
|
+
select_subscribers: Select subscribers
|
53
|
+
select_all: Select All
|
54
|
+
deselect_all: Deselect All
|
55
|
+
message_details: Message Details
|
61
56
|
|
57
|
+
sign_up_for_our_newsletter: Sign up for our newsletter
|
58
|
+
newsletter_text_signup: Lorem Ipsum dolor sit amet...
|
62
59
|
|
63
60
|
activerecord:
|
64
61
|
errors:
|
65
62
|
messages:
|
66
|
-
invalid_email:
|
63
|
+
invalid_email: appears to be invalid
|
data/config/routes.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
|
3
|
-
get "/email/:
|
3
|
+
get "/email/:subscriber/:email", :to => "emails#show", :as => :read_email
|
4
4
|
|
5
5
|
resources :subscribers, :except => [:edit,:update] do
|
6
6
|
put :unsubscribe, :on => :member
|
data/lib/spree_mail.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
|
+
if ENV["RAILS_ENV"] == "test"
|
2
|
+
require 'spree_core'
|
3
|
+
require 'spree_auth'
|
4
|
+
require 'sqlite3'
|
5
|
+
end
|
6
|
+
|
1
7
|
require 'mail'
|
2
8
|
require 'mustache'
|
9
|
+
require 'meta_search'
|
3
10
|
require 'spree_mail/custom_hooks'
|
11
|
+
require 'spree_mail/has_token'
|
4
12
|
|
5
13
|
module SpreeMail
|
6
14
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SpreeMail
|
2
|
+
module HasToken
|
3
|
+
|
4
|
+
def self.included(model)
|
5
|
+
model.instance_eval do
|
6
|
+
attr_readonly :token
|
7
|
+
validates :token, :presence => true
|
8
|
+
before_validation :set_token, :on => :create
|
9
|
+
end
|
10
|
+
model.send(:include, InstanceMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
module InstanceMethods
|
14
|
+
|
15
|
+
def to_param
|
16
|
+
token
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def set_token
|
21
|
+
write_attribute :token, Digest::SHA1.hexdigest((Time.now.to_i * rand).to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/spree_mail/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_mail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 40
|
8
|
-
- 0
|
9
|
-
- 3
|
10
|
-
version: 0.40.0.3
|
4
|
+
prerelease:
|
5
|
+
version: 0.40.0.4
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Spencer Steffen
|
@@ -15,68 +10,86 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-
|
13
|
+
date: 2011-02-22 00:00:00 -08:00
|
19
14
|
default_executable:
|
20
15
|
dependencies:
|
21
16
|
- !ruby/object:Gem::Dependency
|
22
17
|
name: spree_core
|
23
|
-
prerelease: false
|
24
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
19
|
none: false
|
26
20
|
requirements:
|
27
21
|
- - ">="
|
28
22
|
- !ruby/object:Gem::Version
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
- 30
|
32
|
-
- 1
|
33
23
|
version: 0.30.1
|
34
24
|
type: :runtime
|
25
|
+
prerelease: false
|
35
26
|
version_requirements: *id001
|
36
27
|
- !ruby/object:Gem::Dependency
|
37
28
|
name: spree_auth
|
38
|
-
prerelease: false
|
39
29
|
requirement: &id002 !ruby/object:Gem::Requirement
|
40
30
|
none: false
|
41
31
|
requirements:
|
42
32
|
- - ">="
|
43
33
|
- !ruby/object:Gem::Version
|
44
|
-
segments:
|
45
|
-
- 0
|
46
|
-
- 30
|
47
|
-
- 1
|
48
34
|
version: 0.30.1
|
49
35
|
type: :runtime
|
36
|
+
prerelease: false
|
50
37
|
version_requirements: *id002
|
51
38
|
- !ruby/object:Gem::Dependency
|
52
39
|
name: mustache
|
53
|
-
prerelease: false
|
54
40
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
41
|
none: false
|
56
42
|
requirements:
|
57
43
|
- - ">="
|
58
44
|
- !ruby/object:Gem::Version
|
59
|
-
segments:
|
60
|
-
- 0
|
61
|
-
- 12
|
62
|
-
- 0
|
63
45
|
version: 0.12.0
|
64
46
|
type: :runtime
|
47
|
+
prerelease: false
|
65
48
|
version_requirements: *id003
|
66
49
|
- !ruby/object:Gem::Dependency
|
67
50
|
name: mail
|
68
|
-
prerelease: false
|
69
51
|
requirement: &id004 !ruby/object:Gem::Requirement
|
70
52
|
none: false
|
71
53
|
requirements:
|
72
54
|
- - ">="
|
73
55
|
- !ruby/object:Gem::Version
|
74
|
-
|
75
|
-
- 2
|
76
|
-
- 2
|
77
|
-
version: "2.2"
|
56
|
+
version: 2.2.0
|
78
57
|
type: :runtime
|
58
|
+
prerelease: false
|
79
59
|
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: meta_search
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.0.1
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: shoulda
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 2.11.3
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *id006
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: sqlite3-ruby
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: *id007
|
80
93
|
description: Spree Mail extends Spree by adding a mailing list subscriber model, sign up forms and an admin to send messages.
|
81
94
|
email:
|
82
95
|
- spencer@citrusme.com
|
@@ -91,6 +104,7 @@ files:
|
|
91
104
|
- config/locales/en.yml
|
92
105
|
- config/routes.rb
|
93
106
|
- lib/spree_mail/custom_hooks.rb
|
107
|
+
- lib/spree_mail/has_token.rb
|
94
108
|
- lib/spree_mail/version.rb
|
95
109
|
- lib/spree_mail.rb
|
96
110
|
- lib/tasks/install.rake
|
@@ -128,7 +142,7 @@ files:
|
|
128
142
|
- public/images/mailer/postmark.png
|
129
143
|
- public/stylesheets/admin/spree_mail.css
|
130
144
|
- Rakefile
|
131
|
-
has_rdoc:
|
145
|
+
has_rdoc: true
|
132
146
|
homepage: http://github.com/citrus/spree_mail
|
133
147
|
licenses: []
|
134
148
|
|
@@ -142,6 +156,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
156
|
requirements:
|
143
157
|
- - ">="
|
144
158
|
- !ruby/object:Gem::Version
|
159
|
+
hash: 104131697701234155
|
145
160
|
segments:
|
146
161
|
- 0
|
147
162
|
version: "0"
|
@@ -150,13 +165,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
165
|
requirements:
|
151
166
|
- - ">="
|
152
167
|
- !ruby/object:Gem::Version
|
168
|
+
hash: 104131697701234155
|
153
169
|
segments:
|
154
170
|
- 0
|
155
171
|
version: "0"
|
156
172
|
requirements: []
|
157
173
|
|
158
174
|
rubyforge_project:
|
159
|
-
rubygems_version: 1.
|
175
|
+
rubygems_version: 1.5.0
|
160
176
|
signing_key:
|
161
177
|
specification_version: 3
|
162
178
|
summary: Spree Mail adds mailing list signup and delivery features.
|