Commit 9247134c95a52f102fad0eef9fd2bab40247ab9c

Authored by Leandro Santos
2 parents e502c6c0 4615d072
Exists in staging and in 1 other branch production

Merge branch 'master' into staging

Showing 84 changed files with 524 additions and 190 deletions   Show diff stats
app/api/helpers.rb
... ... @@ -331,12 +331,12 @@ module Api
331 331 end
332 332  
333 333 def cant_be_saved_request!(attribute)
334   - message = _("(Invalid request) %s can't be saved") % attribute
  334 + message = _("(Invalid request) %s can't be saved").html_safe % attribute
335 335 render_api_error!(message, 400)
336 336 end
337 337  
338 338 def bad_request!(attribute)
339   - message = _("(Invalid request) %s not given") % attribute
  339 + message = _("(Invalid request) %s not given").html_safe % attribute
340 340 render_api_error!(message, 400)
341 341 end
342 342  
... ...
app/controllers/admin/categories_controller.rb
... ... @@ -44,7 +44,7 @@ class CategoriesController < AdminController
44 44 if request.post?
45 45 @category.update!(params[:category])
46 46 @saved = true
47   - session[:notice] = _("Category %s saved." % @category.name)
  47 + session[:notice] = _("Category %s saved." % @category.name).html_safe
48 48 redirect_to :action => 'index'
49 49 end
50 50 rescue Exception => e
... ...
app/controllers/box_organizer_controller.rb
... ... @@ -109,7 +109,7 @@ class BoxOrganizerController < ApplicationController
109 109 def show_block_type_info
110 110 type = params[:type]
111 111 if type.blank? || !available_blocks.map(&:name).include?(type)
112   - raise ArgumentError.new("Type %s is not allowed. Go away." % type)
  112 + raise ArgumentError.new("Type %s is not allowed. Go away.".html_safe % type)
113 113 end
114 114 @block = type.constantize.new
115 115 @block.box = Box.new(:owner => boxes_holder)
... ... @@ -122,7 +122,7 @@ class BoxOrganizerController < ApplicationController
122 122  
123 123 def new_block(type, box)
124 124 if !available_blocks.map(&:name).include?(type)
125   - raise ArgumentError.new("Type %s is not allowed. Go away." % type)
  125 + raise ArgumentError.new("Type %s is not allowed. Go away.".html_safe % type)
126 126 end
127 127 block = type.constantize.new
128 128 box.blocks << block
... ...
app/controllers/public/account_controller.rb
... ... @@ -213,7 +213,7 @@ class AccountController &lt; ApplicationController
213 213 if params[:value].blank?
214 214 @change_password.errors[:base] << _('Can not recover user password with blank value.')
215 215 else
216   - @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]]
  216 + @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".').html_safe % [fields_label, params[:value]]
217 217 end
218 218 rescue ActiveRecord::RecordInvalid
219 219 @change_password.errors[:base] << _('Could not perform password recovery for the user.')
... ...
app/controllers/public/profile_controller.rb
... ... @@ -42,8 +42,8 @@ class ProfileController &lt; PublicController
42 42 feed_writer = FeedWriter.new
43 43 data = feed_writer.write(
44 44 tagged,
45   - :title => _("%s's contents tagged with \"%s\"") % [profile.name, @tag],
46   - :description => _("%s's contents tagged with \"%s\"") % [profile.name, @tag],
  45 + :title => _("%s's contents tagged with \"%s\"").html_safe % [profile.name, @tag],
  46 + :description => _("%s's contents tagged with \"%s\"").html_safe % [profile.name, @tag],
47 47 :link => url_for(profile.url)
48 48 )
49 49 render :text => data, :content_type => "text/xml"
... ... @@ -88,7 +88,7 @@ class ProfileController &lt; PublicController
88 88  
89 89 def join_modal
90 90 profile.add_member(user)
91   - session[:notice] = _('%s administrator still needs to accept you as member.') % profile.name
  91 + session[:notice] = _('%s administrator still needs to accept you as member.').html_safe % profile.name
92 92 redirect_to :action => :index
93 93 end
94 94  
... ... @@ -98,12 +98,12 @@ class ProfileController &lt; PublicController
98 98  
99 99 profile.add_member(user)
100 100 if !profile.members.include?(user)
101   - render :text => {:message => _('%s administrator still needs to accept you as member.') % profile.name}.to_json
  101 + render :text => {:message => _('%s administrator still needs to accept you as member.').html_safe % profile.name}.to_json
102 102 else
103   - render :text => {:message => _('You just became a member of %s.') % profile.name}.to_json
  103 + render :text => {:message => _('You just became a member of %s.').html_safe % profile.name}.to_json
104 104 end
105 105 else
106   - render :text => {:message => _('You are already a member of %s.') % profile.name}.to_json
  106 + render :text => {:message => _('You are already a member of %s.').html_safe % profile.name}.to_json
107 107 end
108 108 end
109 109  
... ... @@ -125,7 +125,7 @@ class ProfileController &lt; PublicController
125 125 render :text => current_person.leave(profile, params[:reload])
126 126 end
127 127 else
128   - render :text => {:message => _('You are not a member of %s.') % profile.name}.to_json
  128 + render :text => {:message => _('You are not a member of %s.').html_safe % profile.name}.to_json
129 129 end
130 130 end
131 131  
... ... @@ -145,9 +145,9 @@ class ProfileController &lt; PublicController
145 145 # FIXME this shouldn't be in Person model?
146 146 if !user.memberships.include?(profile)
147 147 AddFriend.create!(:person => user, :friend => profile)
148   - render :text => _('%s still needs to accept being your friend.') % profile.name
  148 + render :text => _('%s still needs to accept being your friend.').html_safe % profile.name
149 149 else
150   - render :text => _('You are already a friend of %s.') % profile.name
  150 + render :text => _('You are already a friend of %s.').html_safe % profile.name
151 151 end
152 152 end
153 153  
... ... @@ -178,7 +178,7 @@ class ProfileController &lt; PublicController
178 178 def unblock
179 179 if current_user.person.is_admin?(profile.environment)
180 180 profile.unblock
181   - session[:notice] = _("You have unblocked %s successfully. ") % profile.name
  181 + session[:notice] = _("You have unblocked %s successfully. ").html_safe % profile.name
182 182 redirect_to :controller => 'profile', :action => 'index'
183 183 else
184 184 message = _('You are not allowed to unblock enterprises in this environment.')
... ...
app/helpers/application_helper.rb
... ... @@ -882,7 +882,7 @@ module ApplicationHelper
882 882 link_to_all = link_to(content_tag('strong', _('See all')), :controller => 'memberships', :profile => user.identifier)
883 883 end
884 884 link = list.map do |element|
885   - link_to(content_tag('strong', _('<span>Manage</span> %s') % element.short_name(25)), element.admin_url, :class => "icon-menu-"+element.class.identification.underscore, :title => _('Manage %s') % element.short_name)
  885 + link_to(content_tag('strong', _('<span>Manage</span> %s').html_safe % element.short_name(25)), element.admin_url, :class => "icon-menu-"+element.class.identification.underscore, :title => _('Manage %s').html_safe % element.short_name)
886 886 end
887 887 if link_to_all
888 888 link << link_to_all
... ... @@ -923,7 +923,7 @@ module ApplicationHelper
923 923 logout_link = link_to(logout_icon.html_safe, { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system"))
924 924 join_result = safe_join(
925 925 [welcome_span.html_safe, render_environment_features(:usermenu).html_safe, admin_link.html_safe,
926   - manage_enterprises.html_safe, manage_communities.html_safe, ctrl_panel_link.html_safe,
  926 + manage_enterprises, manage_communities, ctrl_panel_link.html_safe,
927 927 pending_tasks_count.html_safe, logout_link.html_safe], "")
928 928 join_result
929 929 end
... ...
app/mailers/contact.rb
... ... @@ -47,8 +47,8 @@ class Contact
47 47 content_type: 'text/html',
48 48 to: contact.dest.notification_emails,
49 49 reply_to: contact.email,
50   - subject: "[#{contact.dest.short_name(30)}] " + contact.subject,
51   - from: "#{contact.name} <#{contact.dest.environment.noreply_email}>"
  50 + subject: "[#{contact.dest.short_name(30)}] #{contact.subject}".html_safe,
  51 + from: "#{contact.name} <#{contact.dest.environment.noreply_email}>".html_safe
52 52 }
53 53  
54 54 if contact.sender
... ...
app/mailers/environment_mailing.rb
... ... @@ -30,7 +30,7 @@ class EnvironmentMailing &lt; Mailing
30 30 end
31 31  
32 32 def signature_message
33   - _('Sent by %s.') % source.name
  33 + _('Sent by %s.').html_safe % source.name
34 34 end
35 35  
36 36 def url
... ...
app/mailers/mailing.rb
... ... @@ -23,11 +23,11 @@ class Mailing &lt; ApplicationRecord
23 23 end
24 24  
25 25 def generate_from
26   - "#{source.name} <#{if source.is_a? Environment then source.noreply_email else source.contact_email end}>"
  26 + "#{source.name} <#{if source.is_a? Environment then source.noreply_email else source.contact_email end}>".html_safe
27 27 end
28 28  
29 29 def generate_subject
30   - '[%s] %s' % [source.name, subject]
  30 + '[%s] %s'.html_safe % [source.name, subject]
31 31 end
32 32  
33 33 def signature_message
... ...
app/mailers/organization_mailing.rb
... ... @@ -30,7 +30,7 @@ class OrganizationMailing &lt; Mailing
30 30 end
31 31  
32 32 def signature_message
33   - _('Sent by community %s.') % source.name
  33 + _('Sent by community %s.').html_safe % source.name
34 34 end
35 35  
36 36 include Rails.application.routes.url_helpers
... ...
app/mailers/pending_task_notifier.rb
... ... @@ -12,8 +12,8 @@ class PendingTaskNotifier &lt; ApplicationMailer
12 12  
13 13 mail(
14 14 to: person.email,
15   - from: "#{person.environment.name} <#{person.environment.noreply_email}>",
16   - subject: _("[%s] Pending tasks") % person.environment.name
  15 + from: "#{person.environment.name} <#{person.environment.noreply_email}>".html_safe,
  16 + subject: _("[%s] Pending tasks").html_safe % person.environment.name
17 17 )
18 18 end
19 19  
... ...
app/mailers/scrap_notifier.rb
... ... @@ -14,8 +14,8 @@ class ScrapNotifier &lt; ApplicationMailer
14 14 @url = sender.environment.top_url
15 15 mail(
16 16 to: receiver.email,
17   - from: "#{sender.environment.name} <#{sender.environment.noreply_email}>",
18   - subject: _("[%s] You received a scrap!") % [sender.environment.name]
  17 + from: "#{sender.environment.name} <#{sender.environment.noreply_email}>".html_safe,
  18 + subject: _("[%s] You received a scrap!").html_safe % [sender.environment.name]
19 19 )
20 20 end
21 21 end
... ...
app/mailers/task_mailer.rb
... ... @@ -14,7 +14,7 @@ class TaskMailer &lt; ApplicationMailer
14 14 mail(
15 15 to: task.target.notification_emails.compact,
16 16 from: self.class.generate_from(task),
17   - subject: "[%s] %s" % [task.environment.name, task.target_notification_description]
  17 + subject: "[%s] %s".html_safe % [task.environment.name, task.target_notification_description]
18 18 )
19 19 end
20 20  
... ... @@ -27,7 +27,7 @@ class TaskMailer &lt; ApplicationMailer
27 27 mail(
28 28 to: task.friend_email,
29 29 from: self.class.generate_from(task),
30   - subject: '[%s] %s' % [ task.requestor.environment.name, task.target_notification_description ]
  30 + subject: '[%s] %s'.html_safe % [ task.requestor.environment.name, task.target_notification_description ]
31 31 )
32 32 end
33 33  
... ... @@ -43,7 +43,7 @@ class TaskMailer &lt; ApplicationMailer
43 43 mail_with_template(
44 44 to: task.requestor.notification_emails,
45 45 from: self.class.generate_from(task),
46   - subject: '[%s] %s' % [task.requestor.environment.name, task.target_notification_description],
  46 + subject: '[%s] %s'.html_safe % [task.requestor.environment.name, task.target_notification_description],
47 47 email_template: task.email_template,
48 48 template_params: {:environment => task.requestor.environment, :task => task, :message => @message, :url => @url, :requestor => task.requestor}
49 49 )
... ...
app/mailers/user_mailer.rb
... ... @@ -13,8 +13,8 @@ class UserMailer &lt; ApplicationMailer
13 13  
14 14 mail(
15 15 to: user_email,
16   - from: "#{user.environment.name} <#{user.environment.contact_email}>",
17   - subject: _("[%{environment}] Welcome to %{environment} mail!") % { :environment => user.environment.name }
  16 + from: "#{user.environment.name} <#{user.environment.contact_email}>".html_safe,
  17 + subject: _("[%{environment}] Welcome to %{environment} mail!").html_safe % { :environment => user.environment.name }
18 18 )
19 19 end
20 20  
... ... @@ -30,7 +30,7 @@ class UserMailer &lt; ApplicationMailer
30 30 mail_with_template(
31 31 from: "#{user.environment.name} <#{user.environment.contact_email}>",
32 32 to: user.email,
33   - subject: _("[%s] Activate your account") % [user.environment.name],
  33 + subject: _("[%s] Activate your account").html_safe % [user.environment.name],
34 34 template_params: {:environment => user.environment, :activation_code => @activation_code, :redirection => @redirection, :join => @join, :person => user.person, :url => @url},
35 35 email_template: user.environment.email_templates.find_by_template_type(:user_activation),
36 36 )
... ... @@ -44,8 +44,8 @@ class UserMailer &lt; ApplicationMailer
44 44 mail(
45 45 content_type: 'text/html',
46 46 to: user.email,
47   - from: "#{user.environment.name} <#{user.environment.contact_email}>",
48   - subject: email_subject.blank? ? _("Welcome to environment %s") % [user.environment.name] : email_subject,
  47 + from: "#{user.environment.name} <#{user.environment.contact_email}>".html_safe,
  48 + subject: email_subject.blank? ? _("Welcome to environment %s").html_safe % [user.environment.name] : email_subject,
49 49 body: @body
50 50 )
51 51 end
... ... @@ -63,8 +63,8 @@ class UserMailer &lt; ApplicationMailer
63 63 mail(
64 64 content_type: 'text/html',
65 65 to: user.email,
66   - from: "#{user.environment.name} <#{user.environment.contact_email}>",
67   - subject: _("[%s] What about grow up your network?") % user.environment.name
  66 + from: "#{user.environment.name} <#{user.environment.contact_email}>".html_safe,
  67 + subject: _("[%s] What about grow up your network?").html_safe % user.environment.name
68 68 )
69 69 end
70 70  
... ...
app/models/abuse_complaint.rb
... ... @@ -25,7 +25,7 @@ class AbuseComplaint &lt; Task
25 25 end
26 26  
27 27 def title
28   - abuse_reports.count > 1 ? (_('Abuse complaint (%s)') % abuse_reports.count) :_('Abuse complaint')
  28 + abuse_reports.count > 1 ? (_('Abuse complaint (%s)').html_safe % abuse_reports.count) :_('Abuse complaint')
29 29 end
30 30  
31 31 def linked_subject
... ... @@ -53,15 +53,15 @@ class AbuseComplaint &lt; Task
53 53 end
54 54  
55 55 def task_activated_message
56   - _('Your profile was reported by the users of %s due to inappropriate behavior. The administrators of the environment are now reviewing the report. To solve this misunderstanding, please contact the administrators.') % environment.name
  56 + _('Your profile was reported by the users of %s due to inappropriate behavior. The administrators of the environment are now reviewing the report. To solve this misunderstanding, please contact the administrators.').html_safe % environment.name
57 57 end
58 58  
59 59 def task_finished_message
60   - _('Your profile was disabled by the administrators of %s due to inappropriate behavior. To solve this misunderstanding please contact them.') % environment.name
  60 + _('Your profile was disabled by the administrators of %s due to inappropriate behavior. To solve this misunderstanding please contact them.').html_safe % environment.name
61 61 end
62 62  
63 63 def target_notification_description
64   - _('%s was reported due to inappropriate behavior.') % reported.name
  64 + _('%s was reported due to inappropriate behavior.').html_safe % reported.name
65 65 end
66 66  
67 67 def target_notification_message
... ...
app/models/add_member.rb
... ... @@ -56,7 +56,7 @@ class AddMember &lt; Task
56 56 def target_notification_description
57 57 requestor_email = " (#{requestor.email})" if requestor.may_display_field_to?("email")
58 58  
59   - _("%{requestor}%{requestor_email} wants to be a member of '%{organization}'.") % {:requestor => requestor.name, :requestor_email => requestor_email, :organization => organization.name}
  59 + _("%{requestor}%{requestor_email} wants to be a member of '%{organization}'.").html_safe % {:requestor => requestor.name, :requestor_email => requestor_email, :organization => organization.name}
60 60 end
61 61  
62 62 def target_notification_message
... ...
app/models/community.rb
... ... @@ -2,7 +2,7 @@ class Community &lt; Organization
2 2  
3 3 attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type
4 4 attr_accessible :address_reference, :district, :tag_list, :language, :description
5   - attr_accessible :requires_email
  5 +
6 6 after_destroy :check_invite_member_for_destroy
7 7  
8 8 def self.type_name
... ... @@ -13,9 +13,6 @@ class Community &lt; Organization
13 13 N_('Language')
14 14  
15 15 settings_items :language
16   - settings_items :requires_email, :type => :boolean
17   -
18   - alias_method :requires_email?, :requires_email
19 16  
20 17 extend SetProfileRegionFromCityState::ClassMethods
21 18 set_profile_region_from_city_state
... ...
app/models/organization.rb
... ... @@ -2,6 +2,10 @@
2 2 class Organization < Profile
3 3  
4 4 attr_accessible :moderated_articles, :foundation_year, :contact_person, :acronym, :legal_form, :economic_activity, :management_information, :cnpj, :display_name, :enable_contact_us
  5 + attr_accessible :requires_email
  6 +
  7 + settings_items :requires_email, type: :boolean
  8 + alias_method :requires_email?, :requires_email
5 9  
6 10 SEARCH_FILTERS = {
7 11 :order => %w[more_recent more_popular more_active],
... ...
app/views/account/activation_question.html.erb
... ... @@ -3,7 +3,7 @@
3 3 var answer = parseInt(form.answer.value);
4 4 var val = form.answer.value;
5 5 if (!answer || (val.length != 4) || val > <%= Time.now.year %> || val < 1900) {
6   - alert(<%= (_('The year must be between %d and %d') % [1900, Time.now.year]).inspect %>);
  6 + alert(<%= (_('The year must be between %d and %d').html_safe % [1900, Time.now.year]).inspect %>);
7 7 return false;
8 8 } else {
9 9 return true;
... ... @@ -28,9 +28,9 @@
28 28  
29 29 <p> <strong><%= _('Pay atention! You have only one chance!') %></strong> </p>
30 30  
31   - <p><%= _("This is a question to know if you really are part of this enterprise. Pay atention because you have only one chance to answer right and activate your enterprise. If you answer wrong you will not be able to activate the enterprise automaticaly and must get in touch with the admins of %s by email or phone.") % environment.name %> </p>
  31 + <p><%= _("This is a question to know if you really are part of this enterprise. Pay atention because you have only one chance to answer right and activate your enterprise. If you answer wrong you will not be able to activate the enterprise automaticaly and must get in touch with the admins of %s by email or phone.").html_safe % environment.name %> </p>
32 32  
33   - <%= ApplicationHelper::NoosferoFormBuilder::output_field(@question == :foundation_year ? (_("What year your enterprise was founded? It must have 4 digits, eg 1990. %s") % environment.tip_message_enterprise_activation_question) : _('What is the CNPJ of your enterprise?'), text_field_tag(:answer, nil, :id => 'enterprise-activation-answer')) %>
  33 + <%= ApplicationHelper::NoosferoFormBuilder::output_field(@question == :foundation_year ? (_("What year your enterprise was founded? It must have 4 digits, eg 1990. %s").html_safe % environment.tip_message_enterprise_activation_question) : _('What is the CNPJ of your enterprise?'), text_field_tag(:answer, nil, :id => 'enterprise-activation-answer')) %>
34 34  
35 35 <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %>
36 36  
... ...
app/views/admin_panel/_signup_welcome_text.html.erb
1 1 <div class='description'>
2 2 <%= _('This text will be sent to new users if the feature "Send welcome e-mail to new users" is enabled on environment.') %><br/><br/>
3   - <%= _('Including %s on body, it will be replaced by the real name of the e-mail recipient.') % content_tag('code', '{user_name}') %>
  3 + <%= _('Including %s on body, it will be replaced by the real name of the e-mail recipient.').html_safe % content_tag('code', '{user_name}') %>
4 4 </div>
5 5  
6 6 <%= labelled_form_field(_('Subject'), text_field(:environment, :signup_welcome_text_subject, :style => 'width:100%')) %>
... ...
app/views/cms/_blog.html.erb
... ... @@ -58,7 +58,7 @@
58 58 <div id="blog-image-builder">
59 59 <%= f.fields_for :image_builder, @article.image do |i| %>
60 60 <%= file_field_or_thumbnail(_('Cover image:'), @article.image, i)%>
61   - <%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %>
  61 + <%= _("Max size: %s (.jpg, .gif, .png)").html_safe % Image.max_size.to_humanreadable %>
62 62 <% end %>
63 63 </div>
64 64  
... ...
app/views/enterprise_validation/view_processed.html.erb
1   -<h2><%= _('Processed validation request for %s ') % @processed.name %> (<%= status(@processed) %>)</h2>
  1 +<h2><%= _('Processed validation request for %s ').html_safe % @processed.name %> (<%= status(@processed) %>)</h2>
2 2  
3 3 <%= link_to _('Back'), :action => 'index' %>
4 4  
... ...
app/views/favorite_enterprises/add.html.erb
1   -<h1><%= _('Adding %s as a favorite enterprise') % @favorite_enterprise.name %></h1>
  1 +<h1><%= _('Adding %s as a favorite enterprise').html_safe % @favorite_enterprise.name %></h1>
2 2  
3 3 <p>
4   -<%= _('Are you sure you want to add %s as your favorite enterprise?') % @favorite_enterprise.name %>
  4 +<%= _('Are you sure you want to add %s as your favorite enterprise?').html_safe % @favorite_enterprise.name %>
5 5 </p>
6 6  
7 7 <%= form_tag do %>
8 8 <%= hidden_field_tag(:confirmation, 1) %>
9 9  
10   - <%= submit_button(:ok, _("Yes, I am sure"), :title => _("I want to add %s as a favorite enterprise") % @favorite_enterprise.name) %>
  10 + <%= submit_button(:ok, _("Yes, I am sure"), :title => _("I want to add %s as a favorite enterprise").html_safe % @favorite_enterprise.name) %>
11 11 <%= button(:cancel, _("No, I don't want"), :action => 'index') %>
12 12 <% end %>
... ...
app/views/friends/remove.html.erb
1 1 <div id="remove_friend">
2 2  
3   -<h1><%= _('Removing friend: %s') % @friend.name %></h1>
  3 +<h1><%= _('Removing friend: %s').html_safe % @friend.name %></h1>
4 4  
5 5 <%= profile_image @friend, :thumb, :class => 'friend_picture' %>
6 6  
7 7 <p>
8   -<%= _('Are you sure you want to remove %s from your friends list?') % @friend.name %>
  8 +<%= _('Are you sure you want to remove %s from your friends list?').html_safe % @friend.name %>
9 9 </p>
10 10  
11 11 <p>
12 12 <em>
13   -<%= _('Note that %s will still have you as a friend, unless he/she also wants to remove you from his/her friend list.') % @friend.name %>
  13 +<%= _('Note that %s will still have you as a friend, unless he/she also wants to remove you from his/her friend list.').html_safe % @friend.name %>
14 14 </em>
15 15 </p>
16 16  
... ...
app/views/home/welcome.html.erb
1 1 <% default_message = defined?(default_message) ? default_message : false %>
2 2  
3 3 <div id='thanks-for-signing'>
4   - <h1><%= _("Welcome to %s!") % environment.name %></h1>
  4 + <h1><%= _("Welcome to %s!").html_safe % environment.name %></h1>
5 5 <% if environment.has_custom_welcome_screen? && !default_message %>
6 6 <%= environment.settings[:signup_welcome_screen_body].html_safe %>
7 7 <% else %>
... ... @@ -10,21 +10,21 @@
10 10 <p><%= _("Firstly, some tips for getting started:") %></p>
11 11 <h4><%= _("Confirm your account!") %></h4>
12 12 <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p>
13   - <p><%= _("You won't appear as %s until your account is confirmed.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p>
  13 + <p><%= _("You won't appear as %s until your account is confirmed.").html_safe % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p>
14 14 <% else %>
15 15 <h4><%= _("Wait for admin approvement!") %></h4>
16 16 <p><%= _("The administrators will evaluate your signup request for approvement.") %></p>
17   - <p><%= _("You won't appear as %s until your account is approved.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p>
  17 + <p><%= _("You won't appear as %s until your account is approved.").html_safe % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p>
18 18 <% end %>
19 19 <h4><%= _("What to do next?") %></h4>
20   - <p><%= _("Access your %s and see your face on the network!") %
  20 + <p><%= _("Access your %s and see your face on the network!").html_safe %
21 21 (user.present? ? link_to(_('Profile'), {:controller => 'profile', :profile => user.identifier}, :target => '_blank') : 'Profile') %>
22   - <%= _("You can also explore your %s to customize your profile. Here are some %s on what you can do there.") %
  22 + <%= _("You can also explore your %s to customize your profile. Here are some %s on what you can do there.").html_safe %
23 23 [user.present? ? link_to(_('Control Panel'), {:controller => 'profile_editor', :profile => user.identifier}, :target => '_blank') : 'Control Panel',
24 24 link_to(_('tips'), {:controller => 'doc', :action => 'topic', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank')] %></p>
25   - <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :action => 'topic', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p>
26   - <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p>
  25 + <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!").html_safe % link_to(_('Invite and find'), {:controller => 'doc', :action => 'topic', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p>
  26 + <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!").html_safe % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p>
27 27 <p><%= _("Start exploring and have fun!") %></p>
28 28 <% end %>
29   - <%= render :partial => 'shared/template_welcome_page', :locals => {:template => @person_template, :header => _("What can I do as a %s?")} %>
  29 + <%= render :partial => 'shared/template_welcome_page', :locals => {:template => @person_template, :header => _("What can I do as a %s?").html_safe} %>
30 30 </div>
... ...
app/views/person_notifier/mailer/_profile_comments.html.erb
1 1 <% if activity.comments_count > 2 %>
2 2 <div style="font-size: 10px;">
3 3 <% if activity.params['url'].blank? %>
4   - <%= _("%s comments") % activity.comments_count %>
  4 + <%= _("%s comments").html_safe % activity.comments_count %>
5 5 <% else %>
6   - <%= link_to(_("View all %s comments") % activity.comments_count, activity.params['url']) %>
  6 + <%= link_to(_("View all %s comments").html_safe % activity.comments_count, activity.params['url']) %>
7 7 <% end %>
8 8 </div>
9 9 <% else %>
... ...
app/views/profile/_private_profile.html.erb
... ... @@ -13,5 +13,5 @@
13 13 <%= button(:add, content_tag('span', _('Add friend')), profile.add_url, :class => 'add-friend', :title => _("Add friend"), :style => 'position: relative;') %>
14 14 <% end %>
15 15 <%= button :back, _('Go back'), :back %>
16   - <%= button :home, _("Go to %s home page") % environment.name, :controller => 'home' %>
  16 + <%= button :home, _("Go to %s home page").html_safe % environment.name, :controller => 'home' %>
17 17 <% end %>
... ...
app/views/profile/_profile_comments.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <% if activity.comments_count > 0 %>
6 6 <div id="profile-wall-activities-comments-more-<%= activity.id %>" class="profile-wall-activities-comments" >
7 7 <div class='view-all-comments icon-chat'>
8   - <%= link_to(n_('View comment', "View all %s comments", activity.comments_count) % activity.comments_count, :profile => profile.identifier, :controller => 'profile', :action => 'more_comments', :activity => activity, :comment_page => (1)) %>
  8 + <%= link_to(n_('View comment', "View all %s comments".html_safe, activity.comments_count) % activity.comments_count, :profile => profile.identifier, :controller => 'profile', :action => 'more_comments', :activity => activity, :comment_page => (1)) %>
9 9 </div>
10 10 </div>
11 11 <% end %>
... ...
app/views/profile/_profile_scraps.html.erb
... ... @@ -23,7 +23,7 @@
23 23 <% if scrap.replies.count > 0 %>
24 24 <div id="profile-wall-activities-comments-more-<%= activity.id %>" class="profile-wall-activities-comments">
25 25 <div class='view-all-comments icon-chat'>
26   - <%= link_to(n_('View comment', "View all %s comments", scrap.replies.count) % scrap.replies.count, :profile => profile.identifier, :controller => 'profile', :action => 'more_replies', :activity => activity, :comment_page => (1)) %>
  26 + <%= link_to(n_('View comment', "View all %s comments".html_safe, scrap.replies.count) % scrap.replies.count, :profile => profile.identifier, :controller => 'profile', :action => 'more_replies', :activity => activity, :comment_page => (1)) %>
27 27 </div>
28 28 </div>
29 29 <% end %>
... ...
app/views/profile_editor/edit.html.erb
1   -<h1><%= _('Profile settings for %s') % profile.name %></h1>
  1 +<h1><%= _('Profile settings for %s').html_safe % profile.name %></h1>
2 2  
3 3 <%= error_messages_for :profile_data %>
4 4  
... ... @@ -18,7 +18,7 @@
18 18 </div>
19 19 <div id="profile_change_picture">
20 20 <%= f.fields_for :image_builder, @profile.image do |i| %>
21   - <%= file_field_or_thumbnail(_('Image:'), @profile.image, i) %><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %>
  21 + <%= file_field_or_thumbnail(_('Image:'), @profile.image, i) %><%= _("Max size: %s (.jpg, .gif, .png)").html_safe % Image.max_size.to_humanreadable %>
22 22 <% end %>
23 23 </div>
24 24  
... ...
app/views/search/_search_content.html.erb
1 1 <div id='search-content'>
2 2 <div class='total'>
3   - <%= n_('Total of 1 result', 'Total of %s results', @searches[@asset][:results].total_entries) % @searches[@asset][:results].total_entries.inspect %>
  3 + <%= n_('Total of 1 result', 'Total of %s results'.html_safe, @searches[@asset][:results].total_entries) % @searches[@asset][:results].total_entries.inspect %>
4 4 </div>
5 5  
6 6 <%= display_results(@searches, @asset) %>
... ...
app/views/search/search_page.html.erb
1   -<%= render :partial => 'search_form', :locals => { :hint => _("Type words about the %s you're looking for") % _(@asset.to_s.singularize) } %>
  1 +<%= render :partial => 'search_form', :locals => { :hint => _("Type words about the %s you're looking for").html_safe % _(@asset.to_s.singularize) } %>
2 2 <%= render :partial => 'search_content' %>
3 3  
4 4 <div style="clear: both"></div>
... ...
app/views/shared/_remove_suggestion.html.erb
1 1 <%= profile_image suggestion, :thumb, :class => 'suggestion_picture' %>
2 2  
3 3 <p>
4   -<%= _('Are you sure you want to remove %s from your suggestions list?') % suggestion.name %>
  4 +<%= _('Are you sure you want to remove %s from your suggestions list?').html_safe % suggestion.name %>
5 5 </p>
6 6  
7 7 <%= form_tag do %>
8   - <%= submit_button(:ok, _("Yes, I want to remove %s") % suggestion.name) %>
  8 + <%= submit_button(:ok, _("Yes, I want to remove %s").html_safe % suggestion.name) %>
9 9 <%= button(:cancel, _("No"), :action => 'suggest') %>
10 10 <% end %>
... ...
app/views/tasks/ticket_details.html.erb
1   -<h2><%= _('Ticket: %s') % @ticket.name %></h2>
  1 +<h2><%= _('Ticket: %s').html_safe % @ticket.name %></h2>
2 2 <p><small>
3   - <%= _('Created at %s by %s') % [@ticket.created_at.to_date, link_to(@ticket.requestor.name, @ticket.requestor.url)] %><br/>
4   - <%= _('Owner: %s') % link_to(@ticket.target.name, @ticket.target.url) %>
  3 + <%= _('Created at %s by %s').html_safe % [@ticket.created_at.to_date, link_to(@ticket.requestor.name, @ticket.requestor.url)] %><br/>
  4 + <%= _('Owner: %s').html_safe % link_to(@ticket.target.name, @ticket.target.url) %>
5 5 </small></p>
6 6  
7   -<p><%= _('Status: %s') % gettext(Task::Status.names[@ticket.status]) %></p>
  7 +<p><%= _('Status: %s').html_safe % gettext(Task::Status.names[@ticket.status]) %></p>
8 8  
9 9 <div>
10   - <p><%= _('Description: %s') % @ticket.description %></p>
  10 + <p><%= _('Description: %s').html_safe % @ticket.description %></p>
11 11 </div>
12 12  
13 13 <% if @ticket.closing_statment %>
14   - <p><%= _('Closing statement: %s') % @ticket.closing_statment %></p>
  14 + <p><%= _('Closing statement: %s').html_safe % @ticket.closing_statment %></p>
15 15 <% end %>
16 16  
17 17 <%= button_bar do %>
... ...
app/views/templates/index.html.erb
... ... @@ -10,7 +10,7 @@
10 10 <% list_of_templates.each do |title, templates, kind|%>
11 11 <div class='template-kind'>
12 12 <h2><%= title %></h2>
13   - <%= button :add, _('New...'), {:action => "create_#{kind}_template"}, :title => _("Create a new template for %s") % title.downcase %>
  13 + <%= button :add, _('New...'), {:action => "create_#{kind}_template"}, :title => _("Create a new template for %s").html_safe % title.downcase %>
14 14 <table class='actions'>
15 15 <tr>
16 16 <th><%= _('Template') %></th>
... ... @@ -20,11 +20,11 @@
20 20 <tr>
21 21 <td>
22 22 <%#= image_tag "icons-app/#{kind}-icon.png" %>
23   - <%= link_to(template.name, {:controller => 'profile_editor', :profile => template.identifier}, :title => _('Edit template "%s"') % template.name ) %>
  23 + <%= link_to(template.name, {:controller => 'profile_editor', :profile => template.identifier}, :title => _('Edit template "%s"').html_safe % template.name ) %>
24 24 <% if environment.is_default_template?(template) %>
25 25 <%= _('is the default template') %>
26 26 <% else %>
27   - <%= link_to(_('Set as default'), {:action => "set_#{kind}_as_default", :template_id => template.id}, :title => _('Set %s template as default') % template.name ) %>
  27 + <%= link_to(_('Set as default'), {:action => "set_#{kind}_as_default", :template_id => template.id}, :title => _('Set %s template as default').html_safe % template.name ) %>
28 28 <% end %>
29 29 </td>
30 30 <td>
... ...
app/views/user_mailer/activation_email_notify.text.erb
1   -<%= _('Hello %s,') % @name %>
  1 +<%= _('Hello %s,').html_safe % @name %>
2 2  
3   -<%= _('Your email %s was just activated.') % [@email] %>
  3 +<%= _('Your email %s was just activated.').html_safe % [@email] %>
4 4  
5 5 <%= _('You can access your e-mail from anywhere, using the following address:') %>
6 6 <%= @webmail %>
... ... @@ -8,5 +8,5 @@
8 8 <%= _('Greetings,') %>
9 9  
10 10 --
11   -<%= _('%s team.') % @environment.name %>
  11 +<%= _('%s team.').html_safe % @environment.name %>
12 12 <%= @url %>
... ...
plugins/analytics/Gemfile 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +gem 'browser', '~> 2.2.0'
  2 +
... ...
plugins/analytics/controllers/myprofile/analytics_plugin/stats_controller.rb
... ... @@ -7,12 +7,39 @@ class AnalyticsPlugin::StatsController &lt; MyProfileController
7 7 def index
8 8 end
9 9  
  10 + def edit
  11 + return render_access_denied unless user.has_permission? 'edit_profile', profile
  12 +
  13 + params[:analytics_settings][:enabled] = params[:analytics_settings][:enabled] == 'true'
  14 + params[:analytics_settings][:anonymous] = params[:analytics_settings][:anonymous] == 'true'
  15 + @settings = profile.analytics_settings params[:analytics_settings] || {}
  16 + @settings.save!
  17 + render nothing: true
  18 + end
  19 +
  20 + def view
  21 + params[:profile_ids] ||= [profile.id]
  22 + ids = params[:profile_ids].map(&:to_i)
  23 + user.adminships # FIXME just to cache #adminship_ids
  24 + ids = ids.select{ |id| id.in? user.adminship_ids } unless @user_is_admin
  25 +
  26 + @profiles = environment.profiles.find ids
  27 + @user = environment.people.find params[:user_id]
  28 + @visits = AnalyticsPlugin::Visit.eager_load(:users_page_views).
  29 + where(profile_id: ids, analytics_plugin_page_views: {user_id: @user.id})
  30 +
  31 + render partial: 'table', locals: {visits: @visits}
  32 +
  33 + end
  34 +
10 35 protected
11 36  
12   - def default_url_options
13   - # avoid rails' use_relative_controller!
14   - {use_route: '/'}
  37 + # inherit routes from core skipping use_relative_controller!
  38 + def url_for options
  39 + options[:controller] = "/#{options[:controller]}" if options.is_a? Hash and options[:controller] and not options[:controller].to_s.starts_with? '/'
  40 + super options
15 41 end
  42 + helper_method :url_for
16 43  
17 44 def skip_page_view
18 45 @analytics_skip_page_view = true
... ...
plugins/analytics/controllers/profile/analytics_plugin/time_on_page_controller.rb
... ... @@ -7,7 +7,10 @@ class AnalyticsPlugin::TimeOnPageController &lt; ProfileController
7 7 Noosfero::Scheduler::Defer.later do
8 8 page_view = profile.page_views.where(request_id: params[:id]).first
9 9 page_view.request = request
10   - page_view.page_load!
  10 + AnalyticsPlugin::PageView.transaction do
  11 + page_view.page_load! Time.at(params[:time].to_i)
  12 + page_view.update_column :title, params[:title] if params[:title].present?
  13 + end
11 14 end
12 15  
13 16 render nothing: true
... ...
plugins/analytics/db/migrate/20151030122634_add_title_and_is_bot_to_analytics_plugin_page_view.rb 0 → 100644
... ... @@ -0,0 +1,40 @@
  1 +class AddTitleAndIsBotToAnalyticsPluginPageView < ActiveRecord::Migration
  2 +
  3 + def up
  4 + add_column :analytics_plugin_page_views, :title, :text
  5 + add_column :analytics_plugin_page_views, :is_bot, :boolean
  6 +
  7 + # missing indexes for performance
  8 + add_index :analytics_plugin_page_views, :type
  9 + add_index :analytics_plugin_page_views, :visit_id
  10 + add_index :analytics_plugin_page_views, :request_started_at
  11 + add_index :analytics_plugin_page_views, :page_loaded_at
  12 + add_index :analytics_plugin_page_views, :is_bot
  13 +
  14 + AnalyticsPlugin::PageView.transaction do
  15 + AnalyticsPlugin::PageView.find_each do |page_view|
  16 + page_view.send :fill_is_bot
  17 + page_view.update_column :is_bot, page_view.is_bot
  18 + end
  19 + end
  20 +
  21 + change_table :analytics_plugin_visits do |t|
  22 + t.timestamps
  23 + end
  24 + AnalyticsPlugin::Visit.transaction do
  25 + AnalyticsPlugin::Visit.find_each do |visit|
  26 + visit.created_at = visit.page_views.first.request_started_at
  27 + visit.updated_at = visit.page_views.last.request_started_at
  28 + visit.save!
  29 + end
  30 + end
  31 +
  32 + # never used
  33 + remove_column :analytics_plugin_page_views, :track_id
  34 + end
  35 +
  36 + def down
  37 + say "this migration can't be reverted"
  38 + end
  39 +
  40 +end
... ...
plugins/analytics/lib/analytics_plugin.rb
... ... @@ -13,4 +13,15 @@ module AnalyticsPlugin
13 13 I18n.t'analytics_plugin.lib.plugin.description'
14 14 end
15 15  
  16 + def self.clear_non_users
  17 + ActiveRecord::Base.transaction do
  18 + AnalyticsPlugin::PageView.bots.delete_all
  19 + AnalyticsPlugin::PageView.not_page_loaded.delete_all
  20 + # delete_all does not work here
  21 + AnalyticsPlugin::Visit.without_page_views.destroy_all
  22 + end
  23 + end
  24 +
16 25 end
  26 +
  27 +Browser::Bot.detect_empty_ua!
... ...
plugins/analytics/lib/analytics_plugin/base.rb
... ... @@ -3,6 +3,7 @@ class AnalyticsPlugin::Base &lt; Noosfero::Plugin
3 3  
4 4 def body_ending
5 5 return unless profile and profile.analytics_enabled?
  6 + return if @analytics_skip_page_view
6 7 lambda do
7 8 render 'analytics_plugin/body_ending'
8 9 end
... ... @@ -12,6 +13,7 @@ class AnalyticsPlugin::Base &lt; Noosfero::Plugin
12 13 ['analytics'].map{ |j| "javascripts/#{j}" }
13 14 end
14 15  
  16 + # FIXME: not reloading on development, need server restart
15 17 def application_controller_filters
16 18 [{
17 19 type: 'around_filter', options: {}, block: -> &block do
... ... @@ -23,15 +25,12 @@ class AnalyticsPlugin::Base &lt; Noosfero::Plugin
23 25 return unless profile and profile.analytics_enabled?
24 26  
25 27 Noosfero::Scheduler::Defer.later 'analytics: register page view' do
26   - page_view = profile.page_views.build request: request, profile_id: profile,
  28 + page_view = profile.page_views.build request: request, profile_id: profile.id,
27 29 request_started_at: request_started_at, request_finished_at: request_finished_at
28   -
29 30 unless profile.analytics_anonymous?
30   - session_id = session.id
31 31 page_view.user = user
32   - page_view.session_id = session_id
  32 + page_view.session_id = session.id
33 33 end
34   -
35 34 page_view.save!
36 35 end
37 36 end,
... ... @@ -39,6 +38,7 @@ class AnalyticsPlugin::Base &lt; Noosfero::Plugin
39 38 end
40 39  
41 40 def control_panel_buttons
  41 + return unless user.is_admin? environment
42 42 {
43 43 title: I18n.t('analytics_plugin.lib.plugin.panel_button'),
44 44 icon: 'analytics-access',
... ...
plugins/analytics/lib/ext/profile.rb
1 1 require_dependency 'profile'
2   -require_dependency 'community'
3 2  
4   -([Profile] + Profile.descendants).each do |subclass|
5   -subclass.class_eval do
  3 +class Profile
6 4  
7   - has_many :visits, foreign_key: :profile_id, class_name: 'AnalyticsPlugin::Visit'
8   - has_many :page_views, foreign_key: :profile_id, class_name: 'AnalyticsPlugin::PageView'
  5 + has_many :users_visits, -> { latest.with_users_page_views }, foreign_key: :profile_id, class_name: 'AnalyticsPlugin::Visit'
9 6  
10   -end
11   -end
  7 + has_many :visits, -> { latest.eager_load :page_views }, foreign_key: :profile_id, class_name: 'AnalyticsPlugin::Visit'
  8 + has_many :page_views, foreign_key: :profile_id, class_name: 'AnalyticsPlugin::PageView'
12 9  
13   -class Profile
  10 + has_many :user_visits, -> { latest.eager_load :page_views }, foreign_key: :user_id, class_name: 'AnalyticsPlugin::PageView'
  11 + has_many :user_page_views, foreign_key: :user_id, class_name: 'AnalyticsPlugin::PageView'
14 12  
15 13 def analytics_settings attrs = {}
16 14 @analytics_settings ||= Noosfero::Plugin::Settings.new self, ::AnalyticsPlugin, attrs
... ...
plugins/analytics/locales/en.yml
... ... @@ -9,10 +9,14 @@ en: &amp;en
9 9  
10 10 views:
11 11 stats:
  12 + enable: "Enable tracking on the profile '%{profile}'"
  13 + anonymous: "Don't associate users' login"
  14 + config_save: "Configuration saved"
12 15 user: 'User'
13 16 initial_time: 'Time'
  17 + ip: 'IP'
14 18 pages: 'Pages'
15 19  
16   -en-US:
  20 +en_US:
17 21 <<: *en
18 22  
... ...
plugins/analytics/locales/pt.yml
... ... @@ -9,9 +9,14 @@ pt: &amp;pt
9 9  
10 10 views:
11 11 stats:
  12 + enable: "Ativar rastreio no perfil '%{profile}'"
  13 + anonymous: "Não associar login de usuários"
  14 + config_save: "Configuração salva"
12 15 user: 'Usuário'
13 16 initial_time: 'Horário'
  17 + ip: 'IP'
14 18 pages: 'Páginas'
15 19  
16   -pt-BR:
  20 +pt_BR:
17 21 <<: *pt
  22 +
... ...
plugins/analytics/models/analytics_plugin/page_view.rb
... ... @@ -10,22 +10,34 @@ class AnalyticsPlugin::PageView &lt; ApplicationRecord
10 10  
11 11 acts_as_having_settings field: :options
12 12  
13   - belongs_to :visit, class_name: 'AnalyticsPlugin::Visit'
14   - belongs_to :referer_page_view, class_name: 'AnalyticsPlugin::PageView'
  13 + belongs_to :profile, validate: true
  14 + belongs_to :visit, class_name: 'AnalyticsPlugin::Visit', touch: true, validate: true
15 15  
16   - belongs_to :user, class_name: 'Person'
17   - belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: 'Session'
18   - belongs_to :profile
  16 + belongs_to :referer_page_view, class_name: 'AnalyticsPlugin::PageView', validate: false
19 17  
20   - validates_presence_of :visit
21   - validates_presence_of :request, on: :create
22   - validates_presence_of :url
  18 + belongs_to :user, class_name: 'Person', validate: false
  19 + belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: 'Session', validate: false
  20 +
  21 + validates :request, presence: true, on: :create
  22 + validates :url, presence: true
23 23  
24 24 before_validation :extract_request_data, on: :create
25 25 before_validation :fill_referer_page_view, on: :create
26 26 before_validation :fill_visit, on: :create
  27 + before_validation :fill_is_bot, on: :create
  28 +
  29 + after_update :destroy_empty_visit
  30 + after_destroy :destroy_empty_visit
  31 +
  32 + scope :in_sequence, -> { order 'analytics_plugin_page_views.request_started_at ASC' }
  33 +
  34 + scope :page_loaded, -> { where 'analytics_plugin_page_views.page_loaded_at IS NOT NULL' }
  35 + scope :not_page_loaded, -> { where 'analytics_plugin_page_views.page_loaded_at IS NULL' }
27 36  
28   - scope :latest, -> { order 'request_started_at DESC' }
  37 + scope :no_bots, -> { where.not is_bot: true }
  38 + scope :bots, -> { where is_bot: true }
  39 +
  40 + scope :loaded_users, -> { in_sequence.page_loaded.no_bots }
29 41  
30 42 def request_duration
31 43 self.request_finished_at - self.request_started_at
... ... @@ -43,8 +55,8 @@ class AnalyticsPlugin::PageView &lt; ApplicationRecord
43 55 Time.now < self.user_last_time_seen + AnalyticsPlugin::TimeOnPageUpdateInterval
44 56 end
45 57  
46   - def page_load!
47   - self.page_loaded_at = Time.now
  58 + def page_load! time
  59 + self.page_loaded_at = time
48 60 self.update_column :page_loaded_at, self.page_loaded_at
49 61 end
50 62  
... ... @@ -56,6 +68,16 @@ class AnalyticsPlugin::PageView &lt; ApplicationRecord
56 68 self.update_column :time_on_page, self.time_on_page
57 69 end
58 70  
  71 + def find_referer_page_view
  72 + return if self.referer_url.blank?
  73 + AnalyticsPlugin::PageView.order('request_started_at DESC').
  74 + where(url: self.referer_url, session_id: self.session_id, user_id: self.user_id, profile_id: self.profile_id).first
  75 + end
  76 +
  77 + def browser
  78 + @browser ||= Browser.new self.user_agent
  79 + end
  80 +
59 81 protected
60 82  
61 83 def extract_request_data
... ... @@ -64,16 +86,29 @@ class AnalyticsPlugin::PageView &lt; ApplicationRecord
64 86 self.user_agent = self.request.headers['User-Agent']
65 87 self.request_id = self.request.env['action_dispatch.request_id']
66 88 self.remote_ip = self.request.remote_ip
  89 + true
67 90 end
68 91  
69 92 def fill_referer_page_view
70   - self.referer_page_view = AnalyticsPlugin::PageView.order('request_started_at DESC').
71   - where(url: self.referer_url, session_id: self.session_id, user_id: self.user_id, profile_id: self.profile_id).first if self.referer_url.present?
  93 + self.referer_page_view = self.find_referer_page_view
  94 + true
72 95 end
73 96  
74 97 def fill_visit
75 98 self.visit = self.referer_page_view.visit if self.referer_page_view and self.referer_page_view.user_on_page?
76 99 self.visit ||= AnalyticsPlugin::Visit.new profile: profile
  100 + true
  101 + end
  102 +
  103 + def fill_is_bot
  104 + self.is_bot = self.browser.bot?
  105 + true
  106 + end
  107 +
  108 + def destroy_empty_visit
  109 + return unless self.visit_id_changed?
  110 + old_visit = AnalyticsPlugin::Visit.find self.visit_id_was
  111 + old_visit.destroy if old_visit.page_views.empty?
77 112 end
78 113  
79 114 end
... ...
plugins/analytics/models/analytics_plugin/visit.rb
... ... @@ -5,10 +5,16 @@ class AnalyticsPlugin::Visit &lt; ApplicationRecord
5 5  
6 6 belongs_to :profile
7 7 has_many :page_views, class_name: 'AnalyticsPlugin::PageView', dependent: :destroy
  8 + has_many :users_page_views, -> { loaded_users }, class_name: 'AnalyticsPlugin::PageView', dependent: :destroy
8 9  
9   - default_scope -> { joins(:page_views).includes :page_views }
  10 + scope :latest, -> { order 'updated_at DESC' }
10 11  
11   - scope :latest, -> { order 'analytics_plugin_page_views.request_started_at DESC' }
  12 + scope :with_users_page_views, -> {
  13 + eager_load(:users_page_views).where.not analytics_plugin_page_views: {visit_id: nil}
  14 + }
  15 + scope :without_page_views, -> {
  16 + eager_load(:page_views).where analytics_plugin_page_views: {visit_id: nil}
  17 + }
12 18  
13 19 def first_page_view
14 20 self.page_views.first
... ...
plugins/analytics/public/javascripts/analytics.js
1 1 analytics = {
  2 +
  3 + t: function (key, options) {
  4 + return I18n.t(key, $.extend(options, {scope: 'analytics_plugin'}))
  5 + },
  6 +
2 7 requestId: '',
3 8  
4 9 timeOnPage: {
... ... @@ -27,7 +32,7 @@ analytics = {
27 32  
28 33 pageLoad: function() {
29 34 $.ajax(analytics.timeOnPage.baseUrl+'/page_load', {
30   - type: 'POST', data: {id: analytics.requestId},
  35 + type: 'POST', data: {id: analytics.requestId, title: document.title, time: Math.floor(Date.now()/1000)},
31 36 success: function(data) {
32 37 },
33 38 });
... ...
plugins/analytics/public/javascripts/views/settings.tag.slim 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +analytics-settings
  2 + .checkbox
  3 + label name='enabled'
  4 + input type='checkbox' name='enabled' value='1' checked='{settings.enabled}' onchange='{toggleEnabled}'
  5 + |{anl.t('views.stats.enable', {profile: noosfero.profile})}
  6 +
  7 + .checkbox if='{settings.enabled}'
  8 + label name='anonymous'
  9 + input type='checkbox' name='anonymous' value='1' checked='{settings.anonymous}' onchange='{toggleAnonymous}'
  10 + |{anl.t('views.stats.anonymous')}
  11 +
  12 + javascript:
  13 + this.anl = window.analytics
  14 + this.settings = opts.settings
  15 + this.updateUrl = Routes.analytics_plugin_stats_path({profile: noosfero.profile, action: 'edit'})
  16 +
  17 + toggleEnabled (e) {
  18 + this.settings.enabled = !this.settings.enabled
  19 + this.update()
  20 + this.save(e)
  21 + }
  22 + toggleAnonymous (e) {
  23 + this.settings.anonymous = !this.settings.anonymous
  24 + this.save(e)
  25 + }
  26 +
  27 + save (e) {
  28 + var self = this
  29 + $.post(this.updateUrl, {analytics_settings: this.settings}, function() {
  30 + display_notice(self.anl.t('views.stats.config_save'))
  31 + })
  32 + }
  33 +
... ...
plugins/analytics/test/functional/content_viewer_controller_test.rb
... ... @@ -37,7 +37,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
37 37 @request.env['HTTP_REFERER'] = first_url
38 38 get :view_page, profile: @community.identifier, page: @community.articles.last.path.split('/')
39 39 assert_equal 2, @community.page_views.count
40   - assert_equal 2, @community.visits.count
  40 + assert_equal 1, @community.visits.count
41 41  
42 42 second_page_view = @community.page_views.order(:id).last
43 43 assert_equal first_page_view, second_page_view.referer_page_view
... ... @@ -48,7 +48,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
48 48 future = Time.now + 2*AnalyticsPlugin::TimeOnPageUpdateInterval
49 49 Time.stubs(:now).returns(future)
50 50 get :view_page, profile: @community.identifier, page: @community.articles.last.path.split('/')
51   - assert_equal 3, @community.visits.count
  51 + assert_equal 2, @community.visits.count
52 52 end
53 53  
54 54 end
... ...
plugins/analytics/views/analytics_plugin/stats/_table.html.slim
1 1  
2   -table#analytics-stats.table data-toggle='table' data-striped='true' data-sortable='true' data-icons-prefix='fa'
3   - thead
4   - - unless profile.analytics_anonymous?
  2 +.table-responsive
  3 + table#analytics-stats.table data-toggle='table' data-striped='true' data-sortable='true' data-icons-prefix='fa'
  4 + thead
5 5 th= t'analytics_plugin.views.stats.user'
6   - th= t'analytics_plugin.views.stats.initial_time'
7   - th= t'analytics_plugin.views.stats.pages'
  6 + th= t'analytics_plugin.views.stats.initial_time'
  7 + th= t'analytics_plugin.views.stats.ip'
  8 + th= t'analytics_plugin.views.stats.pages'
8 9  
9   - tbody
10   - - profile.visits.each do |visit|
11   - tr
12   - td= link_to visit.user.name, visit.user.url
13   - td
14   - div data-toggle="tooltip" data-title='#{l visit.initial_time}'
15   - = time_ago_in_words(visit.initial_time)
16   - |&nbsp
17   - = _'ago'
18   - td
19   - - visit.page_views.each do |page_view|
20   - = link_to page_view.url, page_view.url
21   - |&nbsp;
22   - = "(#{distance_of_time_in_words page_view.time_on_page})"
23   - |&nbsp;->&nbsp;
  10 + tbody
  11 + - visits.each do |visit|
  12 + tr data-visit-id='#{visit.id}'
  13 + td= link_to visit.user.name, visit.user.url if visit.user
  14 + td
  15 + div data-toggle="tooltip" data-title='#{l visit.initial_time}'
  16 + = time_ago_in_words visit.initial_time
  17 + |&nbsp
  18 + = _'ago'
  19 + td= visit.users_page_views.first.remote_ip
  20 + td
  21 + ol
  22 + - visit.users_page_views.each do |page_view|
  23 + li
  24 + = link_to (if page_view.title.present? then page_view.title else page_view.url end), page_view.url, target: '_blank'
  25 + |&nbsp;
  26 + = "(#{distance_of_time_in_words page_view.time_on_page})"
24 27  
25 28 javascript:
26 29 $('#analytics-stats').bootstrapTable({
27 30 striped: true,
28   - columns: [
29   - {sortable: true},
30   - {sortable: true},
31   - {sortable: true},
32   - ],
33 31 })
34 32  
35 33 $(document).ready(function() {
... ...
plugins/analytics/views/analytics_plugin/stats/index.html.slim
1   -- content_for :head
2   - = javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.8.1/bootstrap-table-all.min.js'
3   - = stylesheet_link_tag 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.8.1/bootstrap-table.css'
  1 += render 'shared/bootstrap_table'
  2 +
  3 += button :back, _('Back to control panel'), controller: 'profile_editor'
  4 +
  5 += js_translations_include plugin: :analytics
  6 += javascript_include_tag 'plugins/analytics/javascripts/views/settings'
  7 +analytics-settings data-opts="#{CGI.escapeHTML({settings: {enabled: profile.analytics_settings.enabled, anonymous: profile.analytics_settings.anonymous}}.to_json)}" data-riot=''
  8 +/ needs html_safe to work
  9 +/= riot_component :analytics_settings, settings: {enabled: profile.analytics_settings.enabled, anonymous: profile.analytics_settings.anonymous}
  10 +
  11 += render 'table', visits: profile.users_visits.limit(50)
4 12  
5   -= render 'table'
... ...
plugins/custom_forms/lib/custom_forms_plugin/helper.rb
... ... @@ -71,7 +71,7 @@ module CustomFormsPlugin::Helper
71 71 def display_custom_field(field, submission, form)
72 72 sanitized_name = ActionView::Base.white_list_sanitizer.sanitize field.name
73 73 answer = submission.answers.select{|answer| answer.field == field}.first
74   - field_tag = send("display_#{type_for_options(field.class)}",field, answer, form)
  74 + field_tag = send("display_#{type_for_options(field.class)}",field, answer, form).html_safe
75 75 if field.mandatory? && submission.id.nil?
76 76 required(labelled_form_field(sanitized_name, field_tag))
77 77 else
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb
... ... @@ -12,7 +12,7 @@
12 12 <%= f.hidden_field(:position) %>
13 13  
14 14 <%= f.hidden_field :_destroy, :class => 'destroy-field' %>
15   - <%= button_to_function :delete, _('Remove field'), "customFormsPlugin.removeFieldBox(this, #{CGI::escapeHTML(_('Are you sure you want to remove this field?').to_json)})" %>
  15 + <%= button_to_function :delete, _('Remove field'), "customFormsPlugin.removeFieldBox(this, #{_('Are you sure you want to remove this field?').to_json})" %>
16 16 <%= yield %>
17 17 </div>
18 18 </fieldset>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb
... ... @@ -51,8 +51,8 @@
51 51 </ul>
52 52  
53 53 <div class="addition-buttons">
54   - <%= button(:add, _('Add a new text field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{CGI::escapeHTML(html_for_field(f, :fields, CustomFormsPlugin::TextField).to_json)}); return false")%>
55   - <%= button(:add, _('Add a new select field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{CGI::escapeHTML(html_for_field(f, :fields, CustomFormsPlugin::SelectField).to_json)}); return false")%>
  54 + <%= button(:add, _('Add a new text field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{html_for_field(f, :fields, CustomFormsPlugin::TextField).to_json}); return false")%>
  55 + <%= button(:add, _('Add a new select field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{html_for_field(f, :fields, CustomFormsPlugin::SelectField).to_json}); return false")%>
56 56 </div>
57 57  
58 58 <%= button_bar do %>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb
... ... @@ -7,6 +7,6 @@
7 7  
8 8 <td>
9 9 <%= f.hidden_field :_destroy, :class => 'destroy-field' %>
10   - <%= button_to_function_without_text :remove, _('Remove alternative'), "customFormsPlugin.removeAlternative(this, #{CGI::escapeHTML(_('Are you sure you want to remove this alternative?').to_json)})", :class => 'remove-field', :title => _('Remove alternative') %>
  10 + <%= button_to_function_without_text :remove, _('Remove alternative'), "customFormsPlugin.removeAlternative(this, #{_('Are you sure you want to remove this alternative?').to_json})", :class => 'remove-field', :title => _('Remove alternative') %>
11 11 </td>
12 12 </tr>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb
... ... @@ -22,7 +22,7 @@
22 22 <tfoot>
23 23 <tr class="addition-buttons">
24 24 <td colspan="3">
25   - <%= button(:add, _('Add a new alternative'), '#', :onclick => "customFormsPlugin.addFields(this, 'alternatives', #{CGI::escapeHTML(html_for_field(f, :alternatives, CustomFormsPlugin::Alternative).to_json)}); return false") %>
  25 + <%= button(:add, _('Add a new alternative'), '#', :onclick => "customFormsPlugin.addFields(this, 'alternatives', #{html_for_field(f, :alternatives, CustomFormsPlugin::Alternative).to_json}); return false") %>
26 26 </td>
27 27 </tr>
28 28 </tfoot>
... ...
plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb
1 1 <div id="custom-forms-plugin_submission">
2 2  
3 3 <h1><%= @form.name %></h1>
4   -<p><%= @form.description %></p>
  4 +<p><%= (@form.description || "").html_safe %></p>
5 5  
6 6 <% if @submission.id.nil? %>
7 7 <% if @form.expired? %>
... ...
plugins/custom_forms/views/shared/_form_submission.html.erb
1 1 <% self.extend(CustomFormsPlugin::Helper) %>
2 2  
3 3 <% @form.fields.each do |field| %>
4   - <%= display_custom_field(field, @submission, f.object_name) %>
  4 + <%= display_custom_field(field, @submission, f.object_name).html_safe %>
5 5 <% end %>
... ...
plugins/oauth_client/Gemfile
1 1 gem 'omniauth', '~> 1.2.2'
2 2 gem 'omniauth-facebook', '~> 2.0.0'
  3 +gem 'omniauth-twitter', '~> 1.0.1'
3 4 gem "omniauth-google-oauth2", '~> 0.2.6'
4 5 gem "omniauth-oauth2", '~> 1.3.1'
  6 +gem "omniauth-github", '~> 1.1.2'
... ...
plugins/oauth_client/README.md
... ... @@ -33,6 +33,20 @@ Facebook
33 33  
34 34 [Create Facebook application](https://developers.facebook.com/docs/facebook-login/v2.1)
35 35  
  36 +Github
  37 +--------
  38 +
  39 +[Create Github application](https://github.com/settings/developers)
  40 +
  41 +Twitter
  42 +--------
  43 +
  44 +- Specially on twitter you need to request user's email address, see more
  45 +in https://dev.twitter.com/rest/reference/get/account/verify_credentials
  46 +
  47 +[Create Twitter application](https://apps.twitter.com/)
  48 +
  49 +
36 50 Callback
37 51 ========
38 52  
... ...
plugins/oauth_client/features/create_provider.feature 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +Feature: Create Twitter provider
  2 + As a environment admin
  3 + I want to be able to create a new twitter provider
  4 + So that users can login wth different strategies
  5 +
  6 +Background:
  7 + Given "OauthProvider" plugin is enabled
  8 + And I am logged in as admin
  9 + And I go to /admin/plugins
  10 + And I check "Oauth Client Plugin"
  11 + And I press "Save changes"
  12 +
  13 +Scenario: Create a twitter provider
  14 + Given I go to /admin/plugin/oauth_client/new
  15 + And I fill in "oauth_client_plugin_provider_name" with "myid"
  16 + And I fill in "oauth_client_plugin_provider[name]" with "google"
  17 + And I fill in "oauth_client_plugin_provider_client_secret" with "mysecret"
  18 + And I check "oauth_client_plugin_provider[enabled]"
  19 + And I select "twitter" from "oauth_client_plugin_provider_strategy"
  20 + Then I should see "To use this provider you need to request the user email in your app"
... ...
plugins/oauth_client/lib/oauth_client_plugin.rb
... ... @@ -31,13 +31,20 @@ class OauthClientPlugin &lt; Noosfero::Plugin
31 31  
32 32 PROVIDERS = {
33 33 :facebook => {
34   - :name => 'Facebook'
  34 + :name => 'Facebook',
  35 + :info_fields => 'name,email'
35 36 },
36 37 :google_oauth2 => {
37 38 :name => 'Google'
38 39 },
39 40 :noosfero_oauth2 => {
40 41 :name => 'Noosfero'
  42 + },
  43 + :github => {
  44 + :name => 'Github'
  45 + },
  46 + :twitter => {
  47 + :name => 'Twitter'
41 48 }
42 49 }
43 50  
... ... @@ -62,8 +69,9 @@ class OauthClientPlugin &lt; Noosfero::Plugin
62 69 provider_id = request.params['id']
63 70 provider_id ||= request.session['omniauth.params']['id'] if request.session['omniauth.params']
64 71 provider = environment.oauth_providers.find(provider_id)
  72 + strategy.options.merge! consumer_key: provider.client_id, consumer_secret: provider.client_secret
65 73 strategy.options.merge! client_id: provider.client_id, client_secret: provider.client_secret
66   - strategy.options.merge! provider.options.symbolize_keys
  74 + strategy.options.merge! options
67 75  
68 76 request.session[:provider_id] = provider_id
69 77 }
... ... @@ -98,4 +106,8 @@ class OauthClientPlugin &lt; Noosfero::Plugin
98 106 }
99 107 end
100 108  
  109 + def js_files
  110 + ["script.js"]
  111 + end
  112 +
101 113 end
... ...
plugins/oauth_client/public/script.js 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +$(document).ready(function(){
  2 + select_box_event();
  3 +});
  4 +
  5 +var toggle_info_message = function(){
  6 + var selected_option = $("#oauth_client_plugin_provider_strategy option:selected");
  7 + if (selected_option.length){
  8 + if (selected_option.val() === "twitter"){
  9 + $(".remember-enable-email").removeClass("hidden");
  10 + } else {
  11 + $(".remember-enable-email").addClass("hidden");
  12 + }
  13 + }
  14 +};
  15 +
  16 +var select_box_event = function(){
  17 + var select_box = $("#oauth_client_plugin_provider_strategy");
  18 + select_box.on("change",function(){
  19 + toggle_info_message();
  20 + });
  21 +};
... ...
plugins/oauth_client/public/style.css
... ... @@ -16,3 +16,7 @@
16 16 .oauth-login .provider .developer {
17 17 display: none;
18 18 }
  19 +
  20 +.remember-enable-email.hidden {
  21 + display: none;
  22 +}
... ...
plugins/oauth_client/views/oauth_client_plugin_admin/edit.html.erb
... ... @@ -15,6 +15,10 @@
15 15 <%= labelled_form_field _('Strategy'), f.select(:strategy, OauthClientPlugin::PROVIDERS) %>
16 16 </div>
17 17  
  18 + <div class="remember-enable-email hidden">
  19 + <span class="error"><%=_('To use this provider you need to request the user email in your app')%></span>
  20 + </div>
  21 +
18 22 <div class="client-id">
19 23 <%= labelled_form_field _('Client Id'), f.text_field(:client_id) %>
20 24 </div>
... ...
plugins/person_tags/features/person_tags.feature
... ... @@ -10,9 +10,9 @@ Background:
10 10 Scenario: add tags to person
11 11 Given I am on joao's control panel
12 12 And I follow "Edit Profile"
13   - When I fill in "profile_data_interest_list" with "linux,debian"
  13 + When I fill in "profile_data_tag_list" with "linux,debian"
14 14 And I press "Save"
15 15 And I go to joao's control panel
16 16 And I follow "Edit Profile"
17   - Then the "profile_data_interest_list" field should contain "linux"
18   - And the "profile_data_interest_list" field should contain "debian"
  17 + Then the "profile_data_tag_list" field should contain "linux"
  18 + And the "profile_data_tag_list" field should contain "debian"
... ...
plugins/person_tags/lib/ext/person.rb
1 1 require_dependency 'person'
2 2  
3 3 class Person
4   - attr_accessible :interest_list
  4 + attr_accessible :tag_list
5 5  
6   - acts_as_taggable_on :interests
  6 + acts_as_taggable_on :tags
7 7 N_('Fields of interest')
8 8 end
... ...
plugins/person_tags/lib/person_tags_plugin.rb
... ... @@ -19,4 +19,18 @@ class PersonTagsPlugin &lt; Noosfero::Plugin
19 19 def self.api_mount_points
20 20 [PersonTagsPlugin::API]
21 21 end
  22 +
  23 + def self.extra_blocks
  24 + {
  25 + PersonTagsPlugin::InterestsBlock => { type: Person }
  26 + }
  27 + end
  28 +
  29 + def self.has_admin_url?
  30 + false
  31 + end
  32 +
  33 + def stylesheet?
  34 + true
  35 + end
22 36 end
... ...
plugins/person_tags/lib/person_tags_plugin/api.rb
... ... @@ -3,7 +3,7 @@ class PersonTagsPlugin::API &lt; Grape::API
3 3 get ':id/tags' do
4 4 person = environment.people.visible.find_by(id: params[:id])
5 5 return not_found! if person.blank?
6   - present person.interest_list
  6 + present person.tag_list
7 7 end
8 8 end
9 9 end
... ...
plugins/person_tags/lib/person_tags_plugin/interests_block.rb 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +class PersonTagsPlugin::InterestsBlock < Block
  2 + def view_title
  3 + self.default_title
  4 + end
  5 +
  6 + def tags
  7 + owner.tag_list
  8 + end
  9 +
  10 + def extra_option
  11 + {}
  12 + end
  13 +
  14 + def self.description
  15 + _('Fields of Interest')
  16 + end
  17 +
  18 + def help
  19 + _('Things that this person is interested in')
  20 + end
  21 +
  22 + def default_title
  23 + _('Fields of Interest')
  24 + end
  25 +
  26 + def self.expire_on
  27 + { profile: [:profile] }
  28 + end
  29 +end
... ...
plugins/person_tags/public/style.css 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +.person-tags-block ul {
  2 + padding: 0;
  3 + margin: 0;
  4 +}
  5 +
  6 +.person-tags-block li {
  7 + float: left;
  8 + list-style: none;
  9 + padding: 5px;
  10 + color: #fff;
  11 + background: #000;
  12 + margin: 5px;
  13 +}
... ...
plugins/person_tags/test/unit/api_test.rb
... ... @@ -10,7 +10,7 @@ class APITest &lt; ActiveSupport::TestCase
10 10  
11 11 should 'return tags for a person' do
12 12 person = create_user('person').person
13   - person.interest_list.add('linux')
  13 + person.tag_list.add('linux')
14 14 person.save!
15 15 person.reload
16 16 get "/api/v1/people/#{person.id}/tags?#{params.to_query}"
... ...
plugins/person_tags/test/unit/person_tags_test.rb
... ... @@ -7,10 +7,10 @@ class PersonTagsPluginTest &lt; ActiveSupport::TestCase
7 7 @environment.enable_plugin(PersonTagsPlugin)
8 8 end
9 9  
10   - should 'have interests' do
  10 + should 'have tags' do
11 11 person = create_user('person').person
12   - assert_equal [], person.interests
13   - person.interest_list.add('linux')
14   - assert_equal ['linux'], person.interest_list
  12 + assert_equal [], person.tags
  13 + person.tag_list.add('linux')
  14 + assert_equal ['linux'], person.tag_list
15 15 end
16 16 end
... ...
plugins/person_tags/views/blocks/interests.html.erb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +<%= block_title(block.view_title, block.subtitle) %>
  2 +
  3 +<div class="person-tags-block">
  4 + <% unless block.tags.size == 0 %>
  5 + <ul>
  6 + <% block.tags.each do |tag| %>
  7 + <li><%= tag %></li>
  8 + <% end %>
  9 + </ul>
  10 + <% else %>
  11 + <div class="person-tags-block-none"><%= c_('None') %></div>
  12 + <% end %>
  13 + <br style="clear:both" />
  14 +</div>
... ...
plugins/person_tags/views/environment_design 0 → 120000
... ... @@ -0,0 +1 @@
  1 +box_organizer
0 2 \ No newline at end of file
... ...
plugins/person_tags/views/profile-editor-extras.html.erb
1 1 <h2><%= _('Select your fields of interest') %></h2>
2   -<%= text_field_tag('profile_data[interest_list]', context.profile.interest_list.join(','), size: 64) %>
  2 +<%= text_field_tag('profile_data[tag_list]', context.profile.tag_list.join(','), size: 64) %>
3 3 <br />
4 4 <%= content_tag( 'small', _('Separate tags with commas') ) %>
5 5  
6 6 <script>
7   - jQuery('#profile_data_interest_list').inputosaurus();
  7 + jQuery('#profile_data_tag_list').inputosaurus();
8 8 </script>
... ...
plugins/person_tags/views/profile_design 0 → 120000
... ... @@ -0,0 +1 @@
  1 +box_organizer
0 2 \ No newline at end of file
... ...
plugins/responsive/views/layouts/_usermenu_logged_in.html.slim
... ... @@ -10,7 +10,7 @@ li.dropdown
10 10  
11 11 ul class='dropdown-menu' role='menu'
12 12 li
13   - = link_to user.public_profile_url, id: "homepage-link", title: _('Go to your homepage')
  13 + = link_to user.url, id: 'homepage-link', title: _('Go to your homepage')
14 14 span class='icon-person' = _('Profile')
15 15 li.divider
16 16  
... ...
plugins/work_assignment/lib/work_assignment_plugin/email_contact.rb
... ... @@ -50,13 +50,13 @@ class WorkAssignmentPlugin::EmailContact
50 50 mail(options)
51 51 end
52 52  
53   - def build_mail_message(email_contact, uploaded_files)
  53 + def self.build_mail_message(email_contact, uploaded_files)
54 54 message = ""
55 55 if uploaded_files && uploaded_files.first && uploaded_files.first.parent && uploaded_files.first.parent.parent
56 56 article = uploaded_files.first.parent.parent
57 57 message = article.default_email + "<br>"
58 58 uploaded_files.each do |file|
59   - url = url_for(file.url)
  59 + url = Rails.application.routes.url_helpers.url_for(file.url)
60 60 message += "<br><a href='#{url}'>#{url}</a>"
61 61 end
62 62 end
... ...
plugins/work_assignment/lib/work_assignment_plugin/helper.rb
... ... @@ -16,7 +16,7 @@ module WorkAssignmentPlugin::Helper
16 16 end
17 17  
18 18 def display_author_folder(author_folder, user)
19   - return if author_folder.children.empty?
  19 + return if author_folder.children(true).empty?
20 20 content_tag('tr',
21 21 content_tag('td', link_to_last_submission(author_folder, user)) +
22 22 content_tag('td', time_format(author_folder.children.last.created_at)) +
... ...
plugins/work_assignment/test/functional/content_viewer_controller_test.rb
... ... @@ -35,6 +35,14 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
35 35 assert_response :success
36 36 end
37 37  
  38 + should 'display users submissions' do
  39 + folder = work_assignment.find_or_create_author_folder(@person)
  40 + submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => folder)
  41 + get :view_page, :profile => @organization.identifier, :page => work_assignment.path
  42 + assert_response :success
  43 + assert_match /rails.png/, @response.body
  44 + end
  45 +
38 46 should "display 'Upload files' when create children of image gallery" do
39 47 login_as(profile.identifier)
40 48 f = Gallery.create!(:name => 'gallery', :profile => profile)
... ...
po/pt/noosfero.po
... ... @@ -13,8 +13,8 @@ msgid &quot;&quot;
13 13 msgstr ""
14 14 "Project-Id-Version: 1.3~rc2-8-g01ea9f7\n"
15 15 "POT-Creation-Date: 2015-11-04 12:36-0300\n"
16   -"PO-Revision-Date: 2016-03-14 15:58+0000\n"
17   -"Last-Translator: Eduardo Vital <vitaldu@gmail.com>\n"
  16 +"PO-Revision-Date: 2016-06-20 20:14+0000\n"
  17 +"Last-Translator: Gabriel Silva <gabriel93.silva@gmail.com>\n"
18 18 "Language-Team: Portuguese "
19 19 "<https://hosted.weblate.org/projects/noosfero/noosfero/pt/>\n"
20 20 "Language: pt\n"
... ... @@ -22,7 +22,7 @@ msgstr &quot;&quot;
22 22 "Content-Type: text/plain; charset=UTF-8\n"
23 23 "Content-Transfer-Encoding: 8bit\n"
24 24 "Plural-Forms: nplurals=2; plural=n != 1;\n"
25   -"X-Generator: Weblate 2.5\n"
  25 +"X-Generator: Weblate 2.7-dev\n"
26 26  
27 27 #: app/models/approve_comment.rb:17
28 28 msgid "Anonymous"
... ... @@ -4141,7 +4141,7 @@ msgstr &quot;%s não pôde ser desabilitado&quot;
4141 4141  
4142 4142 #: app/controllers/admin/organizations_controller.rb:52
4143 4143 msgid "%s removed"
4144   -msgstr "% foi removido"
  4144 +msgstr "%s foi removido"
4145 4145  
4146 4146 #: app/controllers/admin/organizations_controller.rb:54
4147 4147 msgid "%s could not be removed"
... ...
test/unit/noosfero_test.rb
... ... @@ -43,10 +43,12 @@ class NoosferoTest &lt; ActiveSupport::TestCase
43 43 end
44 44  
45 45 should 'change locale temporarily' do
46   - Noosfero.with_locale('pt') do
47   - assert_equal 'pt', FastGettext.locale
  46 + current_locale = FastGettext.locale
  47 + another_locale = current_locale == 'pt' ? 'en' : 'pt'
  48 + Noosfero.with_locale(another_locale) do
  49 + assert_equal another_locale, FastGettext.locale
48 50 end
49   - assert_equal 'en', FastGettext.locale
  51 + assert_equal current_locale, FastGettext.locale
50 52 end
51 53  
52 54 should "use default hostname of default environment as hostname of Noosfero instance" do
... ...