Commit 3ce46bb6b85c5c1b001c3ee576b557255c40564b

Authored by Braulio Bhavamitra
2 parents 8bc107b4 47e5f189

Merge branch 'noosfero' into rails4

Showing 46 changed files with 2126 additions and 45 deletions   Show diff stats
.travis.yml
  1 +notifications:
  2 + irc:
  3 + channels:
  4 + - "chat.freenode.net#noosfero"
  5 + - "chat.freenode.net#noosfero-br"
  6 + template:
  7 + - "%{repository_slug} %{branch} %{commit} %{commit_subject} - %{result} %{build_url}"
  8 +
1 9 language: ruby
2 10 rvm:
3 11 - 2.2.3
... ...
app/mailers/mailing.rb
1   -require 'mailing_job'
  1 +require_dependency 'mailing_job'
2 2  
3 3 class Mailing < ActiveRecord::Base
4 4  
... ... @@ -40,10 +40,8 @@ class Mailing &lt; ActiveRecord::Base
40 40 begin
41 41 Mailing::Sender.notification(self, recipient.email).deliver
42 42 self.mailing_sents.create(:person => recipient)
43   - rescue Exception
44   - # FIXME should not discard errors silently. An idea is to collect all
45   - # errors and generate a task (notification) for the +source+
46   - # (environment/organization) listing these errors.
  43 + rescue Exception => ex
  44 + Rails.logger.error("#{ex.class.to_s} - #{ex.to_s} at #{__FILE__}:#{__LINE__}")
47 45 end
48 46 end
49 47 end
... ...
app/models/add_friend.rb
... ... @@ -14,8 +14,8 @@ class AddFriend &lt; Task
14 14 alias :friend :target
15 15 alias :friend= :target=
16 16  
17   - validates :requestor, :kind_of => { :kind => Person }
18   - validates :target, :kind_of => { :kind => Person }
  17 + validates :requestor, :kind_of => { :kind => Person }
  18 + validates :target, :kind_of => { :kind => Person }
19 19  
20 20 after_create do |task|
21 21 TaskMailer.invitation_notification(task).deliver unless task.friend
... ...
app/models/community.rb
1 1 class Community < Organization
2 2  
3   - attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type, :address_reference, :district, :tag_list, :language
  3 + attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type
  4 + attr_accessible :address_reference, :district, :tag_list, :language, :description
4 5 after_destroy :check_invite_member_for_destroy
5 6  
6 7 def self.type_name
... ...
app/models/create_community.rb
... ... @@ -9,11 +9,15 @@ class CreateCommunity &lt; Task
9 9 alias :environment :target
10 10 alias :environment= :target=
11 11  
  12 + attr_accessible :environment, :requestor, :target
  13 + attr_accessible :reject_explanation, :template_id
  14 +
12 15 acts_as_having_image
13 16  
14   - DATA_FIELDS = Community.fields + ['name', 'closed']
  17 + DATA_FIELDS = Community.fields + ['name', 'closed', 'description']
15 18 DATA_FIELDS.each do |field|
16 19 settings_items field.to_sym
  20 + attr_accessible field.to_sym
17 21 end
18 22  
19 23 def validate
... ...
app/models/event.rb
... ... @@ -114,7 +114,7 @@ class Event &lt; Article
114 114 end
115 115  
116 116 alias_method :article_lead, :lead
117   - def lead
  117 + def lead(length = nil)
118 118 self.class.action_view.render 'content_viewer/event_lead', event: self
119 119 end
120 120  
... ...
app/models/textile_article.rb
... ... @@ -12,7 +12,7 @@ class TextileArticle &lt; TextArticle
12 12 convert_to_html(body)
13 13 end
14 14  
15   - def lead
  15 + def lead(length = nil)
16 16 if abstract.blank?
17 17 super
18 18 else
... ...
app/views/mailing/sender/notification.html.erb
... ... @@ -3,7 +3,7 @@
3 3 <head>
4 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5 5 </head>
6   - <body>
  6 + <body style="margin: 0">
7 7 <%= word_wrap(@message) %>
8 8 <p>
9 9 --<br/>
... ...
config/schedule.rb
... ... @@ -28,3 +28,15 @@ end
28 28 every 30.days do
29 29 runner "ProfileSuggestion.generate_all_profile_suggestions"
30 30 end
  31 +
  32 +# Loads "schedule.rb" files from plugins
  33 +#
  34 +# Allows Noosfero's plugins schedule jobs using `whenever` Ruby gem the same
  35 +# way we do here, just create the file "config/schedule.rb" into the plugin
  36 +# root directory and write jobs using the same syntax used here (see example in
  37 +# the `newsletter` plugin)
  38 +
  39 +Dir.glob("config/plugins/*/config/schedule.rb").each do |filename|
  40 + filecontent = IO.read(filename)
  41 + instance_eval(Whenever::NumericSeconds.process_string(filecontent), filename)
  42 +end
... ...
features/create_community.feature
... ... @@ -39,44 +39,47 @@ Feature: create community
39 39 Then I should see "Creating new community"
40 40  
41 41 Scenario: environment admin receive a task when a user creates a community
42   - Given I am logged in as admin
  42 + Given I am logged in as "joaosilva"
43 43 And feature "admin_must_approve_new_communities" is enabled on environment
44   - When I create community "Community for approval"
  44 + Given "joaosilva" creates the community "Community for approval"
  45 + Given I am logged in as admin
45 46 And I go to admin_user's control panel
46   - Then I should see "admin_user wants to create community Community for approval"
  47 + Then I should see "Joao Silva wants to create community Community for approval"
47 48  
48 49 Scenario: environment admin accepts new community task
49   - Given I am logged in as admin
  50 + Given I am logged in as "joaosilva"
50 51 And feature "admin_must_approve_new_communities" is enabled on environment
51   - When I create community "Community for approval"
  52 + Given "joaosilva" creates the community "Community for approval"
  53 + Given I am logged in as admin
52 54 And I go to admin_user's control panel
53 55 And I follow "Process requests"
54   - And I should see "admin_user wants to create community Community for approval"
  56 + And I should see "Joao Silva wants to create community Community for approval"
55 57 And I choose "Accept"
56 58 When I press "Apply!"
57   - Then I should not see "admin_user wants to create community Community for approval"
58   - And I go to admin_user's control panel
  59 + Then I should not see "Joao Silva wants to create community Community for approval"
  60 + And I go to joaosilva's control panel
59 61 And I follow "Manage my groups"
60 62 Then I should see "Community for approval"
61 63  
62 64 Scenario: environment admin rejects new community task
63   - Given I am logged in as admin
  65 + Given I am logged in as "joaosilva"
64 66 And feature "admin_must_approve_new_communities" is enabled on environment
65   - When I create community "Community for approval"
  67 + Given "joaosilva" creates the community "Community for approval"
  68 + Given I am logged in as admin
66 69 And I go to admin_user's control panel
67 70 And I follow "Process requests"
68   - And I should see "admin_user wants to create community Community for approval"
  71 + And I should see "Joao Silva wants to create community Community for approval"
69 72 And I choose "Reject"
70 73 When I press "Apply!"
71   - Then I should not see "admin_user wants to create community Community for approval"
72   - And I go to admin_user's control panel
  74 + Then I should not see "Joao Silva wants to create community Community for approval"
  75 + And I go to joaosilva's control panel
73 76 And I follow "Manage my groups"
74 77 Then I should not see "Community for approval"
75 78  
76 79 Scenario: new community is listed after approval
77 80 Given I am logged in as admin
78 81 And feature "admin_must_approve_new_communities" is enabled on environment
79   - When I create community "Community for approval"
  82 + Given "admin_user" creates the community "Community for approval"
80 83 And I approve community "Community for approval"
81 84 And I go to admin_user's control panel
82 85 And I follow "Manage my groups"
... ... @@ -85,8 +88,9 @@ Feature: create community
85 88 Scenario: new community is not listed after rejection
86 89 Given I am logged in as admin
87 90 And feature "admin_must_approve_new_communities" is enabled on environment
88   - When I create community "Community for approval"
  91 + Given "admin_user" creates the community "Community for approval"
89 92 And I reject community "Community for approval"
90 93 And I go to admin_user's control panel
91 94 And I follow "Manage my groups"
92 95 Then I should not see "Community for approval"
  96 +
... ...
features/step_definitions/create_community_steps.rb
... ... @@ -8,6 +8,14 @@ Given /^I create community &quot;(.+)&quot;$/ do |community|
8 8 click_button("Create")
9 9 end
10 10  
  11 +Given /^"(.+)" creates the community "(.+)"$/ do |username, community|
  12 + When %{I go to #{username}'s control panel}
  13 + click_link('Manage my groups')
  14 + click_link('Create a new community')
  15 + fill_in("Name", :with => community)
  16 + click_button("Create")
  17 +end
  18 +
11 19 Given /^I approve community "(.+)"$/ do |community|
12 20 task = CreateCommunity.all.select {|c| c.name == community}.first
13 21 step %{I go to admin_user's control panel}
... ...
lib/acts_as_having_image.rb
... ... @@ -5,7 +5,8 @@ module ActsAsHavingImage
5 5 belongs_to :image, dependent: :destroy
6 6 scope :with_image, -> { where "#{table_name}.image_id IS NOT NULL" }
7 7 scope :without_image, -> { where "#{table_name}.image_id IS NULL" }
8   - self.send(:include, ActsAsHavingImage)
  8 + attr_accessible :image_builder
  9 + include ActsAsHavingImage
9 10 end
10 11 end
11 12  
... ...
plugins/newsletter/config/schedule.rb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +every 1.day do
  2 + runner "NewsletterPlugin.compile_and_send_newsletters"
  3 +end
... ...
plugins/newsletter/controllers/newsletter_plugin_admin_controller.rb 0 → 100644
... ... @@ -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 @@
  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 @@
  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
... ...
plugins/newsletter/features/newsletter_plugin.feature 0 → 100644
... ... @@ -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"
... ...
plugins/newsletter/lib/newsletter_plugin.rb 0 → 100644
... ... @@ -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 @@
  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
... ...
plugins/newsletter/lib/newsletter_plugin/newsletter.rb 0 → 100644
... ... @@ -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 @@
  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
... ...
plugins/newsletter/public/newsletter_plugin.js 0 → 100644
... ... @@ -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 +});
... ...
plugins/newsletter/public/style.css 0 → 100644
... ... @@ -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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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
... ...
plugins/newsletter/test/unit/newsletter_plugin_test.rb 0 → 100644
... ... @@ -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
... ... @@ -0,0 +1,3 @@
  1 +<h2><%= _("Mailing not found") %></h2>
  2 +
  3 +<p><%= _("There is no mailing with id #%s") % params[:id] %></p>
... ...
plugins/newsletter/views/newsletter_plugin/unsubscribe.html.erb 0 → 100644
... ... @@ -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 @@
  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 @@
  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 @@
  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>
... ...
plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb
... ... @@ -12,7 +12,7 @@ class OrganizationRatingsPluginProfileController &lt; ProfileController
12 12 if @rating_available
13 13 create_new_rate
14 14 else
15   - session[:notice] = _("You can not vote on this %s") % profile.class.name
  15 + session[:notice] = _("You can not vote on this %s") % _(profile.class.name)
16 16 end
17 17 end
18 18 end
... ...
plugins/organization_ratings/lib/create_organization_rating_comment.rb
... ... @@ -63,7 +63,7 @@ class CreateOrganizationRatingComment &lt; Task
63 63  
64 64 def information
65 65 message = _("<a href=%{requestor_url}>%{requestor}</a> wants to create a comment in this %{target_class}") %
66   - {:requestor_url => url_for(self.requestor.url), :requestor => self.requestor.name, :target_class => self.target.class.name.downcase}
  66 + {:requestor_url => url_for(self.requestor.url), :requestor => self.requestor.name, :target_class => _(self.target.class.name)}
67 67  
68 68 {:message => message}
69 69 end
... ... @@ -88,20 +88,20 @@ class CreateOrganizationRatingComment &lt; Task
88 88  
89 89 def target_notification_description
90 90 _("%{requestor} wants to create a comment in this \"%{target}\"") %
91   - {:requestor => self.requestor.name, :target => self.target.class.name.downcase }
  91 + {:requestor => self.requestor.name, :target => _(self.target.class.name.downcase) }
92 92 end
93 93  
94 94 def target_notification_message
95   - _("User \"%{user}\" just requested to create a comment in the %{target_class}
  95 + _("User \"%{user}\" requested to create a comment in the %{target_class}
96 96 \"%{target_name}\".
97 97 You have to approve or reject it through the \"Pending Validations\"
98 98 section in your control panel.\n") %
99   - { :user => self.requestor.name, :target_class => self.target.class.name.downcase, :target_name => self.target.name }
  99 + { :user => self.requestor.name, :target_class => _(self.target.class.name.downcase), :target_name => self.target.name }
100 100 end
101 101  
102 102 def task_created_message
103 103 _("Your request for commenting at %{target} was
104   - just sent. Environment administrator will receive it and will approve or
  104 + just sent. The administrator will receive it and will approve or
105 105 reject your request according to his methods and criteria.
106 106 You will be notified as soon as environment administrator has a position
107 107 about your request.") %
... ... @@ -110,16 +110,16 @@ class CreateOrganizationRatingComment &lt; Task
110 110  
111 111 def task_cancelled_message
112 112 _("Your request for commenting at %{target} was
113   - not approved by the environment administrator. The following explanation
  113 + not approved by the administrator. The following explanation
114 114 was given: \n\n%{explanation}") %
115 115 { :target => self.target.name,
116 116 :explanation => self.reject_explanation }
117 117 end
118 118  
119 119 def task_finished_message
120   - _('Your request for commenting was approved.
  120 + _('Your request for commenting at %{target} was approved.
121 121 You can access %{url} to see your comment.') %
122   - { :url => ratings_url }
  122 + { :target => self.target.name, :url => ratings_url }
123 123 end
124 124  
125 125 private
... ...
plugins/organization_ratings/lib/organization_ratings_block.rb
... ... @@ -6,7 +6,7 @@ class OrganizationRatingsBlock &lt; Block
6 6 end
7 7  
8 8 def help
9   - _('This block displays the community ratings.')
  9 + _('This block displays the organization ratings.')
10 10 end
11 11  
12 12 def content(args = {})
... ...
plugins/organization_ratings/po/organization_ratings.pot 0 → 100644
... ... @@ -0,0 +1,250 @@
  1 +# SOME DESCRIPTIVE TITLE.
  2 +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
  3 +# This file is distributed under the same license as the PACKAGE package.
  4 +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
  5 +#
  6 +#, fuzzy
  7 +msgid ""
  8 +msgstr ""
  9 +"Project-Id-Version: 1.2-478-gee4ad04\n"
  10 +"POT-Creation-Date: 2015-09-11 18:11-0300\n"
  11 +"PO-Revision-Date: 2015-09-11 18:56-0000\n"
  12 +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  13 +"Language-Team: LANGUAGE <LL@li.org>\n"
  14 +"Language: \n"
  15 +"MIME-Version: 1.0\n"
  16 +"Content-Type: text/plain; charset=UTF-8\n"
  17 +"Content-Transfer-Encoding: 8bit\n"
  18 +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
  19 +
  20 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:31
  21 +msgid "Comment waiting for approval"
  22 +msgstr ""
  23 +
  24 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:48
  25 +msgid "Comment rejected"
  26 +msgstr ""
  27 +
  28 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:52
  29 +#: plugins/organization_ratings/views/shared/_user_rating_container.html.erb:28
  30 +msgid "No comment"
  31 +msgstr ""
  32 +
  33 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:61
  34 +msgid "New Comment"
  35 +msgstr ""
  36 +
  37 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:65
  38 +msgid ""
  39 +"<a href=%{requestor_url}>%{requestor}</a> wants to create a comment in this "
  40 +"%{target_class}"
  41 +msgstr ""
  42 +
  43 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:90
  44 +msgid "%{requestor} wants to create a comment in this \"%{target}\""
  45 +msgstr ""
  46 +
  47 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:95
  48 +msgid ""
  49 +"User \"%{user}\" requested to create a comment in the %{target_class}\n"
  50 +" \"%{target_name}\".\n"
  51 +" You have to approve or reject it through the \"Pending Validations\"\n"
  52 +" section in your control panel.\n"
  53 +msgstr ""
  54 +
  55 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:103
  56 +msgid ""
  57 +"Your request for commenting at %{target} was\n"
  58 +" just sent. The administrator will receive it and will approve or\n"
  59 +" reject your request according to his methods and criteria.\n"
  60 +" You will be notified as soon as environment administrator has a "
  61 +"position\n"
  62 +" about your request."
  63 +msgstr ""
  64 +
  65 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:112
  66 +msgid ""
  67 +"Your request for commenting at %{target} was\n"
  68 +" not approved by the administrator. The following explanation\n"
  69 +" was given: \n"
  70 +"\n"
  71 +"%{explanation}"
  72 +msgstr ""
  73 +
  74 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:120
  75 +msgid ""
  76 +"Your request for commenting at %{target} was approved.\n"
  77 +" You can access %{url} to see your comment."
  78 +msgstr ""
  79 +
  80 +#: plugins/organization_ratings/lib/organization_ratings_config.rb:8
  81 +msgid "More Recent"
  82 +msgstr ""
  83 +
  84 +#: plugins/organization_ratings/lib/organization_ratings_config.rb:8
  85 +msgid "Best Ratings"
  86 +msgstr ""
  87 +
  88 +#: plugins/organization_ratings/lib/organization_ratings_block.rb:5
  89 +msgid "Organization Ratings"
  90 +msgstr ""
  91 +
  92 +#: plugins/organization_ratings/lib/organization_ratings_block.rb:9
  93 +msgid "This block displays the organization ratings."
  94 +msgstr ""
  95 +
  96 +#: plugins/organization_ratings/lib/average_rating_block.rb:5
  97 +msgid "Organization Average Rating"
  98 +msgstr ""
  99 +
  100 +#: plugins/organization_ratings/lib/average_rating_block.rb:9
  101 +msgid "This block displays the organization average rating."
  102 +msgstr ""
  103 +
  104 +#: plugins/organization_ratings/lib/organization_ratings_plugin.rb:9
  105 +msgid "A plugin that allows you to rate a organization and comment about it."
  106 +msgstr ""
  107 +
  108 +#: plugins/organization_ratings/lib/organization_rating.rb:10
  109 +msgid "must be between 1 and 5"
  110 +msgstr ""
  111 +
  112 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_admin_controller.rb:12
  113 +msgid "Configuration updated successfully."
  114 +msgstr ""
  115 +
  116 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_admin_controller.rb:14
  117 +msgid "Configuration could not be saved."
  118 +msgstr ""
  119 +
  120 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb:15
  121 +msgid "You can not vote on this %s"
  122 +msgstr ""
  123 +
  124 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb:47
  125 +msgid "%s successfully rated!"
  126 +msgstr ""
  127 +
  128 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb:49
  129 +msgid "Sorry, there were problems rating this profile."
  130 +msgstr ""
  131 +
  132 +#: plugins/organization_ratings/views/shared/_make_report_block.html.erb:11
  133 +msgid "User not logged"
  134 +msgstr ""
  135 +
  136 +#: plugins/organization_ratings/views/shared/_make_report_block.html.erb:17
  137 +msgid "Report your experiences."
  138 +msgstr ""
  139 +
  140 +#: plugins/organization_ratings/views/shared/_make_report_block.html.erb:24
  141 +msgid "* You must be logged in to submit a report."
  142 +msgstr ""
  143 +
  144 +#: plugins/organization_ratings/views/shared/_rating_button.html.erb:3
  145 +msgid "Rate %s "
  146 +msgstr ""
  147 +
  148 +#: plugins/organization_ratings/views/shared/_rating_button.html.erb:7
  149 +msgid "Log in"
  150 +msgstr ""
  151 +
  152 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:3
  153 +msgid "Organization Rating Settings"
  154 +msgstr ""
  155 +
  156 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:10
  157 +msgid "Value"
  158 +msgstr ""
  159 +
  160 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:13
  161 +msgid "Default amount of stars marked on evaluations"
  162 +msgstr ""
  163 +
  164 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:17
  165 +msgid "Users can rate an organization only once"
  166 +msgstr ""
  167 +
  168 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:21
  169 +msgid "The comments are moderated"
  170 +msgstr ""
  171 +
  172 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:26
  173 +msgid "Time in hours between evaluations from the same user."
  174 +msgstr ""
  175 +
  176 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:27
  177 +msgid "To disable cooldown use zero (0) value."
  178 +msgstr ""
  179 +
  180 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:35
  181 +msgid "Order ratings by"
  182 +msgstr ""
  183 +
  184 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:41
  185 +msgid "Ratings amount per page"
  186 +msgstr ""
  187 +
  188 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:50
  189 +msgid "Back"
  190 +msgstr ""
  191 +
  192 +#: plugins/organization_ratings/views/tasks/_create_organization_rating_comment_accept_details.html.erb:2
  193 +msgid "Comment:"
  194 +msgstr ""
  195 +
  196 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:39
  197 +msgid "Rated as"
  198 +msgstr ""
  199 +
  200 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:39
  201 +msgid "stars"
  202 +msgstr ""
  203 +
  204 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:46
  205 +msgid "Comment (Optional):"
  206 +msgstr ""
  207 +
  208 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:53
  209 +msgid "Save"
  210 +msgstr ""
  211 +
  212 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:63
  213 +msgid "Hi, %s! The administrators set that you can vote"
  214 +msgstr ""
  215 +
  216 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:64
  217 +msgid "only once"
  218 +msgstr ""
  219 +
  220 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:65
  221 +msgid "for this %s."
  222 +msgstr ""
  223 +
  224 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:70
  225 +msgid "Hi, %s! The administrators set the minimum time of"
  226 +msgstr ""
  227 +
  228 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:71
  229 +msgid "%s hour(s)"
  230 +msgstr ""
  231 +
  232 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:72
  233 +msgid "between each evaluation."
  234 +msgstr ""
  235 +
  236 +#: plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb:4
  237 +msgid "Rating: "
  238 +msgstr ""
  239 +
  240 +#: plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb:18
  241 +msgid "Be the first to rate!"
  242 +msgstr ""
  243 +
  244 +#: plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb:23
  245 +msgid "Rate this %s"
  246 +msgstr ""
  247 +
  248 +#: plugins/organization_ratings/views/blocks/organization_ratings_block.html.erb:17
  249 +msgid "See more"
  250 +msgstr ""
... ...
plugins/organization_ratings/po/pt/organization_ratings.po 0 → 100644
... ... @@ -0,0 +1,274 @@
  1 +# SOME DESCRIPTIVE TITLE.
  2 +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
  3 +# This file is distributed under the same license as the PACKAGE package.
  4 +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
  5 +#
  6 +#, fuzzy
  7 +msgid ""
  8 +msgstr ""
  9 +"Project-Id-Version: 1.2-478-gee4ad04\n"
  10 +"POT-Creation-Date: 2015-09-11 18:11-0300\n"
  11 +"PO-Revision-Date: 2015-09-11 18:56-0000\n"
  12 +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  13 +"Language-Team: LANGUAGE <LL@li.org>\n"
  14 +"Language: \n"
  15 +"MIME-Version: 1.0\n"
  16 +"Content-Type: text/plain; charset=UTF-8\n"
  17 +"Content-Transfer-Encoding: 8bit\n"
  18 +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
  19 +
  20 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:31
  21 +msgid "Comment waiting for approval"
  22 +msgstr "Comentario aguardando aprovação"
  23 +
  24 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:48
  25 +msgid "Comment rejected"
  26 +msgstr "Comentário rejeitado"
  27 +
  28 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:52
  29 +#: plugins/organization_ratings/views/shared/_user_rating_container.html.erb:28
  30 +msgid "No comment"
  31 +msgstr "Sem comentário"
  32 +
  33 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:61
  34 +msgid "New Comment"
  35 +msgstr "Novo Comentário"
  36 +
  37 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:65
  38 +msgid ""
  39 +"<a href=%{requestor_url}>%{requestor}</a> wants to create a comment in this "
  40 +"%{target_class}"
  41 +msgstr ""
  42 +"<a href=%{requestor_url}>%{requestor}</a> deseja criar um comentário "
  43 +"neste(a) %{target_class}"
  44 +
  45 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:90
  46 +msgid "%{requestor} wants to create a comment in this \"%{target}\""
  47 +msgstr "%{requestor} deseja criar um comentário neste(a) \"%{target}\""
  48 +
  49 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:95
  50 +msgid ""
  51 +"User \"%{user}\" requested to create a comment in the %{target_class}\n"
  52 +" \"%{target_name}\".\n"
  53 +" You have to approve or reject it through the \"Pending Validations\"\n"
  54 +" section in your control panel.\n"
  55 +msgstr ""
  56 +"O usuário \"%{user}\" requisitou a criação de um comentário na "
  57 +"%{target_class}\n"
  58 +" \"%{target_name}\".\n"
  59 +" Você deve aprová-lo ou rejeitá-lo através da seção de \"Validações "
  60 +"Pendentes\"\n"
  61 +" no seu painel de controle.\n"
  62 +
  63 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:103
  64 +msgid ""
  65 +"Your request for commenting at %{target} was\n"
  66 +" just sent. The administrator will receive it and will approve or\n"
  67 +" reject your request according to his methods and criteria.\n"
  68 +" You will be notified as soon as environment administrator has a "
  69 +"position\n"
  70 +" about your request."
  71 +msgstr ""
  72 +"Seu pedido para comentar em %{target} foi\n"
  73 +" enviado. O administrador irá recebê-lo e aprovarou\n"
  74 +" rejeitar seu pedido de acordo com seus métodos e critérios.\n"
  75 +" Você será notificado assim que o administrador tenha umaposição\n"
  76 +" sobre seu pedido."
  77 +
  78 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:112
  79 +msgid ""
  80 +"Your request for commenting at %{target} was\n"
  81 +" not approved by the administrator. The following explanation\n"
  82 +" was given: \n"
  83 +"\n"
  84 +"%{explanation}"
  85 +msgstr ""
  86 +"Seu pedido para comentar em %{target} não\n"
  87 +" foi aprovado pelo administrador. A seguinte explicação\n"
  88 +" foi dada: \n"
  89 +"\n"
  90 +"%{explanation}"
  91 +
  92 +#: plugins/organization_ratings/lib/create_organization_rating_comment.rb:120
  93 +msgid ""
  94 +"Your request for commenting at %{target} was approved.\n"
  95 +" You can access %{url} to see your comment."
  96 +msgstr ""
  97 +"Seu pedido para comentar em %{target} foi aprovado.\n"
  98 +"\tVocê pode acessar %{url} para ver seu comentário."
  99 +
  100 +#: plugins/organization_ratings/lib/organization_ratings_config.rb:8
  101 +msgid "More Recent"
  102 +msgstr "Mais Recentes"
  103 +
  104 +#: plugins/organization_ratings/lib/organization_ratings_config.rb:8
  105 +msgid "Best Ratings"
  106 +msgstr "Melhores Avaliações"
  107 +
  108 +#: plugins/organization_ratings/lib/organization_ratings_block.rb:5
  109 +msgid "Organization Ratings"
  110 +msgstr "Avaliações da Organização"
  111 +
  112 +#: plugins/organization_ratings/lib/organization_ratings_block.rb:9
  113 +msgid "This block displays the organization ratings."
  114 +msgstr "Este bloco mostra as avaliações da organização."
  115 +
  116 +#: plugins/organization_ratings/lib/average_rating_block.rb:5
  117 +msgid "Organization Average Rating"
  118 +msgstr "Média de Avaliações da Organização"
  119 +
  120 +#: plugins/organization_ratings/lib/average_rating_block.rb:9
  121 +msgid "This block displays the organization average rating."
  122 +msgstr "Este bloco mostra a média de avaliações da organização."
  123 +
  124 +#: plugins/organization_ratings/lib/organization_ratings_plugin.rb:9
  125 +msgid "A plugin that allows you to rate a organization and comment about it."
  126 +msgstr ""
  127 +"Um plugin que permite que você avalie uma organização e comente sobre ela."
  128 +
  129 +#: plugins/organization_ratings/lib/organization_rating.rb:10
  130 +msgid "must be between 1 and 5"
  131 +msgstr "deve ser entre 1 e 5"
  132 +
  133 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_admin_controller.rb:12
  134 +msgid "Configuration updated successfully."
  135 +msgstr "Configurações atualizadas com sucesso."
  136 +
  137 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_admin_controller.rb:14
  138 +msgid "Configuration could not be saved."
  139 +msgstr "Configurações não puderam ser salvas."
  140 +
  141 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb:15
  142 +msgid "You can not vote on this %s"
  143 +msgstr "Você não pode votar nesta %s"
  144 +
  145 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb:47
  146 +msgid "%s successfully rated!"
  147 +msgstr "%s avaliada com sucesso!"
  148 +
  149 +#: plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb:49
  150 +msgid "Sorry, there were problems rating this profile."
  151 +msgstr "Desculpe, ocorreram problemas na avaliação deste perfil."
  152 +
  153 +#: plugins/organization_ratings/views/shared/_make_report_block.html.erb:11
  154 +msgid "User not logged"
  155 +msgstr "Usuário não logado"
  156 +
  157 +#: plugins/organization_ratings/views/shared/_make_report_block.html.erb:17
  158 +msgid "Report your experiences."
  159 +msgstr "Relate suas experiências."
  160 +
  161 +#: plugins/organization_ratings/views/shared/_make_report_block.html.erb:24
  162 +msgid "* You must be logged in to submit a report."
  163 +msgstr "* Você precisa estar logado para enviar um relato."
  164 +
  165 +#: plugins/organization_ratings/views/shared/_rating_button.html.erb:3
  166 +msgid "Rate %s "
  167 +msgstr "Avaliar %s "
  168 +
  169 +#: plugins/organization_ratings/views/shared/_rating_button.html.erb:7
  170 +msgid "Log in"
  171 +msgstr "Entrar"
  172 +
  173 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:3
  174 +msgid "Organization Rating Settings"
  175 +msgstr "Configuração para Avaliações em Organizações"
  176 +
  177 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:10
  178 +msgid "Value"
  179 +msgstr "Valor"
  180 +
  181 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:13
  182 +msgid "Default amount of stars marked on evaluations"
  183 +msgstr "Quantidade padrão de estrelas marcadas nas avaliações"
  184 +
  185 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:17
  186 +msgid "Users can rate an organization only once"
  187 +msgstr "Usuários podem avaliar uma organização apenas uma vez"
  188 +
  189 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:21
  190 +msgid "The comments are moderated"
  191 +msgstr "Os comentários são moderados"
  192 +
  193 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:26
  194 +msgid "Time in hours between evaluations from the same user."
  195 +msgstr "Tempo em horas entre avaliações do mesmo usuário."
  196 +
  197 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:27
  198 +msgid "To disable cooldown use zero (0) value."
  199 +msgstr "Bara desabilitar o tempo de espera utilize o valor zero (0)."
  200 +
  201 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:35
  202 +msgid "Order ratings by"
  203 +msgstr "Ordenar avaliações por"
  204 +
  205 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:41
  206 +msgid "Ratings amount per page"
  207 +msgstr "Quantidade de avaliações por página"
  208 +
  209 +#: plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb:50
  210 +msgid "Back"
  211 +msgstr "Voltar"
  212 +
  213 +#: plugins/organization_ratings/views/tasks/_create_organization_rating_comment_accept_details.html.erb:2
  214 +msgid "Comment:"
  215 +msgstr "Comentário:"
  216 +
  217 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:39
  218 +msgid "Rated as"
  219 +msgstr "Avaliado em"
  220 +
  221 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:39
  222 +msgid "stars"
  223 +msgstr "estrelas"
  224 +
  225 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:46
  226 +msgid "Comment (Optional):"
  227 +msgstr "Comentário (Opcional):"
  228 +
  229 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:53
  230 +msgid "Save"
  231 +msgstr "Salvar"
  232 +
  233 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:63
  234 +msgid "Hi, %s! The administrators set that you can vote"
  235 +msgstr "Olá, %s! Os administradores configuraram que você pode votar apenas"
  236 +
  237 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:64
  238 +msgid "only once"
  239 +msgstr "uma vez"
  240 +
  241 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:65
  242 +msgid "for this %s."
  243 +msgstr "para esta %s."
  244 +
  245 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:70
  246 +msgid "Hi, %s! The administrators set the minimum time of"
  247 +msgstr "Olá, %s! Os administradores configuraram o tempo mínimo de "
  248 +
  249 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:71
  250 +msgid "%s hour(s)"
  251 +msgstr "%s hora(s)"
  252 +
  253 +#: plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb:72
  254 +msgid "between each evaluation."
  255 +msgstr "entre cada avaliação."
  256 +
  257 +#: plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb:4
  258 +msgid "Rating: "
  259 +msgstr "Avaliação:"
  260 +
  261 +#: plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb:18
  262 +msgid "Be the first to rate!"
  263 +msgstr "Seja o primeiro a avaliar!"
  264 +
  265 +#: plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb:23
  266 +msgid "Rate this %s"
  267 +msgstr "Avalie esta %s"
  268 +
  269 +#: plugins/organization_ratings/views/blocks/organization_ratings_block.html.erb:17
  270 +msgid "See more"
  271 +msgstr "Veja mais"
  272 +
  273 +#~ msgid "community"
  274 +#~ msgstr "comunidade"
... ...
plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb
... ... @@ -20,6 +20,6 @@
20 20 <% end %>
21 21  
22 22 <div class="rate-this-organization">
23   - <%= link_to _("Rate this %s" % profile.class.name), url_for(:controller => "organization_ratings_plugin_profile", :action => "new_rating", :profile=>profile_identifier) %>
  23 + <%= link_to _("Rate this %s" % _(profile.class.name)), url_for(:controller => "organization_ratings_plugin_profile", :action => "new_rating", :profile=>profile_identifier) %>
24 24 </div>
25 25 </div>
26 26 \ No newline at end of file
... ...
plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb
1 1 <% config = env_organization_ratings_config %>
2 2  
3   -<h1><%= _("Organization Rating Management") %> </h1>
  3 +<h1><%= _("Organization Rating Settings") %> </h1>
4 4  
5 5 <%= labelled_form_for(:organization_ratings_config, :url => {:action => 'update'}) do |f| %>
6 6 <%= labelled_fields_for(:organization_ratings_config, config) do |c| %>
... ... @@ -14,7 +14,7 @@
14 14 <td><%= c.select :default_rating, (config.minimum_ratings)..5 %></td>
15 15 </tr>
16 16 <tr>
17   - <td><%= _('Can rate an organization only once') %></td>
  17 + <td><%= _('Users can rate an organization only once') %></td>
18 18 <td><%= c.check_box :vote_once %></td>
19 19 </tr>
20 20 <tr>
... ... @@ -38,7 +38,7 @@
38 38 <td><%= c.select :order, order_options %></td>
39 39 </tr>
40 40 <tr>
41   - <td><%= _('Ratings per page') %></td>
  41 + <td><%= _('Ratings amount per page') %></td>
42 42 <td>
43 43 <%= c.select :per_page, 5..20 %>
44 44 </td>
... ...
plugins/organization_ratings/views/shared/_make_report_block.html.erb
... ... @@ -8,7 +8,7 @@
8 8 </div>
9 9  
10 10 <div class="star-profile-name">
11   - <%= logged_in? ? current_user.person.name : _('User not logged *') %>
  11 + <%= logged_in? ? current_user.person.name : _('User not logged') %>
12 12 </div>
13 13 </div>
14 14  
... ...
plugins/organization_ratings/views/shared/_rating_button.html.erb
1 1 <% button_bar do %>
2 2 <% if logged_in? %>
3   - <%= button(:new,_("Rate %s ") % profile.class.name,
  3 + <%= button(:new,_("Rate %s ") % _(profile.class.name),
4 4 {:controller => "organization_ratings_plugin_profile",
5 5 :action => "new_rating"}) %>
6 6 <% else %>
... ...
script/quick-start
... ... @@ -122,6 +122,7 @@ fi
122 122  
123 123 # create needed directory
124 124 mkdir -p tmp/pids
  125 +mkdir -p tmp/cache
125 126  
126 127 # use default gitignore rules
127 128 if [ ! -f .gitignore ]; then
... ...
script/sample-articles
... ... @@ -65,3 +65,22 @@ for subject in EVENT_SUBJECTS
65 65 end
66 66 end
67 67 done
  68 +
  69 +print "Creating some posts: "
  70 +for subject in SUBJECTS
  71 + rand(20).times do |i|
  72 + profile = profiles.sample
  73 + name = "%s #{subject}" % profile.name
  74 + article = TinyMceArticle.new(
  75 + :name => name,
  76 + :body => name,
  77 + :tag_list => [TAGS.sample, TAGS.sample],
  78 + :profile => profile,
  79 + :parent_id => profile.blog.id
  80 + )
  81 + save article do
  82 + article.add_category categories.sample
  83 + end
  84 + end
  85 +end
  86 +done
... ...
util/debian-install/install
... ... @@ -93,7 +93,7 @@ fi
93 93  
94 94 apt-get update
95 95 apt-get dist-upgrade -qy
96   -apt-get install -qy postgresql
  96 +apt-get install -qy postgresql postfix
97 97  
98 98 apt-cache policy noosfero
99 99 apt-get install -qy noosfero noosfero-apache
... ...