Commit 4df54eb8b390b627c677c6969f18af2e39b49fa2
1 parent
296a549d
Exists in
staging
and in
41 other branches
new plugin: newsletter
a plugin that periodically sends newsletter via email to network users signed-off-by: Larissa Reis <larissa@colivre.coop.br> signed-off-by: Melissa Wen <melissa@colivre.coop.br>
Showing
22 changed files
with
1501 additions
and
0 deletions
Show diff stats
plugins/newsletter/controllers/newsletter_plugin_admin_controller.rb
0 → 100644
@@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +class NewsletterPluginAdminController < PluginAdminController | ||
2 | + | ||
3 | + def index | ||
4 | + @newsletter = NewsletterPlugin::Newsletter.where(environment_id: environment.id).first_or_initialize | ||
5 | + | ||
6 | + if request.post? | ||
7 | + # token input gives the param as a comma separated string | ||
8 | + params[:newsletter][:blog_ids] = (params[:newsletter][:blog_ids] || '').split(',') | ||
9 | + | ||
10 | + params[:newsletter][:person_id] = user.id | ||
11 | + | ||
12 | + file = params[:file] | ||
13 | + if file && file[:recipients].present? | ||
14 | + @newsletter.import_recipients(file[:recipients], file[:name], file[:email], file[:headers].present?) | ||
15 | + end | ||
16 | + | ||
17 | + if !@newsletter.errors.any? && @newsletter.update_attributes(params[:newsletter]) | ||
18 | + if params['visualize'] | ||
19 | + @message = @newsletter.body | ||
20 | + render :file => 'mailing/sender/notification', :layout => false | ||
21 | + else | ||
22 | + session[:notice] = _('Newsletter updated.') | ||
23 | + end | ||
24 | + else | ||
25 | + session[:notice] = _('Newsletter could not be saved.') | ||
26 | + end | ||
27 | + end | ||
28 | + | ||
29 | + @blogs = Blog.includes(:profile).find_all_by_id(@newsletter.blog_ids) | ||
30 | + end | ||
31 | + | ||
32 | + #TODO: Make this query faster | ||
33 | + def search_communities | ||
34 | + communities = environment.communities | ||
35 | + blogs = Blog.joins(:profile).where(profiles: {environment_id: environment.id}) | ||
36 | + | ||
37 | + found_communities = find_by_contents(:communities, environment, communities, params['q'], {:page => 1})[:results] | ||
38 | + found_blogs = find_by_contents(:blogs, environment, blogs, params['q'], {:page => 1})[:results] | ||
39 | + | ||
40 | + results = (found_blogs + found_communities.map(&:blogs).flatten).uniq | ||
41 | + render :text => results.map { |blog| {:id => blog.id, :name => _("%s in %s") % [blog.name, blog.profile.name]} }.to_json | ||
42 | + end | ||
43 | + | ||
44 | + def recipients | ||
45 | + @additional_recipients = NewsletterPlugin::Newsletter.where(environment_id: environment.id).first_or_initialize.additional_recipients | ||
46 | + end | ||
47 | + | ||
48 | +end |
plugins/newsletter/controllers/newsletter_plugin_controller.rb
0 → 100644
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +class NewsletterPluginController < PublicController | ||
2 | + | ||
3 | + before_filter :login_required, :only => :confirm_unsubscription | ||
4 | + | ||
5 | + def mailing | ||
6 | + if NewsletterPlugin::NewsletterMailing.exists?(params[:id]) | ||
7 | + mailing = NewsletterPlugin::NewsletterMailing.find(params[:id]) | ||
8 | + @message = mailing.body | ||
9 | + render :file => 'mailing/sender/notification', :layout => false | ||
10 | + else | ||
11 | + render :action => 'mailing_not_found' | ||
12 | + end | ||
13 | + end | ||
14 | + | ||
15 | + def confirm_unsubscription | ||
16 | + if request.post? | ||
17 | + session[:notice] = _('You was unsubscribed from newsletter.') | ||
18 | + @newsletter = NewsletterPlugin::Newsletter.where(environment_id: environment.id).first | ||
19 | + @newsletter.unsubscribe(current_user.email) | ||
20 | + redirect_to :controller => :home | ||
21 | + end | ||
22 | + end | ||
23 | + | ||
24 | +end |
plugins/newsletter/db/migrate/20150717195546_newsletter_plugin_newsletters.rb
0 → 100644
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +class NewsletterPluginNewsletters < ActiveRecord::Migration | ||
2 | + def up | ||
3 | + create_table :newsletter_plugin_newsletters do |t| | ||
4 | + t.references :environment, :null => false | ||
5 | + t.references :person, :null => false | ||
6 | + t.boolean :enabled, :default => false | ||
7 | + t.string :subject | ||
8 | + t.integer :periodicity, :default => 0 | ||
9 | + t.integer :posts_per_blog, :default => 0 | ||
10 | + t.integer :image_id | ||
11 | + t.text :footer | ||
12 | + t.text :blog_ids | ||
13 | + t.text :additional_recipients | ||
14 | + t.boolean :moderated | ||
15 | + t.text :unsubscribers | ||
16 | + end | ||
17 | + add_index :newsletter_plugin_newsletters, :environment_id, :uniq => true | ||
18 | + end | ||
19 | + | ||
20 | + def down | ||
21 | + remove_index :newsletter_plugin_newsletters, :environment_id | ||
22 | + drop_table :newsletter_plugin_newsletters | ||
23 | + end | ||
24 | +end |
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | +Feature: newsletter plugin | ||
2 | + | ||
3 | + Background: | ||
4 | + Given the following users | ||
5 | + | login | name | | ||
6 | + | joaosilva | Joao Silva | | ||
7 | + And I am logged in as "joaosilva" | ||
8 | + | ||
9 | + Scenario: as admin I can configure plugin | ||
10 | + Given I am logged in as admin | ||
11 | + When I go to the environment control panel | ||
12 | + And I follow "Plugins" | ||
13 | + Then I should see "Configuration" linking to "/admin/plugin/newsletter" | ||
14 | + | ||
15 | + Scenario: in the newsletter settings I can see the field to enable/disable | ||
16 | + Given I am logged in as admin | ||
17 | + When I go to the environment control panel | ||
18 | + And I follow "Plugins" | ||
19 | + And I follow "Configuration" | ||
20 | + Then I should see "Enable send of newsletter to members on this environment" | ||
21 | + | ||
22 | + Scenario: redirect to newsletter visualization after save and visualize | ||
23 | + Given I am logged in as admin | ||
24 | + And "NewsletterPlugin" plugin is enabled | ||
25 | + When I go to the environment control panel | ||
26 | + And I follow "Plugins" | ||
27 | + And I follow "Configuration" | ||
28 | + And I press "Save and visualize" | ||
29 | + Then I should see "If you can't view this email, click here" | ||
30 | + And I should not see "Newsletter settings" | ||
31 | + | ||
32 | + Scenario: stay on newsletter settings page after save | ||
33 | + Given I am logged in as admin | ||
34 | + And "NewsletterPlugin" plugin is enabled | ||
35 | + When I go to the environment control panel | ||
36 | + And I follow "Plugins" | ||
37 | + And I follow "Configuration" | ||
38 | + And I press "Save" | ||
39 | + Then I should see "Newsletter settings" | ||
40 | + And I should not see "If you can't view this email, click here" |
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +class NewsletterPlugin < Noosfero::Plugin | ||
2 | + | ||
3 | + def self.plugin_name | ||
4 | + "Newsletter" | ||
5 | + end | ||
6 | + | ||
7 | + def self.plugin_description | ||
8 | + _("Periodically sends newsletter via email to network users") | ||
9 | + end | ||
10 | + | ||
11 | + def js_files | ||
12 | + 'newsletter_plugin.js' | ||
13 | + end | ||
14 | + | ||
15 | + def stylesheet? | ||
16 | + true | ||
17 | + end | ||
18 | + | ||
19 | + def self.compile_and_send_newsletters | ||
20 | + NewsletterPlugin::Newsletter.enabled.each do |newsletter| | ||
21 | + if newsletter.must_be_sent_today? && newsletter.has_posts_in_the_period? | ||
22 | + if newsletter.moderated | ||
23 | + NewsletterPlugin::ModerateNewsletter.create!( | ||
24 | + :newsletter_id => newsletter.id, | ||
25 | + :environment => newsletter.environment | ||
26 | + ) | ||
27 | + else | ||
28 | + mailing = NewsletterPlugin::NewsletterMailing.create!( | ||
29 | + :source => newsletter, | ||
30 | + :subject => newsletter.subject, | ||
31 | + :body => newsletter.body, | ||
32 | + :person => newsletter.person, | ||
33 | + :locale => newsletter.environment.default_locale, | ||
34 | + ) | ||
35 | + mailing.update_attribute(:body, mailing.body.gsub('{mailing_url}', mailing.url)) | ||
36 | + end | ||
37 | + end | ||
38 | + end | ||
39 | + end | ||
40 | + | ||
41 | +end |
plugins/newsletter/lib/newsletter_plugin/moderate_newsletter.rb
0 → 100644
@@ -0,0 +1,53 @@ | @@ -0,0 +1,53 @@ | ||
1 | +class NewsletterPlugin::ModerateNewsletter < Task | ||
2 | + | ||
3 | + settings_items :newsletter_id, :post_ids | ||
4 | + validates_presence_of :newsletter_id | ||
5 | + | ||
6 | + alias :environment :target | ||
7 | + alias :environment= :target= | ||
8 | + | ||
9 | + def perform | ||
10 | + newsletter = NewsletterPlugin::Newsletter.find(newsletter_id) | ||
11 | + self.post_ids ||= [] | ||
12 | + mailing = NewsletterPlugin::NewsletterMailing.create!( | ||
13 | + :source => newsletter, | ||
14 | + :subject => newsletter.subject, | ||
15 | + :body => newsletter.body(:post_ids => self.post_ids.reject{|id| id.to_i.zero?}), | ||
16 | + :person => newsletter.person, | ||
17 | + :locale => newsletter.environment.default_locale, | ||
18 | + ) | ||
19 | + mailing.update_attribute(:body, mailing.body.gsub('{mailing_url}', mailing.url)) | ||
20 | + end | ||
21 | + | ||
22 | + def title | ||
23 | + _("Moderate newsletter") | ||
24 | + end | ||
25 | + | ||
26 | + def subject | ||
27 | + nil | ||
28 | + end | ||
29 | + | ||
30 | + def linked_subject | ||
31 | + nil | ||
32 | + end | ||
33 | + | ||
34 | + def information | ||
35 | + {:message => _('You have to moderate a newsletter.') } | ||
36 | + end | ||
37 | + | ||
38 | + def accept_details | ||
39 | + true | ||
40 | + end | ||
41 | + | ||
42 | + def icon | ||
43 | + {:type => :defined_image, :src => "/images/control-panel/email.png", :name => 'Newsletter'} | ||
44 | + end | ||
45 | + | ||
46 | + def target_notification_message | ||
47 | + _('A newsletter was generated and you need to review it before it is sent to users.') | ||
48 | + end | ||
49 | + | ||
50 | + def target_notification_description | ||
51 | + _('You need to moderate a newsletter.') | ||
52 | + end | ||
53 | +end |
@@ -0,0 +1,191 @@ | @@ -0,0 +1,191 @@ | ||
1 | +require 'csv' | ||
2 | + | ||
3 | +class NewsletterPlugin::Newsletter < Noosfero::Plugin::ActiveRecord | ||
4 | + | ||
5 | + belongs_to :environment | ||
6 | + belongs_to :person | ||
7 | + validates_presence_of :environment, :person | ||
8 | + validates_uniqueness_of :environment_id | ||
9 | + validates_numericality_of :periodicity, only_integer: true, greater_than: -1, message: _('must be a positive number') | ||
10 | + validates_numericality_of :posts_per_blog, only_integer: true, greater_than: -1, message: _('must be a positive number') | ||
11 | + | ||
12 | + attr_accessible :environment, :enabled, :periodicity, :subject, :posts_per_blog, :footer, :blog_ids, :additional_recipients, :person, :person_id, :moderated | ||
13 | + | ||
14 | + scope :enabled, :conditions => { :enabled => true } | ||
15 | + | ||
16 | + # These methods are used by NewsletterMailing | ||
17 | + def people | ||
18 | + list = unsubscribers.map{|i| "'#{i}'"}.join(',') | ||
19 | + if list.empty? | ||
20 | + environment.people | ||
21 | + else | ||
22 | + environment.people.all( | ||
23 | + :joins => "LEFT OUTER JOIN users ON (users.id = profiles.user_id)", | ||
24 | + :conditions => "users.email NOT IN (#{list})" | ||
25 | + ) | ||
26 | + end | ||
27 | + end | ||
28 | + | ||
29 | + def name | ||
30 | + environment.name | ||
31 | + end | ||
32 | + | ||
33 | + def contact_email | ||
34 | + environment.noreply_email | ||
35 | + end | ||
36 | + | ||
37 | + def top_url | ||
38 | + environment.top_url | ||
39 | + end | ||
40 | + | ||
41 | + def unsubscribe_url | ||
42 | + "#{top_url}/plugin/newsletter/unsubscribe" | ||
43 | + end | ||
44 | + | ||
45 | + serialize :blog_ids, Array | ||
46 | + serialize :additional_recipients, Array | ||
47 | + | ||
48 | + def blog_ids | ||
49 | + self[:blog_ids].map(&:to_i) || [] | ||
50 | + end | ||
51 | + | ||
52 | + validates_each :blog_ids do |record, attr, value| | ||
53 | + if record.environment | ||
54 | + unless value.delete_if(&:zero?).select { |id| !Blog.find_by_id(id) || Blog.find(id).environment != record.environment }.empty? | ||
55 | + record.errors.add(attr, _('must be valid')) | ||
56 | + end | ||
57 | + end | ||
58 | + unless value.uniq.length == value.length | ||
59 | + record.errors.add(attr, _('must not have duplicates')) | ||
60 | + end | ||
61 | + end | ||
62 | + | ||
63 | + validates_each :additional_recipients do |record, attr, value| | ||
64 | + unless value.reject { |recipient| recipient[:email] =~ Noosfero::Constants::EMAIL_FORMAT }.empty? | ||
65 | + record.errors.add(attr, _('must have only valid emails')) | ||
66 | + end | ||
67 | + end | ||
68 | + | ||
69 | + def next_send_at | ||
70 | + (self.last_send_at || DateTime.now) + self.periodicity.days | ||
71 | + end | ||
72 | + | ||
73 | + def must_be_sent_today? | ||
74 | + return true unless self.last_send_at | ||
75 | + Date.today >= self.next_send_at.to_date | ||
76 | + end | ||
77 | + | ||
78 | + def blogs | ||
79 | + Blog.where(:id => blog_ids) | ||
80 | + end | ||
81 | + | ||
82 | + def posts(data = {}) | ||
83 | + limit = self.posts_per_blog.zero? ? nil : self.posts_per_blog | ||
84 | + posts = if self.last_send_at.nil? | ||
85 | + self.blogs.map{|blog| blog.posts.all(:limit => limit)}.flatten | ||
86 | + else | ||
87 | + self.blogs.map{|blog| blog.posts.where("published_at >= :last_send_at", {last_send_at: self.last_send_at}).all(:limit => limit)}.flatten | ||
88 | + end | ||
89 | + data[:post_ids].nil? ? posts : posts.select{|post| data[:post_ids].include?(post.id.to_s)} | ||
90 | + end | ||
91 | + | ||
92 | + CSS = { | ||
93 | + 'breakingnews-wrap' => 'background-color: #EFEFEF; padding: 40px 0', | ||
94 | + 'breakingnews' => 'width: 640px; margin: auto; background-color: white; border: 1px solid #ddd; border-spacing: 0; padding: 0', | ||
95 | + 'newsletter-public-link' => 'width: 640px; margin: auto; font-size: small; color: #555; font-style: italic; text-align: right; margin-bottom: 15px; font-family: sans;', | ||
96 | + 'newsletter-header' => 'padding: 0', | ||
97 | + 'header-image' => 'width: 100%', | ||
98 | + 'post-image' => 'padding-left: 20px; width: 25%; border-bottom: 1px dashed #DDD', | ||
99 | + 'post-info' => 'font-family: Arial, Verdana; padding: 20px; width: 75%; border-bottom: 1px dashed #DDD', | ||
100 | + 'post-date' => 'font-size: 12px;', | ||
101 | + 'post-lead' => 'font-size: 14px; text-align: justify', | ||
102 | + 'post-title' => 'color: #000; text-decoration: none; font-size: 16px; text-align: justify', | ||
103 | + 'read-more-line' => 'text-align: right', | ||
104 | + 'read-more-link' => 'color: #000; font-size: 12px;', | ||
105 | + 'newsletter-unsubscribe' => 'width: 640px; margin: auto; font-size: small; color: #555; font-style: italic; text-align: center; margin-top: 15px; font-family: sans;' | ||
106 | + } | ||
107 | + | ||
108 | + # to be able to generate HTML | ||
109 | + include ActionView::Helpers | ||
110 | + include Rails.application.routes.url_helpers | ||
111 | + include DatesHelper | ||
112 | + | ||
113 | + def message_to_public_link | ||
114 | + content_tag(:p, N_("If you can't view this email, %s.") % link_to(N_('click here'), '{mailing_url}'), :id => 'newsletter-public-link') | ||
115 | + end | ||
116 | + | ||
117 | + def message_to_unsubscribe | ||
118 | + content_tag(:div, N_("This is an automatically generated email, please do not reply. If you do not wish to receive future newsletter emails, %s.") % link_to(N_("cancel your subscription here"), self.unsubscribe_url, :style => CSS['public-link']), :style => CSS['newsletter-unsubscribe'], :id => 'newsletter-unsubscribe') | ||
119 | + end | ||
120 | + | ||
121 | + def read_more(link_address) | ||
122 | + content_tag(:p, link_to(N_('Read more'), link_address, :style => CSS['read-more-link']), :style => CSS['read-more-line']) | ||
123 | + end | ||
124 | + | ||
125 | + def post_with_image(post) | ||
126 | + content_tag(:tr,content_tag(:td,tag(:img, :src => "#{self.environment.top_url}#{post.image.public_filename(:big)}", :id => post.id),:style => CSS['post-image'])+content_tag(:td,content_tag(:span, show_date(post.published_at), :style => CSS['post-date'])+content_tag(:h3, link_to(h(post.title), post.url, :style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(190)),:style => CSS['post-lead'])+read_more(post.url), :style => CSS['post-info'])) | ||
127 | + end | ||
128 | + | ||
129 | + def post_without_image(post) | ||
130 | + content_tag(:tr, content_tag(:td,content_tag(:span, show_date(post.published_at),:style => CSS['post-date'], :id => post.id)+content_tag(:h3, link_to(h(post.title), post.url,:style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(360)),:style => CSS['post-lead'])+read_more(post.url),:colspan => 2, :style => CSS['post-info'])) | ||
131 | + end | ||
132 | + | ||
133 | + def body(data = {}) | ||
134 | + content_tag(:div, content_tag(:div, message_to_public_link, :style => CSS['newsletter-public-link'])+content_tag(:table,(self.image.nil? ? '' : content_tag(:tr, content_tag(:th, tag(:img, :src => "#{self.environment.top_url}#{self.image.public_filename}", :style => CSS['header-image']),:colspan => 2),:style => CSS['newsletter-header']))+self.posts(data).map do |post| | ||
135 | + if post.image | ||
136 | + post_with_image(post) | ||
137 | + else | ||
138 | + post_without_image(post) | ||
139 | + end | ||
140 | + end.join()+content_tag(:tr, content_tag(:td, self.footer, :colspan => 2)),:style => CSS['breakingnews'])+content_tag(:div,message_to_unsubscribe, :style => CSS['newsletter-unsubscribe']),:style => CSS['breakingnews-wrap']) | ||
141 | + end | ||
142 | + | ||
143 | + def default_subject | ||
144 | + N_('Breaking news') | ||
145 | + end | ||
146 | + | ||
147 | + def subject | ||
148 | + self[:subject] || default_subject | ||
149 | + end | ||
150 | + | ||
151 | + def import_recipients(file, name_column = nil, email_column = nil, headers = nil) | ||
152 | + name_column ||= 1 | ||
153 | + email_column ||= 2 | ||
154 | + headers ||= false | ||
155 | + | ||
156 | + if File.extname(file.original_filename) == '.csv' | ||
157 | + parsed_recipients = [] | ||
158 | + CSV.foreach(file.path, headers: headers) do |row| | ||
159 | + parsed_recipients << {name: row[name_column.to_i - 1], email: row[email_column.to_i - 1]} | ||
160 | + end | ||
161 | + self.additional_recipients = parsed_recipients | ||
162 | + else | ||
163 | + #FIXME find a better way to deal with errors | ||
164 | + self.errors.add(:additional_recipients, _("have unknown file type: %s" % file.original_filename)) | ||
165 | + end | ||
166 | + end | ||
167 | + | ||
168 | + acts_as_having_image | ||
169 | + | ||
170 | + def last_send_at | ||
171 | + last_mailing = NewsletterPlugin::NewsletterMailing.last( | ||
172 | + :conditions => {:source_id => self.id} | ||
173 | + ) | ||
174 | + last_mailing.nil? ? nil : last_mailing.created_at | ||
175 | + end | ||
176 | + | ||
177 | + def sanitize(html) | ||
178 | + html.gsub(/<\/?p>/, '') | ||
179 | + end | ||
180 | + | ||
181 | + def has_posts_in_the_period? | ||
182 | + ! self.posts.empty? | ||
183 | + end | ||
184 | + | ||
185 | + serialize :unsubscribers, Array | ||
186 | + | ||
187 | + def unsubscribe(email) | ||
188 | + unsubscribers.push(email).uniq! | ||
189 | + end | ||
190 | + | ||
191 | +end |
plugins/newsletter/lib/newsletter_plugin/newsletter_mailing.rb
0 → 100644
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +class NewsletterPlugin::NewsletterMailing < EnvironmentMailing | ||
2 | + | ||
3 | + attr_accessible :source, :person, :locale | ||
4 | + | ||
5 | + validates_presence_of :person | ||
6 | + | ||
7 | + def url | ||
8 | + "#{self.source.top_url}/plugin/newsletter/mailing/#{self.id}" | ||
9 | + end | ||
10 | + | ||
11 | + def source | ||
12 | + NewsletterPlugin::Newsletter.find(source_id) | ||
13 | + end | ||
14 | + | ||
15 | + def deliver | ||
16 | + source.additional_recipients.each do |recipient| | ||
17 | + begin | ||
18 | + Mailing::Sender.notification(self, recipient[:email]).deliver | ||
19 | + rescue Exception => ex | ||
20 | + Rails.logger.error("#{ex.class.to_s} - #{ex.to_s} at #{__FILE__}:#{__LINE__}") | ||
21 | + end | ||
22 | + end | ||
23 | + super | ||
24 | + end | ||
25 | + | ||
26 | +end |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +jQuery(function($) { | ||
2 | + $(".newsletter-toggle-link").live('click', function(){ | ||
3 | + element_id = this.getAttribute('element_id'); | ||
4 | + toggle_link = this; | ||
5 | + $(element_id).slideToggle(400, function() { | ||
6 | + if ($(toggle_link).find('.ui-icon').hasClass('ui-icon-triangle-1-s')) | ||
7 | + $(toggle_link).find('.ui-icon') | ||
8 | + .removeClass('ui-icon-triangle-1-s') | ||
9 | + .addClass('ui-icon-triangle-1-n'); | ||
10 | + else | ||
11 | + $(toggle_link).find('.ui-icon') | ||
12 | + .removeClass('ui-icon-triangle-1-n') | ||
13 | + .addClass('ui-icon-triangle-1-s'); | ||
14 | + }); | ||
15 | + return false; | ||
16 | + }); | ||
17 | + | ||
18 | + $('#file_recipients').change(function(){ | ||
19 | + $('#newsletter-file-options input').enable(); | ||
20 | + }); | ||
21 | +}); |
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +.newsletter-toggle-link { | ||
2 | + cursor: pointer; | ||
3 | +} | ||
4 | +#newsletter-footer-field { | ||
5 | + display: none; | ||
6 | +} | ||
7 | +#newsletter-enabled-field input#settings_enabled { | ||
8 | + margin-right: 6px; | ||
9 | +} | ||
10 | + | ||
11 | +#newsletter-moderation-preview #newsletter-public-link, | ||
12 | +#newsletter-moderation-preview #newsletter-unsubscribe { | ||
13 | + display: none; | ||
14 | +} | ||
15 | + | ||
16 | +#newsletter-moderation-preview { | ||
17 | + margin-left: 25px; | ||
18 | +} | ||
19 | + | ||
20 | +#newsletter-moderation-preview input[type=checkbox] { | ||
21 | + margin-left: -27px; | ||
22 | + margin-top: 16px; | ||
23 | + float: left; | ||
24 | +} |
plugins/newsletter/test/functional/newsletter_plugin_admin_controller_test.rb
0 → 100644
@@ -0,0 +1,176 @@ | @@ -0,0 +1,176 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | + | ||
3 | +class NewsletterPluginAdminControllerTest < ActionController::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @controller = NewsletterPluginAdminController.new | ||
7 | + @request = ActionController::TestRequest.new | ||
8 | + @response = ActionController::TestResponse.new | ||
9 | + | ||
10 | + @admin = create_user('admin_newsletter').person | ||
11 | + @environment = @admin.environment | ||
12 | + @environment.add_admin(@admin) | ||
13 | + | ||
14 | + @environment.enable_plugin(NewsletterPlugin) | ||
15 | + @controller.stubs(:environment).returns(@environment) | ||
16 | + end | ||
17 | + | ||
18 | + should 'allow access to admin' do | ||
19 | + login_as @admin.identifier | ||
20 | + get :index | ||
21 | + assert_response :success | ||
22 | + end | ||
23 | + | ||
24 | + should 'save footer setting' do | ||
25 | + login_as @admin.identifier | ||
26 | + post :index, | ||
27 | + :newsletter => { :footer => 'footer of newsletter' } | ||
28 | + | ||
29 | + assert_equal 'footer of newsletter', assigns(:newsletter).footer | ||
30 | + end | ||
31 | + | ||
32 | + | ||
33 | + should 'save header image' do | ||
34 | + login_as @admin.identifier | ||
35 | + post :index, | ||
36 | + :newsletter => { | ||
37 | + :image_builder => { | ||
38 | + :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') | ||
39 | + } | ||
40 | + } | ||
41 | + assert_equal 'rails.png', assigns(:newsletter).image.filename | ||
42 | + end | ||
43 | + | ||
44 | + should 'save enabled newsletter information' do | ||
45 | + login_as @admin.identifier | ||
46 | + post :index, | ||
47 | + :newsletter => { :enabled => 'true' } | ||
48 | + | ||
49 | + newsletter = NewsletterPlugin::Newsletter.find_by_environment_id(@environment.id) | ||
50 | + | ||
51 | + assert newsletter.enabled | ||
52 | + end | ||
53 | + | ||
54 | + should 'save periodicity newsletter information' do | ||
55 | + login_as @admin.identifier | ||
56 | + post :index, | ||
57 | + :newsletter => { :periodicity => '10' } | ||
58 | + | ||
59 | + newsletter = NewsletterPlugin::Newsletter.find_by_environment_id(@environment.id) | ||
60 | + | ||
61 | + assert_equal 10, newsletter.periodicity | ||
62 | + end | ||
63 | + | ||
64 | + should 'save number of posts per blog setting' do | ||
65 | + login_as @admin.identifier | ||
66 | + post :index, | ||
67 | + :newsletter => { :posts_per_blog => '6' } | ||
68 | + | ||
69 | + assert_equal 6, assigns(:newsletter).posts_per_blog | ||
70 | + end | ||
71 | + | ||
72 | + should 'show error if number of posts per blog is not a positive number' do | ||
73 | + login_as @admin.identifier | ||
74 | + post :index, | ||
75 | + :newsletter => { :posts_per_blog => '-4' } | ||
76 | + | ||
77 | + assert_select 'li', 'Posts per blog must be a positive number' | ||
78 | + end | ||
79 | + | ||
80 | + should 'save blogs for compiling newsletter setting' do | ||
81 | + login_as @admin.identifier | ||
82 | + | ||
83 | + blog1 = fast_create(Blog) | ||
84 | + blog1.profile = fast_create(Profile, environment_id: @environment.id) | ||
85 | + blog1.save | ||
86 | + | ||
87 | + blog2 = fast_create(Blog) | ||
88 | + blog2.profile = fast_create(Profile, environment_id: @environment.id) | ||
89 | + blog2.save | ||
90 | + | ||
91 | + post :index, | ||
92 | + :newsletter => { :blog_ids => "#{blog1.id},#{blog2.id}" } | ||
93 | + | ||
94 | + assert_equivalent [blog1.id,blog2.id], assigns(:newsletter).blog_ids | ||
95 | + end | ||
96 | + | ||
97 | + should 'show error if blog is not in environment' do | ||
98 | + login_as @admin.identifier | ||
99 | + | ||
100 | + blog = fast_create(Blog) | ||
101 | + blog.profile = fast_create(Profile, environment_id: fast_create(Environment).id) | ||
102 | + blog.save | ||
103 | + | ||
104 | + post :index, | ||
105 | + :newsletter => { :blog_ids => "#{blog.id}" } | ||
106 | + | ||
107 | + assert_select 'li', 'Blog ids must be valid' | ||
108 | + end | ||
109 | + | ||
110 | + should 'save logged in admin as person' do | ||
111 | + login_as @admin.identifier | ||
112 | + post :index, :newsletter => { } | ||
113 | + | ||
114 | + assert_equal @admin, assigns(:newsletter).person | ||
115 | + end | ||
116 | + | ||
117 | + should 'receive csv file from user' do | ||
118 | + content = <<-EOS | ||
119 | +Coop1,name1@example.com | ||
120 | +Coop2,name2@example.com | ||
121 | +Coop3,name3@example.com | ||
122 | +EOS | ||
123 | + | ||
124 | + file = Tempfile.new(['recipients', '.csv']) | ||
125 | + file.write(content) | ||
126 | + file.rewind | ||
127 | + | ||
128 | + login_as @admin.identifier | ||
129 | + post :index, newsletter: {}, :file => { recipients: Rack::Test::UploadedFile.new(file, 'text/csv') } | ||
130 | + | ||
131 | + file.close | ||
132 | + file.unlink | ||
133 | + | ||
134 | + assert_equivalent ["name1@example.com", "name2@example.com", "name3@example.com"], assigns(:newsletter).additional_recipients.map { |recipient| recipient[:email] } | ||
135 | + assert_equivalent ["Coop1", "Coop2", "Coop3"], assigns(:newsletter).additional_recipients.map { |recipient| recipient[:name] } | ||
136 | + end | ||
137 | + | ||
138 | + should 'parse csv file with configuration set by user' do | ||
139 | + content = <<-EOS | ||
140 | +Id,Name,City,Email | ||
141 | +1,Coop1,Moscow,name1@example.com | ||
142 | +2,Coop2,Beijing,name2@example.com | ||
143 | +3,Coop3,Paris,name3@example.com | ||
144 | +EOS | ||
145 | + | ||
146 | + file = Tempfile.new(['recipients', '.csv']) | ||
147 | + file.write(content) | ||
148 | + file.rewind | ||
149 | + | ||
150 | + login_as @admin.identifier | ||
151 | + post :index, newsletter: {}, :file => { recipients: Rack::Test::UploadedFile.new(file, 'text/csv'), headers: 1, name: 2, email: 4 } | ||
152 | + | ||
153 | + file.close | ||
154 | + file.unlink | ||
155 | + | ||
156 | + assert_equivalent ["name1@example.com", "name2@example.com", "name3@example.com"], assigns(:newsletter).additional_recipients.map { |recipient| recipient[:email] } | ||
157 | + assert_equivalent ["Coop1", "Coop2", "Coop3"], assigns(:newsletter).additional_recipients.map { |recipient| recipient[:name] } | ||
158 | + end | ||
159 | + | ||
160 | + should 'list additional recipients' do | ||
161 | + login_as @admin.identifier | ||
162 | + get :recipients | ||
163 | + assert_select 'p', 'There are no additional recipients.' | ||
164 | + | ||
165 | + newsletter = NewsletterPlugin::Newsletter.create!(environment: @environment, person: fast_create(Person)) | ||
166 | + newsletter.additional_recipients = [ {name: 'Coop1', email: 'name1@example.com'} ] | ||
167 | + newsletter.save! | ||
168 | + | ||
169 | + get :recipients | ||
170 | + assert_select 'tr' do | ||
171 | + assert_select 'td', 'Coop1' | ||
172 | + assert_select 'td', 'name1@example.com' | ||
173 | + end | ||
174 | + end | ||
175 | + | ||
176 | +end |
plugins/newsletter/test/functional/newsletter_plugin_controller_test.rb
0 → 100644
@@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | + | ||
3 | +class NewsletterPluginControllerTest < ActionController::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @controller = NewsletterPluginController.new | ||
7 | + @request = ActionController::TestRequest.new | ||
8 | + @response = ActionController::TestResponse.new | ||
9 | + environment = fast_create(Environment) | ||
10 | + environment.enable_plugin(NewsletterPlugin) | ||
11 | + @controller.stubs(:environment).returns(environment) | ||
12 | + end | ||
13 | + | ||
14 | + should 'require login to confirm unsubscription' do | ||
15 | + post :confirm_unsubscription | ||
16 | + assert_response 302 | ||
17 | + end | ||
18 | + | ||
19 | + should 'open unsubscription page for anonymous' do | ||
20 | + get :unsubscribe | ||
21 | + assert_response :success | ||
22 | + end | ||
23 | + | ||
24 | + should 'add user email from unsubscribers list' do | ||
25 | + NewsletterPlugin::Newsletter.create!( | ||
26 | + :environment => @controller.environment, | ||
27 | + :person => fast_create(Person) | ||
28 | + ) | ||
29 | + maria = create_user("maria").person | ||
30 | + login_as("maria") | ||
31 | + post :confirm_unsubscription | ||
32 | + assert_response :redirect | ||
33 | + assert_redirected_to :controller => 'home' | ||
34 | + assert_includes assigns(:newsletter).unsubscribers, maria.email | ||
35 | + end | ||
36 | + | ||
37 | +end |
plugins/newsletter/test/unit/newsletter_plugin_moderate_newsletter_test.rb
0 → 100644
@@ -0,0 +1,50 @@ | @@ -0,0 +1,50 @@ | ||
1 | +require 'test_helper' | ||
2 | + | ||
3 | +class NewsletterPluginModerateNewsletterTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'validates presence of newsletter_id' do | ||
6 | + task = NewsletterPlugin::ModerateNewsletter.new | ||
7 | + task.valid? | ||
8 | + assert task.errors.include?(:newsletter_id) | ||
9 | + | ||
10 | + task.newsletter_id = 1 | ||
11 | + task.valid? | ||
12 | + refute task.errors.include?(:newsletter_id) | ||
13 | + end | ||
14 | + | ||
15 | + should 'create mailing on perform' do | ||
16 | + person = create_user('john').person | ||
17 | + newsletter = NewsletterPlugin::Newsletter.create!(:environment => fast_create(Environment), :person => person, :enabled => true) | ||
18 | + task = NewsletterPlugin::ModerateNewsletter.create!( | ||
19 | + :newsletter_id => newsletter.id, | ||
20 | + :target => newsletter.environment | ||
21 | + ) | ||
22 | + | ||
23 | + assert_difference 'NewsletterPlugin::NewsletterMailing.count', 1 do | ||
24 | + task.finish | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + should 'set posts for mailing body on perform' do | ||
29 | + person = create_user('john').person | ||
30 | + blog = fast_create(Blog, profile_id: person.id) | ||
31 | + post_1 = fast_create(TextileArticle, :name => 'First post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
32 | + post_2 = fast_create(TextileArticle, :name => 'Second post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
33 | + post_3 = fast_create(TextileArticle, :name => 'Third post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
34 | + | ||
35 | + newsletter = NewsletterPlugin::Newsletter.create!(:environment => person.environment, :person => person, :enabled => true) | ||
36 | + newsletter.blog_ids = [blog.id] | ||
37 | + newsletter.save! | ||
38 | + | ||
39 | + task = NewsletterPlugin::ModerateNewsletter.create!( | ||
40 | + :newsletter_id => newsletter.id, | ||
41 | + :target => newsletter.environment, | ||
42 | + :post_ids => [post_1.id.to_s,post_2.id.to_s] | ||
43 | + ) | ||
44 | + | ||
45 | + task.finish | ||
46 | + assert_match /First post/, NewsletterPlugin::NewsletterMailing.last.body | ||
47 | + assert_match /Second post/, NewsletterPlugin::NewsletterMailing.last.body | ||
48 | + assert_not_match /Third post/, NewsletterPlugin::NewsletterMailing.last.body | ||
49 | + end | ||
50 | +end |
plugins/newsletter/test/unit/newsletter_plugin_newsletter_mailing_test.rb
0 → 100644
@@ -0,0 +1,72 @@ | @@ -0,0 +1,72 @@ | ||
1 | +require 'test_helper' | ||
2 | + | ||
3 | +class NewsletterPluginNewsletterMailingTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + ActionMailer::Base.delivery_method = :test | ||
7 | + ActionMailer::Base.perform_deliveries = true | ||
8 | + ActionMailer::Base.deliveries = [] | ||
9 | + end | ||
10 | + | ||
11 | + should 'require source id' do | ||
12 | + mailing = NewsletterPlugin::NewsletterMailing.new | ||
13 | + mailing.valid? | ||
14 | + assert mailing.errors[:source_id].any? | ||
15 | + | ||
16 | + mailing.source_id = NewsletterPlugin::Newsletter.create!(:environment => fast_create(Environment), :person => fast_create(Person)).id | ||
17 | + mailing.valid? | ||
18 | + refute mailing.errors[:source_id].any? | ||
19 | + end | ||
20 | + | ||
21 | + should 'deliver mail from noreply environment email address' do | ||
22 | + environment = fast_create(Environment, :noreply_email => 'noreply@localhost') | ||
23 | + person = fast_create Person | ||
24 | + newsletter = NewsletterPlugin::Newsletter.create!(:environment => environment, :person => person, :enabled => true) | ||
25 | + mailing = NewsletterPlugin::NewsletterMailing.create!( | ||
26 | + :source => newsletter, | ||
27 | + :subject => newsletter.subject, | ||
28 | + :body => newsletter.body, | ||
29 | + :person => newsletter.person, | ||
30 | + :locale => environment.default_locale, | ||
31 | + ) | ||
32 | + response = NewsletterPlugin::NewsletterMailing::Sender.notification(mailing, 'recipient@example.com').deliver | ||
33 | + assert_equal 'noreply@localhost', response.from.join | ||
34 | + end | ||
35 | + | ||
36 | + should 'also send to additional recipients' do | ||
37 | + environment = fast_create(Environment, :name => 'Network') | ||
38 | + person = create_user('betty', :environment_id => environment.id).person | ||
39 | + newsletter = NewsletterPlugin::Newsletter.create!(:environment => environment, :person => person) | ||
40 | + | ||
41 | + newsletter.additional_recipients = [{name: 'example', email: 'exemple@mail.co'}, {name: 'jon', email: 'jonsnow@mail.co'}] | ||
42 | + newsletter.save! | ||
43 | + | ||
44 | + mailing = NewsletterPlugin::NewsletterMailing.create!( | ||
45 | + :source => newsletter, | ||
46 | + :subject => newsletter.subject, | ||
47 | + :body => newsletter.body, | ||
48 | + :person => newsletter.person, | ||
49 | + :locale => newsletter.environment.default_locale, | ||
50 | + ) | ||
51 | + | ||
52 | + process_delayed_job_queue | ||
53 | + assert_equal 3, ActionMailer::Base.deliveries.count | ||
54 | + end | ||
55 | + | ||
56 | + should 'generate url to view mailing' do | ||
57 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
58 | + :environment => fast_create(Environment), | ||
59 | + :person => fast_create(Person), | ||
60 | + :enabled => true | ||
61 | + ) | ||
62 | + mailing = NewsletterPlugin::NewsletterMailing.create!( | ||
63 | + :source => newsletter, | ||
64 | + :subject => newsletter.subject, | ||
65 | + :body => newsletter.body, | ||
66 | + :person => newsletter.person, | ||
67 | + :locale => newsletter.environment.default_locale, | ||
68 | + ) | ||
69 | + assert_equal "http://localhost/plugin/newsletter/mailing/#{mailing.id}", mailing.url | ||
70 | + end | ||
71 | + | ||
72 | +end |
plugins/newsletter/test/unit/newsletter_plugin_newsletter_test.rb
0 → 100644
@@ -0,0 +1,414 @@ | @@ -0,0 +1,414 @@ | ||
1 | +require 'test_helper' | ||
2 | + | ||
3 | +class NewsletterPluginNewsletterTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'throws exception when try to create newsletters without reference do environment' do | ||
6 | + assert_raises ActiveRecord::RecordInvalid do |e| | ||
7 | + NewsletterPlugin::Newsletter.create! | ||
8 | + assert_match /Profile can't be blank/, e.to_s | ||
9 | + end | ||
10 | + end | ||
11 | + | ||
12 | + should 'allow save only one newsletter by environment' do | ||
13 | + environment = fast_create Environment | ||
14 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :person => fast_create(Person)) | ||
15 | + assert_raises ActiveRecord::RecordInvalid do |e| | ||
16 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :person => fast_create(Person)) | ||
17 | + assert_match /Profile has already been taken/, e.to_s | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + should 'collect enabled newsletters' do | ||
22 | + enabled_newsletters = [] | ||
23 | + 5.times do | ||
24 | + environment = fast_create(Environment) | ||
25 | + enabled = environment.id % 2 == 0 | ||
26 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
27 | + :environment => environment, | ||
28 | + :enabled => enabled, | ||
29 | + :person => fast_create(Person)) | ||
30 | + enabled_newsletters << newsletter.id if enabled | ||
31 | + end | ||
32 | + assert_equal enabled_newsletters, NewsletterPlugin::Newsletter.enabled.map(&:id) | ||
33 | + end | ||
34 | + | ||
35 | + should 'people of newsletters are the same environment members' do | ||
36 | + 3.times do | ||
37 | + environment = fast_create(Environment) | ||
38 | + 3.times do | ||
39 | + fast_create(Person, environment_id: environment) | ||
40 | + end | ||
41 | + NewsletterPlugin::Newsletter.create!( | ||
42 | + :environment => environment, | ||
43 | + :enabled => true, | ||
44 | + :person => fast_create(Person)) | ||
45 | + end | ||
46 | + NewsletterPlugin::Newsletter.enabled.each do |newsletter| | ||
47 | + assert_not_equal [], newsletter.people | ||
48 | + assert_equal newsletter.environment.people, newsletter.people | ||
49 | + end | ||
50 | + end | ||
51 | + | ||
52 | + should 'save period for newsletter' do | ||
53 | + environment = fast_create Environment | ||
54 | + NewsletterPlugin::Newsletter.create!( | ||
55 | + :environment => environment, | ||
56 | + :periodicity => '3', | ||
57 | + :person => fast_create(Person)) | ||
58 | + | ||
59 | + assert_equal 3, NewsletterPlugin::Newsletter.find_by_environment_id(environment.id).periodicity | ||
60 | + end | ||
61 | + | ||
62 | + should 'save period as number only' do | ||
63 | + environment = fast_create Environment | ||
64 | + assert_raises ActiveRecord::RecordInvalid do |e| | ||
65 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :periodicity => 'one week' ) | ||
66 | + assert_match /Periodicity must be a positive number/, e.to_s | ||
67 | + end | ||
68 | + end | ||
69 | + | ||
70 | + should 'save period as a positive number only' do | ||
71 | + environment = fast_create Environment | ||
72 | + assert_raises ActiveRecord::RecordInvalid do |e| | ||
73 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :periodicity => -1 ) | ||
74 | + assert_match /Periodicity must be a positive number/, e.to_s | ||
75 | + end | ||
76 | + end | ||
77 | + | ||
78 | + should 'save reference to environment blog' do | ||
79 | + environment = fast_create Environment | ||
80 | + blog = fast_create(Blog) | ||
81 | + blog.profile = fast_create(Profile, environment_id: environment.id) | ||
82 | + blog.save | ||
83 | + assert_nothing_raised ActiveRecord::RecordInvalid do | ||
84 | + NewsletterPlugin::Newsletter.create!( | ||
85 | + :environment => environment, | ||
86 | + :blog_ids => [blog.id], | ||
87 | + :person => fast_create(Person)) | ||
88 | + end | ||
89 | + end | ||
90 | + | ||
91 | + should 'not save reference to unknown blog' do | ||
92 | + environment = fast_create Environment | ||
93 | + blog = fast_create(Blog) | ||
94 | + blog.profile = fast_create(Profile, environment_id: fast_create(Environment).id) | ||
95 | + blog.save | ||
96 | + assert_raises ActiveRecord::RecordInvalid do |e| | ||
97 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :blog_ids => [blog.id]) | ||
98 | + assert_match /Blog ids must be valid/, e.to_s | ||
99 | + end | ||
100 | + assert_raises ActiveRecord::RecordInvalid do |e| | ||
101 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :blog_ids => [blog.id*2]) | ||
102 | + assert_match /Blog ids must be valid/, e.to_s | ||
103 | + end | ||
104 | + end | ||
105 | + | ||
106 | + should 'not save duplicates for blog ids' do | ||
107 | + environment = fast_create Environment | ||
108 | + blog = fast_create(Blog) | ||
109 | + blog.profile = fast_create(Profile, environment_id: environment.id) | ||
110 | + blog.save | ||
111 | + assert_raises ActiveRecord::RecordInvalid do |e| | ||
112 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :blog_ids => [blog.id, blog.id]) | ||
113 | + assert_match /Blog ids must not have duplicates/, e.to_s | ||
114 | + end | ||
115 | + end | ||
116 | + | ||
117 | + should "not send newsletters if periodicity isn't expired" do | ||
118 | + newsletter = NewsletterPlugin::Newsletter.new | ||
119 | + newsletter.periodicity = 10 | ||
120 | + newsletter.stubs(:last_send_at).returns(DateTime.parse("2015-01-01")) | ||
121 | + Date.stubs(:today).returns(Date.parse("2015-01-07")) | ||
122 | + assert_equal false, newsletter.must_be_sent_today? | ||
123 | + end | ||
124 | + | ||
125 | + should 'send newsletters when periodicity expires' do | ||
126 | + newsletter = NewsletterPlugin::Newsletter.new | ||
127 | + newsletter.periodicity = 10 | ||
128 | + newsletter.stubs(:last_send_at).returns(DateTime.parse("2015-01-01")) | ||
129 | + Date.stubs(:today).returns(Date.parse("2015-01-15")) | ||
130 | + assert_equal true, newsletter.must_be_sent_today? | ||
131 | + end | ||
132 | + | ||
133 | + should 'send now if never send before' do | ||
134 | + newsletter = NewsletterPlugin::Newsletter.new(:environment => fast_create(Environment)) | ||
135 | + newsletter.periodicity = 10 | ||
136 | + assert newsletter.must_be_sent_today? | ||
137 | + end | ||
138 | + | ||
139 | + should 'validate email format for additional recipients' do | ||
140 | + environment = fast_create Environment | ||
141 | + assert_raises ActiveRecord::RecordInvalid do |e| | ||
142 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :person => fast_create(Person), additional_recipients: [{name: 'Cooperative', email: 'cooperative@example'}]) | ||
143 | + assert_match /Additional recipients must have only valid emails/, e.to_s | ||
144 | + end | ||
145 | + assert_nothing_raised ActiveRecord::RecordInvalid do |e| | ||
146 | + NewsletterPlugin::Newsletter.create!(:environment => environment, :person => fast_create(Person), additional_recipients: [{name: 'Cooperative', email: 'cooperative@example.com'}]) | ||
147 | + end | ||
148 | + end | ||
149 | + | ||
150 | + should 'parse additional recipients' do | ||
151 | + content = <<-EOS | ||
152 | +Coop1,name1@example.com | ||
153 | +Coop2,name2@example.com | ||
154 | +Coop3,name3@example.com | ||
155 | +EOS | ||
156 | + | ||
157 | + file = Tempfile.new(['recipients', '.csv']) | ||
158 | + file.write(content) | ||
159 | + file.rewind | ||
160 | + | ||
161 | + environment = fast_create Environment | ||
162 | + newsletter = NewsletterPlugin::Newsletter.create!(:environment => environment, :person => fast_create(Person)) | ||
163 | + newsletter.import_recipients(Rack::Test::UploadedFile.new(file, 'text/csv')) | ||
164 | + | ||
165 | + file.close | ||
166 | + file.unlink | ||
167 | + | ||
168 | + assert_equivalent ["name1@example.com", "name2@example.com", "name3@example.com"], newsletter.additional_recipients.map { |recipient| recipient[:email] } | ||
169 | + assert_equivalent ["Coop1", "Coop2", "Coop3"], newsletter.additional_recipients.map { |recipient| recipient[:name] } | ||
170 | + end | ||
171 | + | ||
172 | + should 'only parse csv files' do | ||
173 | + content = <<-EOS | ||
174 | +Coop1,name1@example.com | ||
175 | +Coop2,name2@example.com | ||
176 | +Coop3,name3@example.com | ||
177 | +EOS | ||
178 | + | ||
179 | + file = Tempfile.new(['recipients', '.txt']) | ||
180 | + file.write(content) | ||
181 | + file.rewind | ||
182 | + | ||
183 | + environment = fast_create Environment | ||
184 | + newsletter = NewsletterPlugin::Newsletter.create!(:environment => environment, :person => fast_create(Person)) | ||
185 | + newsletter.import_recipients(Rack::Test::UploadedFile.new(file)) | ||
186 | + | ||
187 | + file.close | ||
188 | + file.unlink | ||
189 | + | ||
190 | + assert_equal [], newsletter.additional_recipients | ||
191 | + assert_match /Additional recipients have unknown file type.*/, newsletter.errors.full_messages[0] | ||
192 | + end | ||
193 | + | ||
194 | + should 'parse additional recipients with given column number and header' do | ||
195 | + content = <<-EOS | ||
196 | +Id,Name,City,Email | ||
197 | +1,Coop1,Moscow,name1@example.com | ||
198 | +2,Coop2,Beijing,name2@example.com | ||
199 | +3,Coop3,Paris,name3@example.com | ||
200 | +EOS | ||
201 | + | ||
202 | + file = Tempfile.new(['recipients', '.csv']) | ||
203 | + file.write(content) | ||
204 | + file.rewind | ||
205 | + | ||
206 | + environment = fast_create Environment | ||
207 | + newsletter = NewsletterPlugin::Newsletter.create!(:environment => environment, :person => fast_create(Person)) | ||
208 | + newsletter.import_recipients(Rack::Test::UploadedFile.new(file, 'text/csv'), 2, 4, true) | ||
209 | + | ||
210 | + file.close | ||
211 | + file.unlink | ||
212 | + | ||
213 | + assert_equivalent ["name1@example.com", "name2@example.com", "name3@example.com"], newsletter.additional_recipients.map { |recipient| recipient[:email] } | ||
214 | + assert_equivalent ["Coop1", "Coop2", "Coop3"], newsletter.additional_recipients.map { |recipient| recipient[:name] } | ||
215 | + end | ||
216 | + | ||
217 | + should 'retrieve blogs related to newsletter' do | ||
218 | + environment = fast_create Environment | ||
219 | + community = fast_create(Community, :environment_id => environment.id) | ||
220 | + blog1 = fast_create(Blog, :profile_id => community.id) | ||
221 | + blog2 = fast_create(Blog, :profile_id => community.id) | ||
222 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
223 | + :environment => environment, :blog_ids => [blog1.id, blog2.id], :person => fast_create(Person) | ||
224 | + ) | ||
225 | + assert_equivalent [blog1, blog2], newsletter.blogs | ||
226 | + end | ||
227 | + | ||
228 | + should 'return empty if has no related blogs' do | ||
229 | + environment = fast_create Environment | ||
230 | + newsletter = NewsletterPlugin::Newsletter.create!(:environment => environment, :person => fast_create(Person)) | ||
231 | + assert_empty newsletter.blogs | ||
232 | + end | ||
233 | + | ||
234 | + should 'list posts for all selected blogs' do | ||
235 | + environment = fast_create Environment | ||
236 | + community = fast_create(Community, :environment_id => environment.id) | ||
237 | + blog = fast_create(Blog, :profile_id => community.id) | ||
238 | + post = fast_create(TextArticle, :parent_id => blog.id, :name => 'the last news') | ||
239 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
240 | + :environment => environment, | ||
241 | + :blog_ids => [blog.id], | ||
242 | + :person => fast_create(Person)) | ||
243 | + assert_includes newsletter.posts, post | ||
244 | + end | ||
245 | + | ||
246 | + should 'generate HTML content using posts of selected blogs' do | ||
247 | + environment = fast_create Environment | ||
248 | + community = fast_create(Community, :environment_id => environment.id) | ||
249 | + blog = fast_create(Blog, :profile_id => community.id) | ||
250 | + fast_create(TextArticle, :profile_id => community.id, :parent_id => blog.id, :name => 'the last news') | ||
251 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
252 | + :environment => environment, | ||
253 | + :blog_ids => [blog.id], | ||
254 | + :person => fast_create(Person)) | ||
255 | + assert_tag_in_string newsletter.body, :tag => 'a', :content => 'the last news' | ||
256 | + end | ||
257 | + | ||
258 | + should 'limit the number of posts per blog' do | ||
259 | + environment = fast_create Environment | ||
260 | + community = fast_create(Community, :environment_id => environment.id) | ||
261 | + blog = fast_create(Blog, :profile_id => community.id) | ||
262 | + fast_create(TextArticle, :parent_id => blog.id, :name => 'the last news 1') | ||
263 | + fast_create(TextArticle, :parent_id => blog.id, :name => 'the last news 2') | ||
264 | + fast_create(TextArticle, :parent_id => blog.id, :name => 'the last news 3') | ||
265 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
266 | + :environment => environment, | ||
267 | + :blog_ids => [blog.id], | ||
268 | + :person => fast_create(Person), | ||
269 | + :posts_per_blog => 2) | ||
270 | + assert_equal 2, newsletter.posts.count | ||
271 | + end | ||
272 | + | ||
273 | + should 'include all posts before today' do | ||
274 | + environment = fast_create Environment | ||
275 | + community = fast_create(Community, :environment_id => environment.id) | ||
276 | + blog = fast_create(Blog, :profile_id => community.id) | ||
277 | + | ||
278 | + post1 = fast_create(TextArticle, :parent_id => blog.id, :name => 'the last news 1', | ||
279 | + :published_at => DateTime.parse("2015-01-01")) | ||
280 | + post2 = fast_create(TextArticle, :parent_id => blog.id, :name => 'the last news 2', | ||
281 | + :published_at => DateTime.parse("2015-01-09")) | ||
282 | + | ||
283 | + Date.stubs(:today).returns(DateTime.parse("2015-01-10").to_date) | ||
284 | + | ||
285 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
286 | + :environment => environment, | ||
287 | + :blog_ids => [blog.id], | ||
288 | + :person => fast_create(Person)) | ||
289 | + | ||
290 | + newsletter_posts = newsletter.posts | ||
291 | + assert_includes newsletter_posts, post1 | ||
292 | + assert_includes newsletter_posts, post2 | ||
293 | + end | ||
294 | + | ||
295 | + should 'not include posts already sent' do | ||
296 | + environment = fast_create Environment | ||
297 | + community = fast_create(Community, :environment_id => environment.id) | ||
298 | + blog = fast_create(Blog, :profile_id => community.id) | ||
299 | + | ||
300 | + post1 = fast_create(TextArticle, :parent_id => blog.id, :name => 'the last news 1', | ||
301 | + :published_at => DateTime.parse("2015-01-01")) | ||
302 | + post2 = fast_create(TextArticle, :parent_id => blog.id, :name => 'the last news 2', | ||
303 | + :published_at => DateTime.parse("2015-01-09")) | ||
304 | + | ||
305 | + Date.stubs(:today).returns(DateTime.parse("2015-01-10").to_date) | ||
306 | + | ||
307 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
308 | + :environment => environment, | ||
309 | + :blog_ids => [blog.id], | ||
310 | + :person => fast_create(Person)) | ||
311 | + newsletter.stubs(:last_send_at).returns(DateTime.parse("2015-01-05")) | ||
312 | + | ||
313 | + newsletter_posts = newsletter.posts | ||
314 | + assert_not_includes newsletter_posts, post1 | ||
315 | + assert_includes newsletter_posts, post2 | ||
316 | + end | ||
317 | + | ||
318 | + should 'sanitize tags <p> from news lead' do | ||
319 | + environment = fast_create Environment | ||
320 | + community = fast_create(Community, :environment_id => environment.id) | ||
321 | + blog = fast_create(Blog, :profile_id => community.id) | ||
322 | + post = fast_create(TextArticle, :parent_id => blog.id, | ||
323 | + :name => 'the last news 1', | ||
324 | + :profile_id => community.id, | ||
325 | + :body => "<p>paragraph of news</p>") | ||
326 | + | ||
327 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
328 | + :environment => environment, | ||
329 | + :blog_ids => [blog.id], | ||
330 | + :person => fast_create(Person)) | ||
331 | + | ||
332 | + assert_match /<p>paragraph of news<\/p>/, post.body | ||
333 | + assert_not_match /<p>paragraph of news<\/p>/, newsletter.body | ||
334 | + end | ||
335 | + | ||
336 | + should 'filter posts when listing posts for newsletter' do | ||
337 | + person = fast_create(Person) | ||
338 | + blog = fast_create(Blog, profile_id: person.id) | ||
339 | + | ||
340 | + post_1 = fast_create(TextileArticle, :name => 'First post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
341 | + post_2 = fast_create(TextileArticle, :name => 'Second post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
342 | + post_3 = fast_create(TextileArticle, :name => 'Third post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
343 | + | ||
344 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
345 | + :environment => person.environment, | ||
346 | + :blog_ids => [blog.id], | ||
347 | + :person => person) | ||
348 | + | ||
349 | + assert_equivalent [post_2.id, post_3.id], newsletter.posts({post_ids: [post_2.id.to_s, post_3.id.to_s]}).map(&:id) | ||
350 | + end | ||
351 | + | ||
352 | + should 'filter posts in body for newsletter' do | ||
353 | + person = fast_create(Person) | ||
354 | + blog = fast_create(Blog, profile_id: person.id) | ||
355 | + | ||
356 | + post_1 = fast_create(TextileArticle, :name => 'First post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
357 | + post_2 = fast_create(TextileArticle, :name => 'Second post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
358 | + post_3 = fast_create(TextileArticle, :name => 'Third post', :profile_id => person.id, :parent_id => blog.id, :body => 'Test') | ||
359 | + | ||
360 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
361 | + :environment => person.environment, | ||
362 | + :blog_ids => [blog.id], | ||
363 | + :person => person) | ||
364 | + | ||
365 | + assert_match /First post/, NewsletterPlugin::Newsletter.last.body({post_ids: [post_1.id.to_s, post_3.id.to_s]}) | ||
366 | + assert_not_match /Second post/, NewsletterPlugin::Newsletter.last.body({post_ids: [post_1.id.to_s, post_3.id.to_s]}) | ||
367 | + assert_match /Third post/, NewsletterPlugin::Newsletter.last.body({post_ids: [post_1.id.to_s, post_3.id.to_s]}) | ||
368 | + end | ||
369 | + | ||
370 | + should 'add email to unsubscribers list' do | ||
371 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
372 | + :environment => fast_create(Environment), | ||
373 | + :person => fast_create(Person) | ||
374 | + ) | ||
375 | + newsletter.unsubscribe("ze@localhost.localdomain") | ||
376 | + assert_includes newsletter.unsubscribers, "ze@localhost.localdomain" | ||
377 | + end | ||
378 | + | ||
379 | + should 'not add same email twice to unsubscribers list' do | ||
380 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
381 | + :environment => fast_create(Environment), | ||
382 | + :person => fast_create(Person) | ||
383 | + ) | ||
384 | + newsletter.unsubscribe("ze@localhost.localdomain") | ||
385 | + newsletter.unsubscribe("ze@localhost.localdomain") | ||
386 | + assert_equal ["ze@localhost.localdomain"], newsletter.unsubscribers | ||
387 | + end | ||
388 | + | ||
389 | + should "filter newsletter's recipients using unsubscribers list" do | ||
390 | + environment = fast_create Environment | ||
391 | + p1 = create_user("person1", :environment_id => environment.id).person | ||
392 | + p2 = create_user("person2", :environment_id => environment.id).person | ||
393 | + p3 = create_user("person3", :environment_id => environment.id).person | ||
394 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
395 | + :environment => environment, | ||
396 | + :person => fast_create(Person) | ||
397 | + ) | ||
398 | + newsletter.unsubscribe(p2.email) | ||
399 | + assert_equivalent [p1, p3], newsletter.people | ||
400 | + end | ||
401 | + | ||
402 | + should "no filter newsletter's recipients if unsubscribers list empty" do | ||
403 | + environment = fast_create Environment | ||
404 | + p1 = create_user("person1", :environment_id => environment.id).person | ||
405 | + p2 = create_user("person2", :environment_id => environment.id).person | ||
406 | + p3 = create_user("person3", :environment_id => environment.id).person | ||
407 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
408 | + :environment => environment, | ||
409 | + :person => fast_create(Person) | ||
410 | + ) | ||
411 | + assert_equivalent [p1, p2, p3], newsletter.people | ||
412 | + end | ||
413 | + | ||
414 | +end |
@@ -0,0 +1,113 @@ | @@ -0,0 +1,113 @@ | ||
1 | +require 'test_helper' | ||
2 | + | ||
3 | +class NewsletterPluginTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + NewsletterPlugin::Newsletter.any_instance.stubs(:must_be_sent_today?).returns(true) | ||
7 | + NewsletterPlugin::Newsletter.any_instance.stubs(:has_posts_in_the_period?).returns(true) | ||
8 | + end | ||
9 | + | ||
10 | + should 'update newsletter send date only for enabled newsletters' do | ||
11 | + newsletter_enabled = NewsletterPlugin::Newsletter.create!( | ||
12 | + :environment => fast_create(Environment), | ||
13 | + :enabled => true, | ||
14 | + :subject => 'newsletter test', | ||
15 | + :person => fast_create(Person)) | ||
16 | + | ||
17 | + newsletter_disabled = NewsletterPlugin::Newsletter.create!( | ||
18 | + :environment => fast_create(Environment), | ||
19 | + :enabled => false, | ||
20 | + :subject => 'newsletter test', | ||
21 | + :person => fast_create(Person)) | ||
22 | + | ||
23 | + NewsletterPlugin.compile_and_send_newsletters | ||
24 | + | ||
25 | + newsletter_enabled.reload | ||
26 | + newsletter_disabled.reload | ||
27 | + | ||
28 | + assert_not_nil newsletter_enabled.last_send_at | ||
29 | + assert_nil newsletter_disabled.last_send_at | ||
30 | + end | ||
31 | + | ||
32 | + should 'create and schedule newsletter mailing if not moderated' do | ||
33 | + NewsletterPlugin::Newsletter.create!( | ||
34 | + :environment => fast_create(Environment), | ||
35 | + :enabled => true, | ||
36 | + :moderated => false, | ||
37 | + :subject => 'newsletter test', | ||
38 | + :person => fast_create(Person)) | ||
39 | + | ||
40 | + assert_difference 'NewsletterPlugin::NewsletterMailing.count', 1 do | ||
41 | + NewsletterPlugin.compile_and_send_newsletters | ||
42 | + end | ||
43 | + | ||
44 | + assert_equal 0, NewsletterPlugin::ModerateNewsletter.count | ||
45 | + end | ||
46 | + | ||
47 | + should 'use same environment locale on mailing' do | ||
48 | + NewsletterPlugin::Newsletter.create!( | ||
49 | + :environment => fast_create(Environment, :default_language => 'pt_BR'), | ||
50 | + :enabled => true, | ||
51 | + :subject => 'newsletter test', | ||
52 | + :person => fast_create(Person)) | ||
53 | + | ||
54 | + NewsletterPlugin.compile_and_send_newsletters | ||
55 | + assert_equal 'pt_BR', NewsletterPlugin::NewsletterMailing.last.locale | ||
56 | + end | ||
57 | + | ||
58 | + should 'create newsletter moderation task if newsletter is moderated' do | ||
59 | + adminuser = create_user.person | ||
60 | + Environment.any_instance.stubs(:admins).returns([adminuser]) | ||
61 | + | ||
62 | + NewsletterPlugin::Newsletter.create!( | ||
63 | + :environment => fast_create(Environment), | ||
64 | + :enabled => true, | ||
65 | + :moderated => true, | ||
66 | + :subject => 'newsletter test', | ||
67 | + :person => fast_create(Person)) | ||
68 | + | ||
69 | + assert_difference 'NewsletterPlugin::ModerateNewsletter.count', 1 do | ||
70 | + NewsletterPlugin.compile_and_send_newsletters | ||
71 | + end | ||
72 | + | ||
73 | + assert_equal 0, NewsletterPlugin::NewsletterMailing.count | ||
74 | + end | ||
75 | + | ||
76 | + should 'not create mailing if has no posts in the period' do | ||
77 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
78 | + :environment => fast_create(Environment), | ||
79 | + :person => fast_create(Person), | ||
80 | + :enabled => true | ||
81 | + ) | ||
82 | + NewsletterPlugin::Newsletter.any_instance.stubs(:must_be_sent_today?).returns(true) | ||
83 | + NewsletterPlugin::Newsletter.any_instance.stubs(:has_posts_in_the_period?).returns(false) | ||
84 | + assert_no_difference 'NewsletterPlugin::NewsletterMailing.count' do | ||
85 | + NewsletterPlugin.compile_and_send_newsletters | ||
86 | + end | ||
87 | + end | ||
88 | + | ||
89 | + should 'not create mailing if doesnt must be sent today' do | ||
90 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
91 | + :environment => fast_create(Environment), | ||
92 | + :person => fast_create(Person), | ||
93 | + :enabled => true | ||
94 | + ) | ||
95 | + NewsletterPlugin::Newsletter.any_instance.stubs(:must_be_sent_today?).returns(false) | ||
96 | + NewsletterPlugin::Newsletter.any_instance.stubs(:has_posts_in_the_period?).returns(true) | ||
97 | + assert_no_difference 'NewsletterPlugin::NewsletterMailing.count' do | ||
98 | + NewsletterPlugin.compile_and_send_newsletters | ||
99 | + end | ||
100 | + end | ||
101 | + | ||
102 | + should 'create mailing' do | ||
103 | + newsletter = NewsletterPlugin::Newsletter.create!( | ||
104 | + :environment => fast_create(Environment), | ||
105 | + :person => fast_create(Person), | ||
106 | + :enabled => true | ||
107 | + ) | ||
108 | + assert_difference 'NewsletterPlugin::NewsletterMailing.count' do | ||
109 | + NewsletterPlugin.compile_and_send_newsletters | ||
110 | + end | ||
111 | + end | ||
112 | + | ||
113 | +end |
plugins/newsletter/views/newsletter_plugin/mailing_not_found.html.erb
0 → 100644
plugins/newsletter/views/newsletter_plugin/unsubscribe.html.erb
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +<h1><%= _('Cancel newsletter subscription') %></h1> | ||
2 | + | ||
3 | +<h4> | ||
4 | +<%= _("I don't want to receive future newsletter emails from this network.") %> | ||
5 | +</h4> | ||
6 | + | ||
7 | +<%= _('Send an email to %s requesting your unsubscription or click on the button below.') % link_to(environment.contact_email, "mailto:#{environment.contact_email}?subject=#{_('Cancel newsletter subscription')}") %> | ||
8 | + | ||
9 | +<% button_bar do %> | ||
10 | + <%= button :ok, _('Confirm unsubscription'), {:action => 'confirm_unsubscription'}, :method => 'post' %> | ||
11 | +<% end %> |
plugins/newsletter/views/newsletter_plugin_admin/index.html.erb
0 → 100644
@@ -0,0 +1,92 @@ | @@ -0,0 +1,92 @@ | ||
1 | +<h1><%= _('Newsletter settings') %></h1> | ||
2 | + | ||
3 | +<%= render :file => 'shared/tiny_mce' %> | ||
4 | + | ||
5 | +<%= error_messages_for :newsletter %> | ||
6 | + | ||
7 | +<%= form_for(:newsletter, html: { multipart: true }) do |f| %> | ||
8 | + <%= labelled_form_field( | ||
9 | + content_tag('h3', hidden_field_tag('newsletter[enabled]', false) + | ||
10 | + f.check_box('enabled') + | ||
11 | + _('Enable send of newsletter to members on this environment'), :id => 'newsletter-enabled-field'), | ||
12 | + nil) | ||
13 | + %> | ||
14 | + | ||
15 | + <%= labelled_form_field( | ||
16 | + content_tag('span', hidden_field_tag('newsletter[moderated]', false) + f.check_box('moderated') + _('Moderate newsletter each time before sending to users.')), nil) | ||
17 | + %> | ||
18 | + | ||
19 | + <h2> | ||
20 | + <%= _('Content') %> | ||
21 | + </h2> | ||
22 | + | ||
23 | + <%= labelled_form_field( | ||
24 | + _('Period (in days) for news compilation'), f.number_field(:periodicity, min: '0')) | ||
25 | + %> | ||
26 | + | ||
27 | + <%= labelled_form_field( | ||
28 | + _('Number of posts compiled per blog (choose 0 for all posts since last newsletter)'), f.number_field(:posts_per_blog, min: '0')) | ||
29 | + %> | ||
30 | + | ||
31 | + <p><%= _('Blogs from which news will be compiled') %></p> | ||
32 | + <% search_action = url_for(:action => 'search_communities') %> | ||
33 | + <% selected_blogs = @blogs.map { |blog| {:id => blog.id, :name => _("%s in %s") % [blog.name, blog.profile.name]} } %> | ||
34 | + <%= token_input_field_tag( | ||
35 | + 'newsletter[blog_ids]', 'search-communities', search_action, | ||
36 | + { hint_text: _('Type in the communities\' or blogs\' names'), | ||
37 | + focus: false, pre_populate: selected_blogs }) %> | ||
38 | + | ||
39 | + <br/> | ||
40 | + | ||
41 | + <h2> | ||
42 | + <%= _('Recipients') %> | ||
43 | + </h2> | ||
44 | + | ||
45 | + <p> | ||
46 | + <%= _('You can follow the link below to see which e-mails are currently being used as additional recipients for this newsletter.') %> | ||
47 | + </p> | ||
48 | + <p> | ||
49 | + <%= link_to 'Currently set additional recipients', {action: :recipients}, target: '_blank' %> | ||
50 | + </p> | ||
51 | + | ||
52 | + <p><%= _('You can set additional e-mails to send the newsletter to in addition to all environment\'s users that already receive the newsletter by default. To do that, you need to upload a CSV file that contains a column for the person\'s or enterprise\'s name as well as a column with their e-mail.') %></p> | ||
53 | + | ||
54 | + <%= labelled_form_field( | ||
55 | + _('Additional recipients for newsletter'), file_field_tag('file[recipients]', accept: '.csv')) | ||
56 | + %> | ||
57 | + | ||
58 | + <div id='newsletter-file-options'> | ||
59 | + <%= labelled_form_field( | ||
60 | + content_tag('span', check_box_tag('file[headers]', 1, false, disabled: true) + _('The CSV file contains a header row')), nil) | ||
61 | + %> | ||
62 | + | ||
63 | + <%= labelled_form_field( | ||
64 | + _('Number of colunm with name field'), number_field_tag('file[name]', '1', min: '1', disabled: true)) | ||
65 | + %> | ||
66 | + | ||
67 | + <%= labelled_form_field( | ||
68 | + _('Number of colunm with email field'), number_field_tag('file[email]', '2', min: '1', disabled: true)) | ||
69 | + %> | ||
70 | + </div> | ||
71 | + | ||
72 | + <h2> | ||
73 | + <%= _('Layout') %> | ||
74 | + </h2> | ||
75 | + | ||
76 | + <%= f.fields_for :image_builder, @newsletter.image do |i| %> | ||
77 | + <%= file_field_or_thumbnail(_('Header image (images with 640px width):'), @newsletter.image, i) %> | ||
78 | + <% end %> | ||
79 | + | ||
80 | + <%= labelled_form_field( | ||
81 | + content_tag('h3', ui_icon('ui-icon-triangle-1-s') + | ||
82 | + _('Newsletter footer'), :class => 'newsletter-toggle-link', :element_id => '#newsletter-footer-field'), | ||
83 | + content_tag('div', | ||
84 | + f.text_area(:footer, :style => 'width: 100%', :class => 'mceEditor'), | ||
85 | + :id => 'newsletter-footer-field' | ||
86 | + )) | ||
87 | + %> | ||
88 | + <% button_bar do %> | ||
89 | + <%= submit_button :save, _('Save') %> | ||
90 | + <%= submit_button :save, _('Save and visualize'), :name => "visualize", :cancel => {:controller => 'plugins'} %> | ||
91 | + <% end %> | ||
92 | +<% end %> |
plugins/newsletter/views/newsletter_plugin_admin/recipients.html.erb
0 → 100644
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +<h1><%= _('Additional recipients') %></h1> | ||
2 | + | ||
3 | +<% if @additional_recipients.present? %> | ||
4 | + <table border="0" cellspacing="5" cellpadding="5"> | ||
5 | + <tr> | ||
6 | + <th><%= _('Name') %></th> | ||
7 | + <th><%= _('E-mail') %></th> | ||
8 | + </tr> | ||
9 | + <% @additional_recipients.each do |recipient| %> | ||
10 | + <tr> | ||
11 | + <td><%= recipient[:name] %></td> | ||
12 | + <td><%= recipient[:email] %></td> | ||
13 | + </tr> | ||
14 | + <% end %> | ||
15 | + </table> | ||
16 | +<% else %> | ||
17 | + <p><%= _('There are no additional recipients.') %></p> | ||
18 | +<% end %> | ||
19 | + | ||
20 | +<br/> | ||
21 | +<%= button :back, _('Back'), action: :index %> |
plugins/newsletter/views/tasks/newsletter_plugin/_moderate_newsletter_accept_details.html.erb
0 → 100644
@@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
1 | +<% newsletter = NewsletterPlugin::Newsletter.find(task.newsletter_id) %> | ||
2 | + | ||
3 | +<h1><%= _('Check posts you want to include') %></h1> | ||
4 | + | ||
5 | +<div id='newsletter-moderation-preview'> | ||
6 | + <% newsletter_content = newsletter.body.gsub(/width: 640px;/,'').sub(/#{NewsletterPlugin::Newsletter::CSS['breaking-news-wrap']}/, '') %> | ||
7 | + | ||
8 | + <% newsletter.posts.each do |post| %> | ||
9 | + <% input_name = "tasks[#{task.id}][task][post_ids][]" %> | ||
10 | + <% post_check_box = hidden_field_tag(input_name, '0') +check_box_tag(input_name, post.id, true) %> | ||
11 | + | ||
12 | + <% newsletter_content.gsub!(/<span id="#{post.id}"/, post_check_box+ '<span') %> | ||
13 | + <% newsletter_content.gsub!(/<img id="#{post.id}"/, post_check_box+ '<img') %> | ||
14 | + <% end %> | ||
15 | + | ||
16 | + <%= newsletter_content %> | ||
17 | +</div> |