refinerycms-mailchimp 0.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/app/controllers/admin/campaigns_controller.rb +80 -0
- data/app/models/campaign.rb +105 -0
- data/app/views/admin/campaigns/_campaign.html.erb +22 -0
- data/app/views/admin/campaigns/_form.html.erb +85 -0
- data/app/views/admin/campaigns/_modal_fields.html.erb +4 -0
- data/app/views/admin/campaigns/_sortable_list.html.erb +4 -0
- data/app/views/admin/campaigns/edit.html.erb +1 -0
- data/app/views/admin/campaigns/index.html.erb +49 -0
- data/app/views/admin/campaigns/new.html.erb +1 -0
- data/app/views/admin/campaigns/send_options.html.erb +40 -0
- data/config/locales/en.yml +60 -0
- data/config/locales/nb.yml +19 -0
- data/config/locales/nl.yml +19 -0
- data/config/routes.rb +13 -0
- data/db/migrate/1_create_campaigns.rb +25 -0
- data/db/seeds/campaigns.rb +10 -0
- data/features/campaigns.feature_brainstorm +15 -0
- data/features/support/factories/campaigns.rb +8 -0
- data/features/support/paths.rb +24 -0
- data/lib/generators/refinerycms_mailchimp_generator.rb +8 -0
- data/lib/refinerycms-mailchimp.rb +39 -0
- data/lib/tasks/mailchimp.rake +13 -0
- data/spec/controllers/admin/campaigns_controller_spec.rb +19 -0
- data/spec/models/api_spec.rb +35 -0
- data/spec/models/campaign_spec.rb +43 -0
- metadata +105 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
class Admin::CampaignsController < Admin::BaseController
|
2
|
+
|
3
|
+
crudify :campaign, :order => "updated_at desc", :sortable => false, :title_attribute => :subject
|
4
|
+
|
5
|
+
rescue_from Refinery::Mailchimp::API::BadAPIKeyError, :with => :need_api_key
|
6
|
+
rescue_from Hominid::APIError, :with => :need_api_key
|
7
|
+
|
8
|
+
before_filter :get_mailchimp_assets, :except => :index
|
9
|
+
before_filter :find_campaign, :except => [:index, :new, :create]
|
10
|
+
|
11
|
+
def new
|
12
|
+
@campaign = Campaign.new :to_name => RefinerySetting.get_or_set(Refinery::Mailchimp::API::DefaultToNameSetting[:name], Refinery::Mailchimp::API::DefaultToNameSetting[:default]),
|
13
|
+
:from_name => RefinerySetting.get_or_set(Refinery::Mailchimp::API::DefaultFromNameSetting[:name], Refinery::Mailchimp::API::DefaultFromNameSetting[:default]),
|
14
|
+
:from_email => RefinerySetting.get_or_set(Refinery::Mailchimp::API::DefaultFromEmailSetting[:name], Refinery::Mailchimp::API::DefaultFromEmailSetting[:default])
|
15
|
+
end
|
16
|
+
|
17
|
+
def send_options
|
18
|
+
end
|
19
|
+
|
20
|
+
def send_test
|
21
|
+
if @campaign.send_test_to params[:email]
|
22
|
+
flash[:notice] = t('admin.campaigns.campaign.send_test_success', :email => params[:email])
|
23
|
+
else
|
24
|
+
flash[:alert] = t('admin.campaigns.campaign.send_test_failure', :email => params[:email])
|
25
|
+
end
|
26
|
+
sending_redirect_to admin_campaigns_path
|
27
|
+
end
|
28
|
+
|
29
|
+
def send_now
|
30
|
+
if @campaign.send_now
|
31
|
+
flash[:notice] = t('admin.campaigns.campaign.send_now_success')
|
32
|
+
else
|
33
|
+
flash[:alert] = t('admin.campaigns.campaign.send_now_failure')
|
34
|
+
end
|
35
|
+
sending_redirect_to admin_campaigns_path
|
36
|
+
end
|
37
|
+
|
38
|
+
def schedule
|
39
|
+
if @campaign.schedule_for DateTime.new(*params['date'].values_at('year','month','day','hour','minute').map{|x|x.to_i})
|
40
|
+
flash[:notice] = t('admin.campaigns.campaign.schedule_success')
|
41
|
+
else
|
42
|
+
flash[:alert] = t('admin.campaigns.campaign.schedule_failure')
|
43
|
+
end
|
44
|
+
sending_redirect_to admin_campaigns_path
|
45
|
+
end
|
46
|
+
|
47
|
+
def unschedule
|
48
|
+
if @campaign.unschedule
|
49
|
+
flash[:notice] = t('admin.campaigns.campaign.unschedule_success')
|
50
|
+
else
|
51
|
+
flash[:alert] = t('admin.campaigns.campaign.unschedule_failure')
|
52
|
+
end
|
53
|
+
sending_redirect_to admin_campaigns_path
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
def sending_redirect_to(path)
|
58
|
+
if from_dialog?
|
59
|
+
render :text => "<script>parent.window.location = '#{path}';</script>"
|
60
|
+
else
|
61
|
+
redirect_to path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def need_api_key
|
66
|
+
msg = t('admin.campaigns.index.set_api_key')
|
67
|
+
msg += " <a href=\"#{edit_admin_refinery_setting_path(RefinerySetting.find_by_name(Refinery::Mailchimp::API::KeySetting[:name]))}\" style=\"display:inline\">#{t('admin.campaigns.index.set_api_link')}</a>"
|
68
|
+
flash[:alert] = msg.html_safe
|
69
|
+
redirect_to admin_campaigns_path
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_mailchimp_assets
|
73
|
+
@lists = client.lists['data']
|
74
|
+
@templates = client.templates['user']
|
75
|
+
end
|
76
|
+
|
77
|
+
def client
|
78
|
+
@client ||= Refinery::Mailchimp::API.new
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
class Campaign < ActiveRecord::Base
|
2
|
+
|
3
|
+
acts_as_indexed :fields => [:subject, :body]
|
4
|
+
|
5
|
+
validates_presence_of :subject, :body, :mailchimp_list_id, :from_email, :from_name, :to_name
|
6
|
+
|
7
|
+
before_save :update_mailchimp_campaign
|
8
|
+
before_create :create_mailchimp_campaign
|
9
|
+
before_destroy :delete_mailchimp_campaign
|
10
|
+
|
11
|
+
def sent?
|
12
|
+
!!sent_at || !!scheduled_at && scheduled_at <= Time.now
|
13
|
+
end
|
14
|
+
|
15
|
+
def scheduled?
|
16
|
+
!!scheduled_at && scheduled_at > Time.now
|
17
|
+
end
|
18
|
+
|
19
|
+
def sent
|
20
|
+
sent_at || scheduled_at
|
21
|
+
end
|
22
|
+
|
23
|
+
def send_test_to(*emails)
|
24
|
+
Refinery::Mailchimp::API.new.campaign_send_test mailchimp_campaign_id, emails
|
25
|
+
rescue Hominid::APIError
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def send_now
|
30
|
+
success = Refinery::Mailchimp::API.new.campaign_send_now mailchimp_campaign_id
|
31
|
+
self.update_attribute :sent_at, Time.now if success
|
32
|
+
success
|
33
|
+
rescue Hominid::APIError
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
def schedule_for(datetime)
|
38
|
+
success = Refinery::Mailchimp::API.new.campaign_schedule mailchimp_campaign_id, datetime.utc.strftime("%Y-%m-%d %H:%M:%S")
|
39
|
+
self.update_attribute :scheduled_at, datetime if success
|
40
|
+
success
|
41
|
+
rescue Hominid::APIError
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def unschedule
|
46
|
+
success = Refinery::Mailchimp::API.new.campaign_unschedule mailchimp_campaign_id
|
47
|
+
self.update_attribute :scheduled_at, nil if success
|
48
|
+
success
|
49
|
+
rescue Hominid::APIError
|
50
|
+
false
|
51
|
+
end
|
52
|
+
|
53
|
+
def google_analytics
|
54
|
+
RefinerySetting.find_or_set Refinery::Mailchimp::API::GoogleAnalyticsSetting[:name], Refinery::Mailchimp::API::GoogleAnalyticsSetting[:default]
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def create_mailchimp_campaign
|
60
|
+
options = { :subject => subject, :from_email => from_email, :from_name => from_name, :to_name => to_name, :list_id => mailchimp_list_id, :auto_tweet => auto_tweet }
|
61
|
+
options[:template_id] = mailchimp_template_id unless mailchimp_template_id.blank?
|
62
|
+
# options[:analytics] = { :google => google_analytics } unless google_analytics.blank?
|
63
|
+
|
64
|
+
self.mailchimp_campaign_id = begin
|
65
|
+
Refinery::Mailchimp::API.new.campaign_create 'regular', options, { content_key => body }
|
66
|
+
rescue Hominid::APIError
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
return halt_with_mailchimp_error if self.mailchimp_campaign_id.blank?
|
71
|
+
end
|
72
|
+
|
73
|
+
def update_mailchimp_campaign
|
74
|
+
return if new_record?
|
75
|
+
|
76
|
+
client = Refinery::Mailchimp::API.new
|
77
|
+
|
78
|
+
options = {:title => :subject, :from_email => :from_email, :from_name => :from_name, :to_name => :to_name, :list_id => :mailchimp_list_id, :template_id => :mailchimp_template_id, :content => :body, :auto_tweet => :auto_tweet }
|
79
|
+
options.each_pair do |option_name, attribute|
|
80
|
+
if changed.include?(attribute.to_s)
|
81
|
+
success = client.campaign_update mailchimp_campaign_id, option_name, (option_name == :content ? { content_key => body } : self.send(attribute))
|
82
|
+
return halt_with_mailchimp_error unless success
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def delete_mailchimp_campaign
|
88
|
+
success = begin
|
89
|
+
Refinery::Mailchimp::API.new.campaign_delete mailchimp_campaign_id
|
90
|
+
rescue Hominid::APIError
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
return halt_with_mailchimp_error unless success
|
95
|
+
end
|
96
|
+
|
97
|
+
def halt_with_mailchimp_error
|
98
|
+
self.errors.add :base, I18n.t('admin.campaigns.campaign.mailchimp_error')
|
99
|
+
return false
|
100
|
+
end
|
101
|
+
|
102
|
+
def content_key
|
103
|
+
mailchimp_template_id.blank? ? :html : :html_MAIN
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<li class='clearfix record <%= cycle("on", "on-hover") %>' id="<%= dom_id(campaign) -%>">
|
2
|
+
<span class='subject'>
|
3
|
+
<%= campaign.subject %>
|
4
|
+
|
5
|
+
<% if campaign.sent? %>
|
6
|
+
<span class="preview" title="<%= campaign.sent %>">sent <%= distance_of_time_in_words_to_now(campaign.sent) %> ago</span>
|
7
|
+
<% elsif campaign.scheduled? %>
|
8
|
+
<span class="preview" title="<%= campaign.scheduled_at %>">sending in <%= distance_of_time_in_words_to_now(campaign.scheduled_at) %></span>
|
9
|
+
<% end %>
|
10
|
+
</span>
|
11
|
+
<span class='actions'>
|
12
|
+
<%= link_to refinery_icon_tag("application_edit.png"), edit_admin_campaign_path(campaign),
|
13
|
+
:subject => t('.edit') %>
|
14
|
+
<%= link_to refinery_icon_tag("email_go.png"), send_options_admin_campaign_path(campaign, :dialog => true, :width => 725, :height => 525),
|
15
|
+
:title => t('send_dialog', :scope => 'admin.campaigns.campaign') %>
|
16
|
+
<%= link_to refinery_icon_tag("delete.png"), admin_campaign_path(campaign),
|
17
|
+
:class => "cancel confirm-delete",
|
18
|
+
:subject => t('.delete'),
|
19
|
+
:'data-confirm' => t('admin.campaigns.campaign.delete_confirmation', :subject => campaign.subject),
|
20
|
+
:'data-method' => :delete %>
|
21
|
+
</span>
|
22
|
+
</li>
|
@@ -0,0 +1,85 @@
|
|
1
|
+
<% form_for [:admin, @campaign] do |f| -%>
|
2
|
+
<%= render :partial => "/shared/admin/error_messages", :locals => {
|
3
|
+
:object => @campaign,
|
4
|
+
:include_object_name => true
|
5
|
+
} %>
|
6
|
+
|
7
|
+
<div class='field'>
|
8
|
+
<span class='label_with_help'>
|
9
|
+
<%= f.label :subject -%>
|
10
|
+
<%= refinery_help_tag t('.subject_help') %>
|
11
|
+
</span>
|
12
|
+
<%= f.text_field :subject, :class => 'larger widest' -%>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class='field'>
|
16
|
+
<%= f.label :body -%>
|
17
|
+
<%= f.text_area :body, :rows => 20, :class => 'wymeditor widest' -%>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div class="hemisquare">
|
21
|
+
<h2><%= t('.to_and_from') %></h2>
|
22
|
+
|
23
|
+
<div class='field'>
|
24
|
+
<span class='label_with_help'>
|
25
|
+
<%= f.label :to_name, t('.to_name') -%>
|
26
|
+
<%= refinery_help_tag t('.to_name_help') %>
|
27
|
+
</span>
|
28
|
+
<%= f.text_field :to_name %>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<div class='field'>
|
32
|
+
<span class='label_with_help'>
|
33
|
+
<%= f.label :from_name, t('.from_name') -%>
|
34
|
+
<%= refinery_help_tag t('.from_name_help') %>
|
35
|
+
</span>
|
36
|
+
<%= f.text_field :from_name %>
|
37
|
+
</div>
|
38
|
+
|
39
|
+
<div class='field'>
|
40
|
+
<span class='label_with_help'>
|
41
|
+
<%= f.label :from_email, t('.from_email') -%>
|
42
|
+
<%= refinery_help_tag t('.from_email_help') %>
|
43
|
+
</span>
|
44
|
+
<%= f.text_field :from_email %>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
|
48
|
+
<div class="hemisquare right_side">
|
49
|
+
<h2><%= t('.settings') %></h2>
|
50
|
+
|
51
|
+
<div class='field'>
|
52
|
+
<span class='label_with_help'>
|
53
|
+
<%= f.label :mailchimp_list_id, t('.mailchimp_list_id') -%>
|
54
|
+
<%= refinery_help_tag t('.mailchimp_list_id_help') %>
|
55
|
+
</span>
|
56
|
+
<%= f.select :mailchimp_list_id, @lists.collect{ |list| [list['name'], list['id']] } %>
|
57
|
+
</div>
|
58
|
+
|
59
|
+
<div class='field'>
|
60
|
+
<span class='label_with_help'>
|
61
|
+
<%= f.label :mailchimp_template_id, t('.mailchimp_template_id') -%>
|
62
|
+
<%= refinery_help_tag t('.mailchimp_template_id_help') %>
|
63
|
+
</span>
|
64
|
+
<%= f.select :mailchimp_template_id, @templates.collect{ |template| [template['name'], template['id']] }, :include_blank => true %>
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<div class='field'>
|
68
|
+
<span class='label_with_help'>
|
69
|
+
<%= f.label :auto_tweet, t('.auto_tweet') -%>
|
70
|
+
<%= refinery_help_tag t('.auto_tweet_help') %>
|
71
|
+
</span>
|
72
|
+
<%= f.check_box :auto_tweet %>
|
73
|
+
</div>
|
74
|
+
</div>
|
75
|
+
|
76
|
+
<div class="clearfix"></div>
|
77
|
+
|
78
|
+
<%= render :partial => "/shared/admin/form_actions",
|
79
|
+
:locals => {
|
80
|
+
:f => f,
|
81
|
+
:continue_editing => false,
|
82
|
+
:delete_subject => t('admin.campaigns.campaign.delete'),
|
83
|
+
:delete_confirmation => t('admin.campaigns.campaign.delete_confirmation', :subject => @campaign.subject)
|
84
|
+
} %>
|
85
|
+
<% end -%>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render :partial => "form" %>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<div id='actions'>
|
2
|
+
<ul>
|
3
|
+
<% if Admin::CampaignsController.searchable? %>
|
4
|
+
<li>
|
5
|
+
<%= render :partial => "/shared/admin/search",
|
6
|
+
:locals => {
|
7
|
+
:url => admin_campaigns_url
|
8
|
+
} %>
|
9
|
+
</li>
|
10
|
+
<% end %>
|
11
|
+
<li>
|
12
|
+
<%= link_to t('.create_new'), new_admin_campaign_url,
|
13
|
+
:class => "add_icon" %>
|
14
|
+
</li>
|
15
|
+
</ul>
|
16
|
+
</div>
|
17
|
+
<div id='records'>
|
18
|
+
<% if searching? %>
|
19
|
+
<h2><%= t('shared.admin.search.results_for', :query => params[:search]) %></h2>
|
20
|
+
<% if @campaigns.any? %>
|
21
|
+
<%= will_paginate @campaigns, :previous_label => '«', :next_label => '»' %>
|
22
|
+
<ul>
|
23
|
+
<%= render :partial => "campaign",
|
24
|
+
:collection => @campaigns %>
|
25
|
+
</ul>
|
26
|
+
<%= will_paginate @campaigns, :previous_label => '«', :next_label => '»' %>
|
27
|
+
<% else %>
|
28
|
+
<p><%= t('shared.admin.search.no_results') %></p>
|
29
|
+
<% end %>
|
30
|
+
<% else %>
|
31
|
+
<% if @campaigns.any? %>
|
32
|
+
<%= will_paginate @campaigns,
|
33
|
+
:previous_label => '«',
|
34
|
+
:next_label => '»' %>
|
35
|
+
|
36
|
+
<%= render :partial => "sortable_list" %>
|
37
|
+
|
38
|
+
<%= will_paginate @campaigns,
|
39
|
+
:previous_label => '«',
|
40
|
+
:next_label => '»' %>
|
41
|
+
<% else %>
|
42
|
+
<p>
|
43
|
+
<strong>
|
44
|
+
<%= t('.no_items_yet') %>
|
45
|
+
</strong>
|
46
|
+
</p>
|
47
|
+
<% end %>
|
48
|
+
<% end %>
|
49
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render :partial => "form" %>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<% if @campaign.sent? %>
|
2
|
+
<h2>Sent</h2>
|
3
|
+
<p>
|
4
|
+
This campaign was sent <strong title="<%= @campaign.sent_at %>"><%= distance_of_time_in_words_to_now(@campaign.sent_at) %> ago</strong>.
|
5
|
+
</p>
|
6
|
+
<% elsif @campaign.scheduled? %>
|
7
|
+
<h2>Scheduled</h2>
|
8
|
+
<p>
|
9
|
+
This campaign is scheduled to be sent in <strong title="<%= @campaign.scheduled_at %>"><%= distance_of_time_in_words_to_now(@campaign.scheduled_at) %></strong>.
|
10
|
+
</p>
|
11
|
+
<%= form_tag unschedule_admin_campaign_path(@campaign) do -%>
|
12
|
+
<%= render :partial => "modal_fields" %>
|
13
|
+
<%= submit_tag "Unschedule Campaign"%>
|
14
|
+
<% end %>
|
15
|
+
<% else %>
|
16
|
+
<h2>Send Test Email</h2>
|
17
|
+
<p>This will send a test email to the email address you enter below.</p>
|
18
|
+
<%= form_tag send_test_admin_campaign_path(@campaign) do -%>
|
19
|
+
<%= render :partial => "modal_fields" %>
|
20
|
+
<%= label_tag :email %>
|
21
|
+
<%= text_field_tag :email, current_user.email %>
|
22
|
+
<%= submit_tag "Send Test" %>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<h2>Send Campaign Now</h2>
|
26
|
+
<p>This will send the campaign.</p>
|
27
|
+
<%= form_tag send_now_admin_campaign_path(@campaign) do -%>
|
28
|
+
<%= render :partial => "modal_fields" %>
|
29
|
+
<%= submit_tag "Send Now"%>
|
30
|
+
<% end %>
|
31
|
+
|
32
|
+
<h2>Schedule Campaign for Later</h2>
|
33
|
+
<p>This will schedule the campaign to be sent automatically at a future date.</p>
|
34
|
+
<%= form_tag schedule_admin_campaign_path(@campaign) do -%>
|
35
|
+
<%= render :partial => "modal_fields" %>
|
36
|
+
<%= label_tag :send_at %>
|
37
|
+
<%= select_datetime %>
|
38
|
+
<%= submit_tag "Schedule Campaign"%>
|
39
|
+
<% end %>
|
40
|
+
<% end %>
|
@@ -0,0 +1,60 @@
|
|
1
|
+
en:
|
2
|
+
shared:
|
3
|
+
admin:
|
4
|
+
image_picker:
|
5
|
+
image: image
|
6
|
+
plugins:
|
7
|
+
campaigns:
|
8
|
+
title: Campaigns
|
9
|
+
admin:
|
10
|
+
refinery_settings:
|
11
|
+
form:
|
12
|
+
help:
|
13
|
+
mailchimp_api_key: "Get your API key from your Mailchimp dashboard by choosing 'Account' and then 'API Keys & Info.'"
|
14
|
+
mailchimp_default_to_name: "The default To: name recipients will see (not email address). This can be changed for each campaign."
|
15
|
+
mailchimp_default_from_name: "The default From: name for your campaign message (not an email address). This can be changed for each campaign."
|
16
|
+
mailchimp_default_from_email: "The default From: email address for your campaign message. This can be changed for each campaign."
|
17
|
+
mailchimp_admin_base_url: The base URL of your Mailchimp admin area. This is used to generate links to your campaigns for convenience. Only change it if you know what you're doing.
|
18
|
+
campaigns:
|
19
|
+
index:
|
20
|
+
create_new: Create a new Campaign
|
21
|
+
reorder: Reorder Campaigns
|
22
|
+
reorder_done: Done Reordering Campaigns
|
23
|
+
sorry_no_results: Sorry! There are no results found.
|
24
|
+
no_items_yet: There are no Campaigns yet. Click "Create a new Campaign" to add your first campaign.
|
25
|
+
set_api_key: You must set a valid Mailchimp API key.
|
26
|
+
set_api_link: Click here to update your key.
|
27
|
+
campaign:
|
28
|
+
view_live: View this campaign live <br/><em>(opens in a new window)</em>
|
29
|
+
edit: Edit this campaign
|
30
|
+
delete: Remove this campaign forever
|
31
|
+
delete_confirmation: "Are you sure you want to remove '%{subject}'?"
|
32
|
+
mailchimp_error: "Could not save to Mailchimp! Please make sure your API key is right and that you are using a good 'From' email address."
|
33
|
+
send_dialog: "Send, schedule, or test this campaign"
|
34
|
+
send_test_success: Test email successfully sent to %{email}.
|
35
|
+
send_test_failure: Test email could not be sent to %{email}. Please check the email address.
|
36
|
+
send_now_success: The campaign was successfully sent!
|
37
|
+
send_now_failure: The campaign could not be sent. Please check in Mailchimp to make sure everything is ok.
|
38
|
+
schedule_success: The campaign was successfully scheduled.
|
39
|
+
schedule_failure: The campaign could not be scheduled. Please check in Mailchimp to make sure everything is ok.
|
40
|
+
unschedule_success: The campaign was successfully unscheduled.
|
41
|
+
unschedule_failure: The campaign could not be unscheduled. Please check in Mailchimp to make sure everything is ok.
|
42
|
+
form:
|
43
|
+
to_and_from: To and From
|
44
|
+
settings: Settings
|
45
|
+
subject_help: The subject line that will be used for the campaign emails.
|
46
|
+
mailchimp_list_id: Mailing List
|
47
|
+
mailchimp_list_id_help: The mailing list to send this campaign to. These are managed in Mailchimp.
|
48
|
+
mailchimp_template_id: Template
|
49
|
+
mailchimp_template_id_help: The HTML template to use for this campaign. These are managed in Mailchimp.
|
50
|
+
to_name: To Name
|
51
|
+
to_name_help: "The To: name recipients will see (not email address). You can change the default in Settings."
|
52
|
+
from_name: From Name
|
53
|
+
from_name_help: "The From: name for your campaign message (not an email address). You can change the default in Settings."
|
54
|
+
from_email: From Email
|
55
|
+
from_email_help: "The From: email address for your campaign message. You can change the default in Settings."
|
56
|
+
auto_tweet: Auto Tweet
|
57
|
+
auto_tweet_help: Automatically tweet about this campaign when sent. Requires setting up Twitter from Mailchimp.
|
58
|
+
campaigns:
|
59
|
+
show:
|
60
|
+
other: Other Campaigns
|
@@ -0,0 +1,19 @@
|
|
1
|
+
nb:
|
2
|
+
plugins:
|
3
|
+
refinerycms_mailchimp:
|
4
|
+
title: Campaigns
|
5
|
+
admin:
|
6
|
+
campaigns:
|
7
|
+
index:
|
8
|
+
create_new: Lag en ny Campaign
|
9
|
+
reorder: Endre rekkefølgen på Campaigns
|
10
|
+
reorder_done: Ferdig å endre rekkefølgen Campaigns
|
11
|
+
sorry_no_results: Beklager! Vi fant ikke noen resultater.
|
12
|
+
no_items_yet: Det er ingen Campaigns enda. Klikk på "Lag en ny Campaign" for å legge til din første campaign.
|
13
|
+
campaign:
|
14
|
+
view_live: Vis hvordan denne campaign ser ut offentlig <br/><em>(åpner i et nytt vindu)</em>
|
15
|
+
edit: Rediger denne campaign
|
16
|
+
delete: Fjern denne campaign permanent
|
17
|
+
campaigns:
|
18
|
+
show:
|
19
|
+
other: Andre Campaigns
|
@@ -0,0 +1,19 @@
|
|
1
|
+
nl:
|
2
|
+
plugins:
|
3
|
+
refinerycms_mailchimp:
|
4
|
+
title: Campaigns
|
5
|
+
admin:
|
6
|
+
campaigns:
|
7
|
+
index:
|
8
|
+
create_new: Maak een nieuwe Campaign
|
9
|
+
reorder: Wijzig de volgorde van de Campaigns
|
10
|
+
reorder_done: Klaar met het wijzingen van de volgorde van de Campaigns
|
11
|
+
sorry_no_results: Helaas! Er zijn geen resultaten gevonden.
|
12
|
+
no_items_yet: Er zijn nog geen Campaigns. Druk op 'Maak een nieuwe Campaign' om de eerste aan te maken.
|
13
|
+
campaign:
|
14
|
+
view_live: Bekijk deze campaign op de website <br/><em>(opent een nieuw venster)</em>
|
15
|
+
edit: Bewerk deze campaign
|
16
|
+
delete: Verwijder deze campaign voor eeuwig
|
17
|
+
campaigns:
|
18
|
+
show:
|
19
|
+
other: Andere Campaigns
|
data/config/routes.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Refinery::Application.routes.draw do
|
2
|
+
scope(:path => 'refinery', :as => 'admin', :module => 'admin') do
|
3
|
+
resources :campaigns do
|
4
|
+
member do
|
5
|
+
get :send_options
|
6
|
+
post :send_test
|
7
|
+
post :send_now
|
8
|
+
post :schedule
|
9
|
+
post :unschedule
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class CreateCampaigns < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
create_table :campaigns do |t|
|
5
|
+
t.string :subject, :mailchimp_campaign_id, :mailchimp_list_id, :mailchimp_template_id, :from_email, :from_name, :to_name
|
6
|
+
t.text :body
|
7
|
+
t.datetime :sent_at, :scheduled_at
|
8
|
+
t.boolean :auto_tweet, :default => false
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
|
12
|
+
add_index :campaigns, :id
|
13
|
+
|
14
|
+
load(Rails.root.join('db', 'seeds', 'campaigns.rb'))
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.down
|
18
|
+
UserPlugin.destroy_all({:name => "Campaigns"})
|
19
|
+
|
20
|
+
Page.delete_all({:link_url => "/campaigns"})
|
21
|
+
|
22
|
+
drop_table :campaigns
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
User.find(:all).each do |user|
|
2
|
+
user.plugins.create(:name => "campaigns",
|
3
|
+
:position => (user.plugins.maximum(:position) || -1) +1)
|
4
|
+
end
|
5
|
+
|
6
|
+
RefinerySetting.create :name => Refinery::Mailchimp::API::KeySetting[:name], :value => Refinery::Mailchimp::API::KeySetting[:default], :restricted => true
|
7
|
+
RefinerySetting.create :name => Refinery::Mailchimp::API::DefaultFromNameSetting[:name], :value => Refinery::Mailchimp::API::DefaultFromNameSetting[:default], :restricted => true
|
8
|
+
RefinerySetting.create :name => Refinery::Mailchimp::API::DefaultFromEmailSetting[:name], :value => Refinery::Mailchimp::API::DefaultFromEmailSetting[:default], :restricted => true
|
9
|
+
RefinerySetting.create :name => Refinery::Mailchimp::API::DefaultToNameSetting[:name], :value => Refinery::Mailchimp::API::DefaultToNameSetting[:default], :restricted => true
|
10
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
@campaign
|
2
|
+
Feature: Campaigns
|
3
|
+
Campaigns can be created through the given user model
|
4
|
+
current_user is assumed through admin screens
|
5
|
+
|
6
|
+
Scenario: Saving a campaign is successful
|
7
|
+
Given I am a logged in refinery user
|
8
|
+
|
9
|
+
When I am on the new campaign form
|
10
|
+
And I fill in "Subject" with "This is my campaign"
|
11
|
+
And I fill in "Body" with "And I love it"
|
12
|
+
And I press "Save"
|
13
|
+
|
14
|
+
Then there should be 1 campaign
|
15
|
+
And the campaign should belong to me
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module NavigationHelpers
|
2
|
+
module Refinery
|
3
|
+
module Mailchimp
|
4
|
+
def path_to(page_name)
|
5
|
+
case page_name
|
6
|
+
when /the list of campaigns/
|
7
|
+
admin_campaigns_path
|
8
|
+
when /the new campaigns? form/
|
9
|
+
new_admin_campaign_path
|
10
|
+
else
|
11
|
+
begin
|
12
|
+
if page_name =~ /the campaign subjectd "?([^\"]*)"?/ and (page = Campaign.find_by_subject($1)).present?
|
13
|
+
self.url_for(page.url)
|
14
|
+
else
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
rescue
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'refinery'
|
2
|
+
require 'hominid'
|
3
|
+
|
4
|
+
module Refinery
|
5
|
+
module Mailchimp
|
6
|
+
class Engine < Rails::Engine
|
7
|
+
initializer "static assets" do |app|
|
8
|
+
app.middleware.insert_after ::ActionDispatch::Static, ::ActionDispatch::Static, "#{root}/public"
|
9
|
+
end
|
10
|
+
|
11
|
+
config.after_initialize do
|
12
|
+
Refinery::Plugin.register do |plugin|
|
13
|
+
plugin.name = "campaigns"
|
14
|
+
plugin.activity = {:class => Campaign,}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class API < Hominid::API
|
20
|
+
KeySetting = { :name => "mailchimp_api_key", :default => "Set me!" }
|
21
|
+
DefaultFromNameSetting = { :name => "mailchimp_default_from_name", :default => "" }
|
22
|
+
DefaultFromEmailSetting = { :name => "mailchimp_default_from_email", :default => "" }
|
23
|
+
DefaultToNameSetting = { :name => "mailchimp_default_to_name", :default => "" }
|
24
|
+
|
25
|
+
class BadAPIKeyError < StandardError; end
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
api_key = RefinerySetting.get_or_set KeySetting[:name], KeySetting[:default]
|
29
|
+
raise BadAPIKeyError if api_key.blank? || api_key == KeySetting[:default]
|
30
|
+
|
31
|
+
begin
|
32
|
+
super api_key
|
33
|
+
rescue ArgumentError
|
34
|
+
raise BadAPIKeyError
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
Dir[File.expand_path('../../../../features/support/factories/*.rb', __FILE__)].each{|factory| require factory}
|
3
|
+
|
4
|
+
describe Admin::CampaignsController do
|
5
|
+
describe "getting lists and templates" do
|
6
|
+
it "should get lists and templates on new"
|
7
|
+
it "should get lists and templates on create"
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "creating a campaign" do
|
11
|
+
it "should redirect to index with flash message if API is not set up"
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "sending the campaign" do
|
15
|
+
it "should send a test email"
|
16
|
+
it "should send the campaign now"
|
17
|
+
it "should schedule the campaign to send in the future"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hominid'
|
3
|
+
|
4
|
+
Dir[File.expand_path('../../../features/support/factories/*.rb', __FILE__)].each{|factory| require factory}
|
5
|
+
|
6
|
+
describe Refinery::Mailchimp::API do
|
7
|
+
describe "the client" do
|
8
|
+
before do
|
9
|
+
RefinerySetting.find_by_name(Refinery::Mailchimp::API::KeySetting[:name]).try :destroy
|
10
|
+
RefinerySetting.rewrite_cache
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should give a properly setup client if the API key is set" do
|
14
|
+
RefinerySetting.set Refinery::Mailchimp::API::KeySetting[:name], 'abcdefg-us1'
|
15
|
+
Refinery::Mailchimp::API.new
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise an error if the API key is not set" do
|
19
|
+
begin
|
20
|
+
client = Refinery::Mailchimp::API.new
|
21
|
+
fail
|
22
|
+
rescue Refinery::Mailchimp::API::BadAPIKeyError
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise an error if the API key is malformed" do
|
27
|
+
begin
|
28
|
+
RefinerySetting.set Refinery::Mailchimp::API::KeySetting[:name], 'abcdefg'
|
29
|
+
client = Refinery::Mailchimp::API.new
|
30
|
+
fail
|
31
|
+
rescue Refinery::Mailchimp::API::BadAPIKeyError
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
Dir[File.expand_path('../../../features/support/factories/*.rb', __FILE__)].each{|factory| require factory}
|
3
|
+
|
4
|
+
describe Campaign do
|
5
|
+
describe "validations" do
|
6
|
+
it "should be valid with valid attributes" do
|
7
|
+
Factory.build(:campaign).should be_valid
|
8
|
+
end
|
9
|
+
|
10
|
+
it "requires subject" do
|
11
|
+
Factory.build(:campaign, :subject => "").should_not be_valid
|
12
|
+
end
|
13
|
+
|
14
|
+
it "requires a body" do
|
15
|
+
Factory.build(:campaign, :body => "").should_not be_valid
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "integrating with Mailchimp" do
|
20
|
+
it "should save to mailchimp before create" do
|
21
|
+
campaign = Factory.build(:campaign)
|
22
|
+
campaign.mailchimp_campaign_id.should be_nil
|
23
|
+
|
24
|
+
Refinery::Mailchimp::API.should_receive(:new).and_return(mock('api', :campaign_create => 'abcdef'))
|
25
|
+
campaign.save
|
26
|
+
campaign.reload.mailchimp_campaign_id.should == 'abcdef'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not create and add error if mailchimp create fails" do
|
30
|
+
campaign = Factory.build(:campaign)
|
31
|
+
mock_api = mock('api')
|
32
|
+
mock_api.stub(:campaign_create) { |*args| raise Hominid::APIError.new(mock('xmlerror', :faultCode => -32602, :message => "server error. invalid method parameters")) }
|
33
|
+
Refinery::Mailchimp::API.should_receive(:new).and_return(mock_api)
|
34
|
+
campaign.save.should be_false
|
35
|
+
campaign.errors[:base].should include(I18n.t('admin.campaigns.campaign.mailchimp_error'))
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should update mailchimp before save"
|
39
|
+
it "should not save if mailchimp update fails"
|
40
|
+
it "should know if it's been sent or scheduled"
|
41
|
+
it "should know where it was sent to"
|
42
|
+
end
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: refinerycms-mailchimp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ian Terrell
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-04-04 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: hominid
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
version: "3.0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
description: Ruby on Rails Mailchimp engine for Refinery CMS. Manage your campaigns right from the admin!
|
37
|
+
email: ian.terrell@gmail.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- lib/generators/refinerycms_mailchimp_generator.rb
|
46
|
+
- lib/refinerycms-mailchimp.rb
|
47
|
+
- lib/tasks/mailchimp.rake
|
48
|
+
- config/locales/en.yml
|
49
|
+
- config/locales/nb.yml
|
50
|
+
- config/locales/nl.yml
|
51
|
+
- config/routes.rb
|
52
|
+
- app/controllers/admin/campaigns_controller.rb
|
53
|
+
- app/models/campaign.rb
|
54
|
+
- app/views/admin/campaigns/_campaign.html.erb
|
55
|
+
- app/views/admin/campaigns/_form.html.erb
|
56
|
+
- app/views/admin/campaigns/_modal_fields.html.erb
|
57
|
+
- app/views/admin/campaigns/_sortable_list.html.erb
|
58
|
+
- app/views/admin/campaigns/edit.html.erb
|
59
|
+
- app/views/admin/campaigns/index.html.erb
|
60
|
+
- app/views/admin/campaigns/new.html.erb
|
61
|
+
- app/views/admin/campaigns/send_options.html.erb
|
62
|
+
- spec/controllers/admin/campaigns_controller_spec.rb
|
63
|
+
- spec/models/api_spec.rb
|
64
|
+
- spec/models/campaign_spec.rb
|
65
|
+
- features/campaigns.feature_brainstorm
|
66
|
+
- features/support/factories/campaigns.rb
|
67
|
+
- features/support/paths.rb
|
68
|
+
- db/migrate/1_create_campaigns.rb
|
69
|
+
- db/seeds/campaigns.rb
|
70
|
+
has_rdoc: true
|
71
|
+
homepage: https://github.com/ianterrell/refinerycms-mailchimp
|
72
|
+
licenses: []
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 3
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
version: "0"
|
97
|
+
requirements: []
|
98
|
+
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.5.2
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: Ruby on Rails Mailchimp engine for Refinery CMS
|
104
|
+
test_files: []
|
105
|
+
|