├── .gitignore ├── app ├── views │ └── admin │ │ └── campaigns │ │ ├── edit.html.erb │ │ ├── new.html.erb │ │ ├── _modal_fields.html.erb │ │ ├── _sortable_list.html.erb │ │ ├── _campaign.html.erb │ │ ├── index.html.erb │ │ ├── send_options.html.erb │ │ └── _form.html.erb ├── controllers │ └── admin │ │ └── campaigns_controller.rb └── models │ └── campaign.rb ├── Rakefile ├── lib ├── generators │ └── refinerycms_mailchimp_generator.rb ├── tasks │ └── mailchimp.rake └── refinerycms-mailchimp.rb ├── features ├── support │ ├── factories │ │ └── campaigns.rb │ └── paths.rb └── campaigns.feature_brainstorm ├── config ├── routes.rb └── locales │ ├── nb.yml │ ├── nl.yml │ └── en.yml ├── spec ├── controllers │ └── admin │ │ └── campaigns_controller_spec.rb └── models │ ├── api_spec.rb │ └── campaign_spec.rb ├── db ├── migrate │ └── 1_create_campaigns.rb └── seeds │ └── campaigns.rb ├── refinerycms-mailchimp.gemspec └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem -------------------------------------------------------------------------------- /app/views/admin/campaigns/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= render :partial => "form" %> 2 | -------------------------------------------------------------------------------- /app/views/admin/campaigns/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render :partial => "form" %> 2 | -------------------------------------------------------------------------------- /app/views/admin/campaigns/_modal_fields.html.erb: -------------------------------------------------------------------------------- 1 | <% if from_dialog? %> 2 | 3 | 4 | <% end %> -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake' 2 | 3 | task :build do 4 | output = `gem build refinerycms-mailchimp.gemspec` 5 | if output =~ /File: refinerycms-mailchimp-([\d\.]+).gem/ 6 | `gem install ./refinerycms-mailchimp-#{$1}.gem` 7 | end 8 | end -------------------------------------------------------------------------------- /lib/generators/refinerycms_mailchimp_generator.rb: -------------------------------------------------------------------------------- 1 | require 'refinery/generators' 2 | 3 | class RefinerycmsMailchimp < Refinery::Generators::EngineInstaller 4 | 5 | source_root File.expand_path('../../../', __FILE__) 6 | engine_name "refinerycms-mailchimp" 7 | 8 | end 9 | -------------------------------------------------------------------------------- /features/support/factories/campaigns.rb: -------------------------------------------------------------------------------- 1 | Factory.define(:campaign) do |f| 2 | f.sequence(:subject) { |n| "See our #{n} newest site additions!" } 3 | f.body "Here's a campaign body!" 4 | f.to_name "Jimmy" 5 | f.from_name "Johnny" 6 | f.from_email "Johnson" 7 | f.mailchimp_list_id "ah23jxj" 8 | end -------------------------------------------------------------------------------- /app/views/admin/campaigns/_sortable_list.html.erb: -------------------------------------------------------------------------------- 1 | 4 | <%= render :partial => "/shared/admin/sortable_list", :locals => {:continue_reordering => (defined?(continue_reordering) ? continue_reordering : true)} %> 5 | -------------------------------------------------------------------------------- /lib/tasks/mailchimp.rake: -------------------------------------------------------------------------------- 1 | namespace :refinery do 2 | 3 | namespace :mailchimp do 4 | 5 | # call this task my running: rake refinery:campaigns:my_task 6 | # desc "Description of my task below" 7 | # task :my_task => :environment do 8 | # # add your logic here 9 | # end 10 | 11 | end 12 | 13 | end -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 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 14 | -------------------------------------------------------------------------------- /features/campaigns.feature_brainstorm: -------------------------------------------------------------------------------- 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 -------------------------------------------------------------------------------- /features/support/paths.rb: -------------------------------------------------------------------------------- 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 25 | -------------------------------------------------------------------------------- /spec/controllers/admin/campaigns_controller_spec.rb: -------------------------------------------------------------------------------- 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 -------------------------------------------------------------------------------- /db/migrate/1_create_campaigns.rb: -------------------------------------------------------------------------------- 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 26 | -------------------------------------------------------------------------------- /config/locales/nb.yml: -------------------------------------------------------------------------------- 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
(åpner i et nytt vindu) 15 | edit: Rediger denne campaign 16 | delete: Fjern denne campaign permanent 17 | campaigns: 18 | show: 19 | other: Andre Campaigns 20 | -------------------------------------------------------------------------------- /config/locales/nl.yml: -------------------------------------------------------------------------------- 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
(opent een nieuw venster) 15 | edit: Bewerk deze campaign 16 | delete: Verwijder deze campaign voor eeuwig 17 | campaigns: 18 | show: 19 | other: Andere Campaigns 20 | -------------------------------------------------------------------------------- /refinerycms-mailchimp.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.platform = Gem::Platform::RUBY 3 | s.name = 'refinerycms-mailchimp' 4 | s.author = 'Ian Terrell' 5 | s.email = 'ian.terrell@gmail.com' 6 | s.homepage = 'https://github.com/ianterrell/refinerycms-mailchimp' 7 | s.version = '0.0.2' 8 | s.description = 'Ruby on Rails Mailchimp engine for Refinery CMS. Manage your campaigns right from the admin!' 9 | s.date = '2011-04-04' 10 | s.summary = 'Ruby on Rails Mailchimp engine for Refinery CMS' 11 | s.require_paths = %w(lib) 12 | s.files = Dir['lib/**/*', 'config/**/*', 'app/**/*', 'spec/**/*', 'features/**/*', 'db/**/*'] 13 | s.add_dependency 'hominid', '~> 3.0' 14 | end 15 | -------------------------------------------------------------------------------- /db/seeds/campaigns.rb: -------------------------------------------------------------------------------- 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 | 11 | -------------------------------------------------------------------------------- /spec/models/api_spec.rb: -------------------------------------------------------------------------------- 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 -------------------------------------------------------------------------------- /app/views/admin/campaigns/_campaign.html.erb: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | <%= campaign.subject %> 4 | 5 | <% if campaign.sent? %> 6 | sent <%= distance_of_time_in_words_to_now(campaign.sent) %> ago 7 | <% elsif campaign.scheduled? %> 8 | sending in <%= distance_of_time_in_words_to_now(campaign.scheduled_at) %> 9 | <% end %> 10 | 11 | 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 | 22 |
  • 23 | -------------------------------------------------------------------------------- /lib/refinerycms-mailchimp.rb: -------------------------------------------------------------------------------- 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 40 | -------------------------------------------------------------------------------- /app/views/admin/campaigns/index.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | 16 |
    17 |
    18 | <% if searching? %> 19 |

    <%= t('shared.admin.search.results_for', :query => params[:search]) %>

    20 | <% if @campaigns.any? %> 21 | <%= will_paginate @campaigns, :previous_label => '«', :next_label => '»' %> 22 | 26 | <%= will_paginate @campaigns, :previous_label => '«', :next_label => '»' %> 27 | <% else %> 28 |

    <%= t('shared.admin.search.no_results') %>

    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 |

    43 | 44 | <%= t('.no_items_yet') %> 45 | 46 |

    47 | <% end %> 48 | <% end %> 49 |
    -------------------------------------------------------------------------------- /app/views/admin/campaigns/send_options.html.erb: -------------------------------------------------------------------------------- 1 | <% if @campaign.sent? %> 2 |

    Sent

    3 |

    4 | This campaign was sent <%= distance_of_time_in_words_to_now(@campaign.sent_at) %> ago. 5 |

    6 | <% elsif @campaign.scheduled? %> 7 |

    Scheduled

    8 |

    9 | This campaign is scheduled to be sent in <%= distance_of_time_in_words_to_now(@campaign.scheduled_at) %>. 10 |

    11 | <%= form_tag unschedule_admin_campaign_path(@campaign) do -%> 12 | <%= render :partial => "modal_fields" %> 13 | <%= submit_tag "Unschedule Campaign"%> 14 | <% end %> 15 | <% else %> 16 |

    Send Test Email

    17 |

    This will send a test email to the email address you enter below.

    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 |

    Send Campaign Now

    26 |

    This will send the campaign.

    27 | <%= form_tag send_now_admin_campaign_path(@campaign) do -%> 28 | <%= render :partial => "modal_fields" %> 29 | <%= submit_tag "Send Now"%> 30 | <% end %> 31 | 32 |

    Schedule Campaign for Later

    33 |

    This will schedule the campaign to be sent automatically at a future date.

    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 %> -------------------------------------------------------------------------------- /spec/models/campaign_spec.rb: -------------------------------------------------------------------------------- 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 -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Mailchimp engine for Refinery CMS 2 | 3 | This project was originally sponsored by Mailchimp! Many thanks to them for supporting open source development. 4 | 5 | ## How to use this engine with a Refinery CMS project 6 | 7 | To set up a Refinery app from scratch, you'll need to install Refinery and create a new app: 8 | 9 | gem install refinerycms 10 | refinerycms new_project 11 | cd new_project 12 | 13 | Once you have a Refinery app created, add this engine to your Gemfile in the `USER DEFINED` area: 14 | 15 | gem 'refinerycms-mailchimp' 16 | 17 | Then, from the command line: 18 | 19 | bundle install 20 | rails generate refinerycms_mailchimp 21 | rake db:migrate 22 | 23 | ## Settings 24 | 25 | You'll need to set up your Mailchimp API key in the Settings area. [Get your API key here.](https://admin.mailchimp.com/account/api-key-popup) 26 | 27 | All available settings are: 28 | 29 | * `mailchimp_api_key` The API key of the Mailchimp account you wish to send campaigns from. 30 | * `mailchimp_default_to_name` The default To: name recipients will see (not email address). This can be changed for each campaign. 31 | * `mailchimp_default_from_name` The default From: name for your campaign message (not an email address). This can be changed for each campaign. 32 | * `mailchimp_default_from_email` The default From: email address for your campaign message. This can be changed for each campaign. 33 | 34 | ## Using Templates 35 | 36 | This plugin currently only supports one editable text area per campaign. If you use a template, the body will replace the template's MAIN area (see [the Mailchimp docs on editable content areas](http://kb.mailchimp.com/article/template-language-creating-editable-content-areas)). 37 | 38 | ## How to run the test suite 39 | 40 | Uncomment the following line in your Gemfile: 41 | 42 | gem 'refinerycms-testing', '~> 0.9.9.9' 43 | 44 | Then install the testing functionality with 45 | 46 | rails generate refinerycms_testing 47 | 48 | You can now run all engine specs and features with `rake`, or run them separately with `rake spec` and `rake cucumber`. -------------------------------------------------------------------------------- /app/views/admin/campaigns/_form.html.erb: -------------------------------------------------------------------------------- 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 |
    8 | 9 | <%= f.label :subject -%> 10 | <%= refinery_help_tag t('.subject_help') %> 11 | 12 | <%= f.text_field :subject, :class => 'larger widest' -%> 13 |
    14 | 15 |
    16 | <%= f.label :body -%> 17 | <%= f.text_area :body, :rows => 20, :class => 'wymeditor widest' -%> 18 |
    19 | 20 |
    21 |

    <%= t('.to_and_from') %>

    22 | 23 |
    24 | 25 | <%= f.label :to_name, t('.to_name') -%> 26 | <%= refinery_help_tag t('.to_name_help') %> 27 | 28 | <%= f.text_field :to_name %> 29 |
    30 | 31 |
    32 | 33 | <%= f.label :from_name, t('.from_name') -%> 34 | <%= refinery_help_tag t('.from_name_help') %> 35 | 36 | <%= f.text_field :from_name %> 37 |
    38 | 39 |
    40 | 41 | <%= f.label :from_email, t('.from_email') -%> 42 | <%= refinery_help_tag t('.from_email_help') %> 43 | 44 | <%= f.text_field :from_email %> 45 |
    46 |
    47 | 48 |
    49 |

    <%= t('.settings') %>

    50 | 51 |
    52 | 53 | <%= f.label :mailchimp_list_id, t('.mailchimp_list_id') -%> 54 | <%= refinery_help_tag t('.mailchimp_list_id_help') %> 55 | 56 | <%= f.select :mailchimp_list_id, @lists.collect{ |list| [list['name'], list['id']] } %> 57 |
    58 | 59 |
    60 | 61 | <%= f.label :mailchimp_template_id, t('.mailchimp_template_id') -%> 62 | <%= refinery_help_tag t('.mailchimp_template_id_help') %> 63 | 64 | <%= f.select :mailchimp_template_id, @templates.collect{ |template| [template['name'], template['id']] }, :include_blank => true %> 65 |
    66 | 67 |
    68 | 69 | <%= f.label :auto_tweet, t('.auto_tweet') -%> 70 | <%= refinery_help_tag t('.auto_tweet_help') %> 71 | 72 | <%= f.check_box :auto_tweet %> 73 |
    74 |
    75 | 76 |
    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 -%> 86 | -------------------------------------------------------------------------------- /app/controllers/admin/campaigns_controller.rb: -------------------------------------------------------------------------------- 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 | before_filter :fully_qualify_links, :only => [:create, :update] 11 | 12 | def new 13 | @campaign = Campaign.new :to_name => RefinerySetting.get_or_set(Refinery::Mailchimp::API::DefaultToNameSetting[:name], Refinery::Mailchimp::API::DefaultToNameSetting[:default]), 14 | :from_name => RefinerySetting.get_or_set(Refinery::Mailchimp::API::DefaultFromNameSetting[:name], Refinery::Mailchimp::API::DefaultFromNameSetting[:default]), 15 | :from_email => RefinerySetting.get_or_set(Refinery::Mailchimp::API::DefaultFromEmailSetting[:name], Refinery::Mailchimp::API::DefaultFromEmailSetting[:default]) 16 | end 17 | 18 | def send_options 19 | end 20 | 21 | def send_test 22 | if @campaign.send_test_to params[:email] 23 | flash[:notice] = t('admin.campaigns.campaign.send_test_success', :email => params[:email]) 24 | else 25 | flash[:alert] = t('admin.campaigns.campaign.send_test_failure', :email => params[:email]) 26 | end 27 | sending_redirect_to admin_campaigns_path 28 | end 29 | 30 | def send_now 31 | if @campaign.send_now 32 | flash[:notice] = t('admin.campaigns.campaign.send_now_success') 33 | else 34 | flash[:alert] = t('admin.campaigns.campaign.send_now_failure') 35 | end 36 | sending_redirect_to admin_campaigns_path 37 | end 38 | 39 | def schedule 40 | if @campaign.schedule_for DateTime.new(*params['date'].values_at('year','month','day','hour','minute').map{|x|x.to_i}) 41 | flash[:notice] = t('admin.campaigns.campaign.schedule_success') 42 | else 43 | flash[:alert] = t('admin.campaigns.campaign.schedule_failure') 44 | end 45 | sending_redirect_to admin_campaigns_path 46 | end 47 | 48 | def unschedule 49 | if @campaign.unschedule 50 | flash[:notice] = t('admin.campaigns.campaign.unschedule_success') 51 | else 52 | flash[:alert] = t('admin.campaigns.campaign.unschedule_failure') 53 | end 54 | sending_redirect_to admin_campaigns_path 55 | end 56 | 57 | protected 58 | def sending_redirect_to(path) 59 | if from_dialog? 60 | render :text => "" 61 | else 62 | redirect_to path 63 | end 64 | end 65 | 66 | def need_api_key 67 | msg = t('admin.campaigns.index.set_api_key') 68 | msg += " #{t('admin.campaigns.index.set_api_link')}" 69 | flash[:alert] = msg.html_safe 70 | redirect_to admin_campaigns_path 71 | end 72 | 73 | def fully_qualify_links 74 | params[:campaign][:body].gsub!(/(href|src)="\//i, %|\\1="#{root_url}|) 75 | end 76 | 77 | def get_mailchimp_assets 78 | @lists = client.lists['data'] 79 | @templates = client.templates['user'] 80 | end 81 | 82 | def client 83 | @client ||= Refinery::Mailchimp::API.new 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 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
    (opens in a new window) 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 61 | -------------------------------------------------------------------------------- /app/models/campaign.rb: -------------------------------------------------------------------------------- 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 106 | --------------------------------------------------------------------------------