dm_newsletter 4.2.1.5

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.
Files changed (130) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +33 -0
  4. data/Rakefile +30 -0
  5. data/app/assets/stylesheets/dm_newsletter/application.css +13 -0
  6. data/app/controllers/dm_newsletter/admin/admin_controller.rb +16 -0
  7. data/app/controllers/dm_newsletter/admin/newsletters_controller.rb +81 -0
  8. data/app/controllers/dm_newsletter/application_controller.rb +3 -0
  9. data/app/controllers/dm_newsletter/newsletters_controller.rb +50 -0
  10. data/app/helpers/dm_newsletter/newsletters_helper.rb +8 -0
  11. data/app/models/dm_newsletter/concerns/ability.rb +37 -0
  12. data/app/models/dm_newsletter/permitted_params.rb +20 -0
  13. data/app/models/mailchimp_newsletter.rb +217 -0
  14. data/app/models/mailchimp_newsletter_subscriber.rb +43 -0
  15. data/app/models/newsletter.rb +46 -0
  16. data/app/models/newsletter_subscriber.rb +257 -0
  17. data/app/models/standard_newsletter.rb +19 -0
  18. data/app/views/dm_newsletter/admin/newsletters/_form.html.erb +17 -0
  19. data/app/views/dm_newsletter/admin/newsletters/edit.html.erb +2 -0
  20. data/app/views/dm_newsletter/admin/newsletters/index.html.erb +32 -0
  21. data/app/views/dm_newsletter/admin/newsletters/new.html.erb +2 -0
  22. data/app/views/dm_newsletter/admin/newsletters/show.html.erb +46 -0
  23. data/config/locales/nms.cs.yml +15 -0
  24. data/config/locales/nms.de.yml +15 -0
  25. data/config/locales/nms.en.yml +15 -0
  26. data/config/locales/nms.fi.yml +15 -0
  27. data/config/locales/nms.ja.yml +15 -0
  28. data/config/routes.rb +15 -0
  29. data/db/20130730120724_create_subscribers.rb +32 -0
  30. data/db/migrate/20130729075442_create_newsletter.rb +24 -0
  31. data/lib/dm_newsletter.rb +4 -0
  32. data/lib/dm_newsletter/engine.rb +8 -0
  33. data/lib/tasks/dm_newsletter_tasks.rake +4 -0
  34. data/spec/dummy/README.rdoc +28 -0
  35. data/spec/dummy/Rakefile +6 -0
  36. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  37. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  38. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  39. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  40. data/spec/dummy/app/models/ability.rb +12 -0
  41. data/spec/dummy/app/models/user.rb +6 -0
  42. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  43. data/spec/dummy/bin/bundle +3 -0
  44. data/spec/dummy/bin/rails +4 -0
  45. data/spec/dummy/bin/rake +4 -0
  46. data/spec/dummy/config.ru +4 -0
  47. data/spec/dummy/config/application.rb +26 -0
  48. data/spec/dummy/config/boot.rb +5 -0
  49. data/spec/dummy/config/database.yml +25 -0
  50. data/spec/dummy/config/environment.rb +5 -0
  51. data/spec/dummy/config/environments/development.rb +37 -0
  52. data/spec/dummy/config/environments/production.rb +82 -0
  53. data/spec/dummy/config/environments/test.rb +39 -0
  54. data/spec/dummy/config/initializers/assets.rb +8 -0
  55. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  56. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  57. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  58. data/spec/dummy/config/initializers/inflections.rb +16 -0
  59. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  60. data/spec/dummy/config/initializers/session_store.rb +3 -0
  61. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  62. data/spec/dummy/config/locales/en.yml +23 -0
  63. data/spec/dummy/config/routes.rb +12 -0
  64. data/spec/dummy/config/secrets.yml +22 -0
  65. data/spec/dummy/db/development.sqlite3 +0 -0
  66. data/spec/dummy/db/migrate/20141114170927_add_globalize_countries.dm_core.rb +50 -0
  67. data/spec/dummy/db/migrate/20141114170928_devise_create_users.dm_core.rb +46 -0
  68. data/spec/dummy/db/migrate/20141114170929_add_user_fields.dm_core.rb +14 -0
  69. data/spec/dummy/db/migrate/20141114170930_rolify_create_roles.dm_core.rb +20 -0
  70. data/spec/dummy/db/migrate/20141114170931_add_last_access.dm_core.rb +10 -0
  71. data/spec/dummy/db/migrate/20141114170932_create_versions.dm_core.rb +19 -0
  72. data/spec/dummy/db/migrate/20141114170933_add_object_changes_column_to_versions.dm_core.rb +12 -0
  73. data/spec/dummy/db/migrate/20141114170934_create_dm_core_accounts.dm_core.rb +13 -0
  74. data/spec/dummy/db/migrate/20141114170935_add_account_to_users.dm_core.rb +9 -0
  75. data/spec/dummy/db/migrate/20141114170936_create_preferences.dm_core.rb +13 -0
  76. data/spec/dummy/db/migrate/20141114170937_create_comments.dm_core.rb +22 -0
  77. data/spec/dummy/db/migrate/20141114170938_add_activity.dm_core.rb +21 -0
  78. data/spec/dummy/db/migrate/20141114170939_add_type_to_comments.dm_core.rb +9 -0
  79. data/spec/dummy/db/migrate/20141114170940_add_category.dm_core.rb +28 -0
  80. data/spec/dummy/db/migrate/20141114170941_create_email_table.dm_core.rb +26 -0
  81. data/spec/dummy/db/migrate/20141114170942_add_user_profile.dm_core.rb +46 -0
  82. data/spec/dummy/db/migrate/20141114170943_add_profile_email.dm_core.rb +14 -0
  83. data/spec/dummy/db/migrate/20141114170944_create_payment_history.dm_core.rb +37 -0
  84. data/spec/dummy/db/migrate/20141114170945_change_anchor_field.dm_core.rb +10 -0
  85. data/spec/dummy/db/migrate/20141114170946_create_user_site_profile.dm_core.rb +27 -0
  86. data/spec/dummy/db/migrate/20141114170947_add_avatar.dm_core.rb +12 -0
  87. data/spec/dummy/db/migrate/20141114170948_add_notify_to_payment_history.dm_core.rb +8 -0
  88. data/spec/dummy/db/migrate/20141114170949_acts_as_votable_migration.dm_core.rb +28 -0
  89. data/spec/dummy/db/migrate/20141114170950_add_user_site_profile_uuid.dm_core.rb +19 -0
  90. data/spec/dummy/db/migrate/20141114170951_add_invoice_id.dm_core.rb +7 -0
  91. data/spec/dummy/db/migrate/20141114170952_acts_as_follower_migration.dm_core.rb +18 -0
  92. data/spec/dummy/db/migrate/20141114170953_rename_invoice_id.dm_core.rb +12 -0
  93. data/spec/dummy/db/migrate/20141114170954_add_core_addresses.dm_core.rb +18 -0
  94. data/spec/dummy/db/migrate/20141114170955_papertrail_increase_column.dm_core.rb +9 -0
  95. data/spec/dummy/db/migrate/20141114170956_acts_as_taggable_on_migration.dm_core.rb +32 -0
  96. data/spec/dummy/db/migrate/20141114170957_add_missing_unique_indices.dm_core.rb +23 -0
  97. data/spec/dummy/db/migrate/20141114170958_add_taggings_counter_cache_to_tags.dm_core.rb +16 -0
  98. data/spec/dummy/db/migrate/20141114170959_create_custom_fields.dm_core.rb +40 -0
  99. data/spec/dummy/db/migrate/20141114170960_add_missing_taggable_index.dm_core.rb +11 -0
  100. data/spec/dummy/db/migrate/20141119112030_create_cms.dm_cms.rb +92 -0
  101. data/spec/dummy/db/migrate/20141119112031_add_account_to_cms.dm_cms.rb +11 -0
  102. data/spec/dummy/db/migrate/20141119112032_create_blog.dm_cms.rb +62 -0
  103. data/spec/dummy/db/migrate/20141119112033_add_notification_sent.dm_cms.rb +6 -0
  104. data/spec/dummy/db/migrate/20141119112034_add_blog_comment.dm_cms.rb +8 -0
  105. data/spec/dummy/db/migrate/20141119112035_add_blog_image.dm_cms.rb +6 -0
  106. data/spec/dummy/db/migrate/20141119112036_rename_snippet_slug.dm_cms.rb +14 -0
  107. data/spec/dummy/db/migrate/20141119112037_add_requires_subscription_blog.dm_cms.rb +8 -0
  108. data/spec/dummy/db/migrate/20141119112038_add_pages_ranked_model.dm_cms.rb +23 -0
  109. data/spec/dummy/db/migrate/20141119112039_add_blog_owner.dm_cms.rb +7 -0
  110. data/spec/dummy/db/migrate/20141119112040_create_media_files.dm_cms.rb +30 -0
  111. data/spec/dummy/db/migrate/20141119112041_add_cmspage_summary.dm_cms.rb +7 -0
  112. data/spec/dummy/db/migrate/20141119112042_add_blog_image_email_header.dm_cms.rb +6 -0
  113. data/spec/dummy/db/migrate/20141119112043_add_header_image.dm_cms.rb +10 -0
  114. data/spec/dummy/db/migrate/20160128145239_add_favored_locale.dm_core.rb +17 -0
  115. data/spec/dummy/db/migrate/20160128145240_update_papertrail_v4.dm_core.rb +41 -0
  116. data/spec/dummy/db/schema.rb +593 -0
  117. data/spec/dummy/public/404.html +67 -0
  118. data/spec/dummy/public/422.html +67 -0
  119. data/spec/dummy/public/500.html +66 -0
  120. data/spec/dummy/public/favicon.ico +0 -0
  121. data/spec/factories/accounts.rb +9 -0
  122. data/spec/factories/user_profiles.rb +10 -0
  123. data/spec/factories/users.rb +19 -0
  124. data/spec/models/newsletter_spec.rb +9 -0
  125. data/spec/rails_helper.rb +70 -0
  126. data/spec/spec_helper.rb +85 -0
  127. data/spec/support/accounts.rb +17 -0
  128. data/spec/support/devise.rb +44 -0
  129. data/spec/support/fix_locale.rb +57 -0
  130. metadata +296 -0
@@ -0,0 +1,43 @@
1
+ class MailchimpNewsletterSubscriber < NewsletterSubscriber
2
+
3
+ attr_accessor :member_info_data, :email, :euid, :subscribed, :grouping_id, :groups
4
+
5
+ # is subscriber interested in the named group?
6
+ #------------------------------------------------------------------------------
7
+ def interest_group?(name)
8
+ group = self.groups.detect {|group| group['name'] == name} if self.groups
9
+ return (group ? group['interested'] : false)
10
+ end
11
+
12
+ #------------------------------------------------------------------------------
13
+ def subscribed?
14
+ subscribed
15
+ end
16
+
17
+ # Instantiate a new subscriber based on data from a Mailchimp query like
18
+ # member_info. Does nothing with the database at this time.
19
+ #------------------------------------------------------------------------------
20
+ def self.new_from_mailchimp(attributes = {})
21
+ obj = MailchimpNewsletterSubscriber.new
22
+ obj.member_info_data = attributes
23
+ obj.subscribed = attributes['status'] == 'subscribed' ? true : false
24
+ obj.email = attributes['email']
25
+ obj.euid = attributes['euid']
26
+ obj.grouping_id = attributes['merges']['GROUPINGS'] ? attributes['merges']['GROUPINGS'][0]['id'] : nil
27
+ obj.groups = attributes['merges']['GROUPINGS'] ? attributes['merges']['GROUPINGS'][0]['groups'] : nil
28
+ return obj
29
+ end
30
+
31
+ # Query for the subscriber info.
32
+ #------------------------------------------------------------------------------
33
+ def self.subscriber_info(newsletter, email)
34
+ api = MailchimpNewsletter.api
35
+ subscriber = api.lists.member_info(id: newsletter.mc_id, emails: [email: email])
36
+ if subscriber['success_count'] == 1
37
+ return MailchimpNewsletterSubscriber.new_from_mailchimp(subscriber['data'][0])
38
+ else
39
+ return nil
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,46 @@
1
+ #------------------------------------------------------------------------------
2
+ class Newsletter < ActiveRecord::Base
3
+
4
+ self.table_name = 'email_newsletters'
5
+
6
+ # [todo] has_many :newsletter_subscribers, :dependent => :destroy
7
+
8
+ validates_uniqueness_of :token
9
+
10
+
11
+ default_scope { where(account_id: Account.current.id) }
12
+ before_create :generate_token
13
+
14
+ #------------------------------------------------------------------------------
15
+ def subscribe(user_or_email, options = {FNAME: '', LNAME: ''})
16
+ end
17
+
18
+ #------------------------------------------------------------------------------
19
+ def update_list_stats
20
+ end
21
+
22
+ #------------------------------------------------------------------------------
23
+ def map_error_to_msg(code)
24
+ end
25
+
26
+ # Find the newsletter associated with the token
27
+ #------------------------------------------------------------------------------
28
+ def self.find_newsletter(token, options = {})
29
+ Newsletter.find_by_token(token)
30
+ end
31
+
32
+ #------------------------------------------------------------------------------
33
+ def self.signup_information(token, options = {})
34
+ end
35
+
36
+ protected
37
+
38
+ #------------------------------------------------------------------------------
39
+ def generate_token
40
+ self.token = loop do
41
+ random_token = SecureRandom.hex(10)
42
+ break random_token unless Newsletter.where(token: random_token).exists?
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,257 @@
1
+ # [todo] currently not saving subscriber info in database, only working with a
2
+ # temporary object. Look at caching/syncing subscriber info for performance
3
+ #------------------------------------------------------------------------------
4
+ class NewsletterSubscriber #< ActiveRecord::Base
5
+
6
+ =begin
7
+ belongs_to :newsletter
8
+
9
+ validates_presence_of :email
10
+ validates_presence_of :firstname, :if => Proc.new { |sub| sub.newsletter.require_name}
11
+ validates_presence_of :lastname, :if => Proc.new { |sub| sub.newsletter.require_name}
12
+ validates_presence_of :country, :if => Proc.new { |sub| sub.newsletter.require_country}
13
+
14
+ default_scope { where(account_id: Account.current.id) }
15
+
16
+ #------------------------------------------------------------------------------
17
+ # protect admin values from being assigned via a malicious form
18
+ # attr_accessible makes everything protected except those listed
19
+ # attr_protected makes everything accessible except those listed
20
+ #------------------------------------------------------------------------------
21
+ scope :subscribed, :conditions => ["process_state = ?", 'subscribed']
22
+ scope :unsubscribed, :conditions => ["process_state = ?", 'unubscribed']
23
+ scope :unconfirmed, :conditions => ["process_state = ?", 'unconfirmed']
24
+ scope :not_reminded, :conditions => ["process_state = ? AND reminded_on IS NULL", 'unconfirmed']
25
+
26
+ attr_protected :subscribedate, :confirmed, :confrimdate, :unsubscribed,
27
+ :unsubscribedate, :confirmcode, :subscribeip,
28
+ :confirmationemail, :confirmationreply
29
+
30
+ belongs_to :country
31
+
32
+ #--- tie the subscriber_id to a student record
33
+ belongs_to :subscriber, :class_name => 'Student', :foreign_key => 'subscriber_id'
34
+
35
+ #=== validation rules
36
+
37
+ validates_length_of :firstname, :maximum => 50
38
+ validates_length_of :lastname, :maximum => 50
39
+ validates_length_of :email, :maximum => 60
40
+
41
+ validates_email_veracity_of :email, :on => :create
42
+
43
+ #--- define how the state machine works
44
+ acts_as_state_machine :initial => :unconfirmed, :column => :process_state
45
+ state :unconfirmed, :after => Proc.new { |o| o.update_attribute(:processed_on, Time.now) }
46
+ state :subscribed, :after => Proc.new { |o| o.update_attribute(:processed_on, Time.now) }
47
+ state :unsubscribed, :after => Proc.new { |o| o.update_attribute(:processed_on, Time.now) }
48
+ state :bounced, :after => Proc.new { |o| o.update_attribute(:processed_on, Time.now) }
49
+
50
+ #------------------------------------------------------------------------------
51
+ event :unconfirm do
52
+ transitions :from => :subscribed, :to => :unconfirmed
53
+ transitions :from => :unsubscribed, :to => :unconfirmed
54
+ transitions :from => :bounced, :to => :unconfirmed
55
+ end
56
+
57
+ #------------------------------------------------------------------------------
58
+ event :subscribe do
59
+ transitions :from => :unconfirmed, :to => :subscribed
60
+ transitions :from => :unsubscribed, :to => :subscribed
61
+ transitions :from => :bounced, :to => :subscribed
62
+ end
63
+
64
+ #------------------------------------------------------------------------------
65
+ event :unsubscribe do
66
+ transitions :from => :unconfirmed, :to => :unsubscribed
67
+ transitions :from => :subscribed, :to => :unsubscribed
68
+ transitions :from => :bounced, :to => :unsubscribed
69
+ end
70
+
71
+ #------------------------------------------------------------------------------
72
+ event :bounce do
73
+ transitions :from => :unconfirmed, :to => :bounced
74
+ transitions :from => :subscribed, :to => :bounced
75
+ transitions :from => :unsubscribed, :to => :bounced
76
+ end
77
+
78
+ # Takes either a Hash of values or an object that responds to the proper values
79
+ #------------------------------------------------------------------------------
80
+ def initialize(subscriber = nil, options = {:subscriber_id => nil})
81
+ if subscriber.nil? || subscriber.is_a?(Hash)
82
+ super(subscriber)
83
+ else
84
+ super(:firstname => subscriber.firstname, :lastname => subscriber.lastname,
85
+ :email => subscriber.email, :country => subscriber.country,
86
+ :subscriber_id => options[:subscriber_id])
87
+ end
88
+ write_attribute(:subscribeip, options[:remote_ip])
89
+ write_attribute(:confirmcode, generate_confirmation_code())
90
+ end
91
+
92
+ # find if there is an existing subscription
93
+ #------------------------------------------------------------------------------
94
+ def self.find_existing_subscription(newsletter_id, subscriber_id = nil, email = nil)
95
+ if subscriber_id
96
+ #--- look for a specific subscriber_id
97
+ subscriber = NewsletterSubscriber.find_by_subscriber_id_and_newsletter_id(subscriber_id, newsletter_id)
98
+ else
99
+ #--- look for a specific email address
100
+ subscriber = NewsletterSubscriber.find_by_email_and_newsletter_id(email, newsletter_id)
101
+ end
102
+ return subscriber
103
+ end
104
+
105
+ #------------------------------------------------------------------------------
106
+ def self.find_existing_subscription_is_subscribed(newsletter_id, subscriber_id = nil, email = nil)
107
+ subscriber = NewsletterSubscriber.find_existing_subscription(newsletter_id, subscriber_id, email)
108
+ return subscriber ? subscriber.is_subscribed? : false
109
+ end
110
+
111
+ # Return a reference to the actual subscriber data (like name and email).
112
+ #------------------------------------------------------------------------------
113
+ def subscriber_data
114
+ subscriber_id.nil? ? self : subscriber
115
+ end
116
+
117
+ #------------------------------------------------------------------------------
118
+ def country_name
119
+ self.country.english_name
120
+ end
121
+
122
+ #------------------------------------------------------------------------------
123
+ def full_name
124
+ name = firstname.capitalize + " " + lastname.capitalize
125
+ return name.blank? ? email : name
126
+ end
127
+
128
+ # Given a subscriber, update the information in this record with that from the
129
+ # subscriber info. If there is a subscriber_id, then don't update the record.
130
+ #------------------------------------------------------------------------------
131
+ def update_subscription(subscriber)
132
+ unless subscriber.nil?
133
+ update_attributes(:firstname => subscriber.firstname, :lastname => subscriber.lastname,
134
+ :email => subscriber.email, :country => subscriber.country)
135
+ end
136
+ end
137
+
138
+ #------------------------------------------------------------------------------
139
+ def hard_bounce
140
+ increment!(:hard_bounces)
141
+ bounce! if hard_bounces >= 1
142
+ end
143
+
144
+ #------------------------------------------------------------------------------
145
+ def soft_bounce
146
+ increment!(:soft_bounces)
147
+ end
148
+
149
+ #------------------------------------------------------------------------------
150
+ def is_subscribed?
151
+ process_state == 'subscribed'
152
+ end
153
+
154
+ #------------------------------------------------------------------------------
155
+ def is_unsubscribed?
156
+ process_state == 'unsubscribed'
157
+ end
158
+
159
+ #------------------------------------------------------------------------------
160
+ def is_unconfirmed?
161
+ process_state == 'unconfirmed'
162
+ end
163
+
164
+ #------------------------------------------------------------------------------
165
+ def is_bounced?
166
+ process_state == 'bounced'
167
+ end
168
+
169
+ #------------------------------------------------------------------------------
170
+ def generate_confirmation_code()
171
+ hashed(Time.now.to_i.to_s + rand.to_s)
172
+ end
173
+
174
+ #------------------------------------------------------------------------------
175
+ def hashed(str)
176
+ return Digest::SHA1.hexdigest("guruparampara--#{str}--")[0..39]
177
+ end
178
+
179
+ #------------------------------------------------------------------------------
180
+ def update_confirmationemail(email)
181
+ update_attribute(:confirmationemail, email)
182
+ end
183
+
184
+ # This trys to keep information indicating that the user actually
185
+ # did click on the activation link in the email. We will track the
186
+ # ipaddress and the uri that was requested.
187
+ #------------------------------------------------------------------------------
188
+ def update_confirmationreply(request_obj)
189
+ info = "Remote IP: " + request_obj.remote_ip + " URI: " + request_obj.url
190
+ update_attribute(:confirmationreply, info)
191
+ end
192
+
193
+ # Set everything back to a pre confirmed state
194
+ #------------------------------------------------------------------------------
195
+ def reset_confirmation
196
+ update_attribute(:confirmcode, generate_confirmation_code)
197
+ update_attribute(:confirmationemail, nil)
198
+ update_attribute(:confirmationreply, nil)
199
+ update_attribute(:hard_bounces, 0)
200
+ update_attribute(:soft_bounces, 0)
201
+ unconfirm!
202
+ end
203
+
204
+ #------------------------------------------------------------------------------
205
+ def send_confirmation
206
+ email = NewsletterSubscriberMailer.signup(self, confirm_subscription_url, confirm_unsubscribe_url).deliver_now
207
+ update_confirmationemail(email.to_s)
208
+ end
209
+
210
+ #------------------------------------------------------------------------------
211
+ def resend_confirmation
212
+ email = NewsletterSubscriberMailer.reconfirm(self, confirm_subscription_url, confirm_unsubscribe_url).deliver_now
213
+ update_confirmationemail(email.to_s)
214
+ update_attribute(:reminded_on, Time.now)
215
+ end
216
+
217
+ #------------------------------------------------------------------------------
218
+ def confirm_subscription_url
219
+ confirm_url = newsletter.account.preferred(:system_main_site) + "/#{I18n.locale}" + Hanuman::Application.config.confirm_subscription_url
220
+ confirm_url += "?subid=#{self.id}&code=#{self.confirmcode}"
221
+ end
222
+
223
+ #------------------------------------------------------------------------------
224
+ def confirm_unsubscribe_url
225
+ confirm_url = newsletter.account.preferred(:system_main_site) + "/#{I18n.locale}" + Hanuman::Application.config.confirm_unsubscription_url
226
+ confirm_url += "?subid=#{self.id}&code=#{self.confirmcode}"
227
+ end
228
+
229
+ # Return the number of items specified, in particular the number of items in
230
+ # a particular state
231
+ #------------------------------------------------------------------------------
232
+ def self.number_of(state, options = {})
233
+ #--- must be wanting to count the process states
234
+ if options[:date]
235
+ count(:conditions => "process_state = '#{state.to_s}' AND date(created_on) = '#{options[:date]}'")
236
+ elsif options[:before_date]
237
+ count(:conditions => "process_state = '#{state.to_s}' AND date(created_on) <= '#{options[:before_date]}'")
238
+ else
239
+ count(:conditions => "process_state = '#{state.to_s}'")
240
+ end
241
+ end
242
+
243
+ # Supported series:
244
+ # :subscribed, :unsubscribed, :unconfirmed, :continents
245
+ #------------------------------------------------------------------------------
246
+ def self.subscribers_chart_series(requested_data = :subscribed, months_ago = 24)
247
+ case requested_data
248
+ when :subscribed, :unsubscribed, :unconfirmed
249
+ months_ago.downto(0).map { |date| number_of(requested_data.to_s, :before_date => date.months.ago.to_date) }.inspect
250
+ when :continents
251
+ joins(:country).where(:process_state => 'subscribed').select('globalize_countries.continent').group('continent').count('continent')
252
+ end
253
+ end
254
+
255
+ =end
256
+
257
+ end
@@ -0,0 +1,19 @@
1
+ # This is the standard or "manual" newsletter class - all newsletter subscription
2
+ # funtions are handled internally. This is in case you don't want to use the
3
+ # integration with MailChimp
4
+ #------------------------------------------------------------------------------
5
+ class StandardNewsletter < Newsletter
6
+
7
+ validates_presence_of :name
8
+
9
+ #------------------------------------------------------------------------------
10
+ def self.signup_information(token, options = {})
11
+ #--- [todo] implement
12
+ end
13
+
14
+ #------------------------------------------------------------------------------
15
+ def map_error_to_msg(code)
16
+ #--- [todo] implement
17
+ end
18
+
19
+ end
@@ -0,0 +1,17 @@
1
+ <% submit_url = (@newsletter.new_record? ? admin_newsletters_path : admin_newsletter_path) %>
2
+ <%= simple_form_for @newsletter, url: submit_url,
3
+ html: { class: 'form-horizontal' }, wrapper: :bs3_horizontal_form, wrapper_mappings: DmAdmin::FormWrapperMappings do |f| %>
4
+
5
+ <%= f.error_notification :message => "Please review the problems below" %>
6
+
7
+ <%= panel header: false do %>
8
+ <% if using_mailchimp? %>
9
+ <%= f.input :mc_id , label: 'List ID', hint: 'MailChimp List ID, in the "Settings -> List Name and Defatuls" setion of a list' %>
10
+ <% else %>
11
+ <%= f.input :name , label: 'Name of Newsletter' %>
12
+ <% end %>
13
+
14
+ <%= submit_or_cancel :cancel_url => admin_newsletters_path %>
15
+ <% end %>
16
+
17
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <% content_for :content_title, "Edit Newsletter <small>#{@newsletter.name}</small>".html_safe %>
2
+ <%= render 'form' %>
@@ -0,0 +1,32 @@
1
+ <% content_for :content_title_extra do %>
2
+ <%= page_header_buttons do %>
3
+ <%= link_to(icon_label(:new, 'New'), new_admin_newsletter_path, title: 'New Newsletter', class: "btn btn-xs btn-default") %>
4
+ <% end %>
5
+ <% end %>
6
+
7
+ <% if false #using_mailchimp? %>
8
+ <% content_for :sidebar do %>
9
+ <%= link_to 'Sync with Mailchimp', admin_newsletters_synchronize_lists_path, class: "action-button greyish" %>
10
+ <% end %>
11
+ <% end %>
12
+
13
+
14
+ <% content_for :content_title, 'Newsletter Dashboard' %>
15
+
16
+ <% @newsletters.in_groups_of(2, false) do |newsletter_row| %>
17
+ <div class="row">
18
+ <% for newsletter in newsletter_row %>
19
+ <div class="col-md-12">
20
+ <% toolbar = toolbar_btn(newsletter.subscribed_count, admin_newsletter_path(newsletter), title: 'Number of subscriptions', class: 'label label-success pull-right') %>
21
+ <%= panel title: link_to(newsletter.name, admin_newsletter_path(newsletter)), toolbar: toolbar do %>
22
+ <ul class="statistics">
23
+ <% total = newsletter.subscribed_count + newsletter.unsubscribed_count + newsletter.cleaned_count %>
24
+ <li><%= stat_block_small label: 'subscribed', number: newsletter.subscribed_count, color_type: :success, percent: total == 0 ? 0 : (100 * newsletter.subscribed_count / total) %></li>
25
+ <li><%= stat_block_small label: 'unsubscribed', number: newsletter.unsubscribed_count, color_type: :danger, percent: total == 0 ? 0 : (100 * newsletter.unsubscribed_count / total) %></li>
26
+ <li><%= stat_block_small label: 'cleaned', number: newsletter.cleaned_count, color_type: :info, percent: total == 0 ? 0 : (100 * newsletter.cleaned_count / total) %></li>
27
+ </ul>
28
+ <% end %>
29
+ </div>
30
+ <% end %>
31
+ </div>
32
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <% content_for :content_title, 'New Newsletter' %>
2
+ <%= render 'form' %>
@@ -0,0 +1,46 @@
1
+ <% content_for :content_title, "#{@newsletter.name} <small>Newsletter</small>".html_safe %>
2
+ <% content_for :content_title_extra do %>
3
+ <%= page_header_buttons do %>
4
+ <%= link_to(icon_label(:trash, 'Delete'), admin_newsletter_path(@newsletter), method: :delete, class: "btn btn-xs btn-default", data: {confirm: 'Are you sure you wish to delete this newsletter?'}) %>
5
+ <% end %>
6
+ <% end %>
7
+
8
+ <%= panel header: false do %>
9
+ <div class="row">
10
+ <ul class="statistics">
11
+ <% total = @newsletter.subscribed_count + @newsletter.unsubscribed_count + @newsletter.cleaned_count %>
12
+ <li><%= stat_block_small label: 'subscribed', number: @newsletter.subscribed_count, color_type: :success, percent: total == 0 ? 0 : (100 * @newsletter.subscribed_count / total) %></li>
13
+ <li><%= stat_block_small label: 'unsubscribed', number: @newsletter.unsubscribed_count, color_type: :danger, percent: total == 0 ? 0 : (100 * @newsletter.unsubscribed_count / total) %></li>
14
+ <li><%= stat_block_small label: 'cleaned', number: @newsletter.cleaned_count, color_type: :info, percent: total == 0 ? 0 : (100 * @newsletter.cleaned_count / total) %></li>
15
+ </ul>
16
+ <hr>
17
+ </div>
18
+
19
+ <div class="row">
20
+ <dl class="dl-horizontal">
21
+ <dt>Subscription Token</dt>
22
+ <dd><%= @newsletter.token %></dd>
23
+ </dl>
24
+ </div>
25
+ <% end %>
26
+
27
+ <%= panel body: false, title: 'Campaign Folders' do %>
28
+ <table class="table table-striped table-bordered">
29
+ <thead>
30
+ <tr>
31
+ <th>Name</th>
32
+ <th width="50">Count</th>
33
+ <th width="100">Folder ID</th>
34
+ </tr>
35
+ </thead>
36
+ <tbody>
37
+ <% @folder_list.each do |folder| %>
38
+ <tr class="item">
39
+ <td><%= folder['name'] %></td>
40
+ <td><%= folder['cnt'] %></td>
41
+ <td><%= folder['folder_id'] %></td>
42
+ </tr>
43
+ <% end %>
44
+ </tbody>
45
+ </table>
46
+ <% end %>