Compare View
Commits (54)
-
- Environments and profiles now return the layout template used. Signed-off-by: Tallys Martins <tallysmartins@gmail.com>
-
Display layout_template on api - Environments and profiles now return the layout template used. @marcosronaldo can you take a look at this? We'll use it on angular theme. See merge request !968
-
Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com>
-
Organization_ratings: Show rejected message to admins Show rejected message to admins on organization_ratings plugin. Only environment admins can see the rejected message. Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> See merge request !969
-
analytics: identify bots and filter them out by default This needs riot.js/serializers/i18n-js/js-routes See merge request !735
-
Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Luan Guimarães <guimaraesluan@me.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Omar Junior <omarroinuj@gmail.com> Signed-off-by: Tallys Martins <tallysmartins@gmail.com>
-
Fix work assignment plugin issues on rails 4 - Fixed submissions not being displayed on work assignment page - Fixed email notifications not being sent See merge request !967
-
… recent activities of the profile who owns it
-
Recent activities Adding a plugin "recent_activities" which adds a block that list the recent activities of the profile who owns it:  See merge request !972
-
The profile activities returns action trackers and scraps, but the scraps should not be displayed on recent activities block. Only the action tracker records Related to merge request !972
-
spaminator: update mailer to rails4 new scheme See merge request !971
-
api: add and remove members from profile See merge request !977
-
Signed-off-by: Alessandro Caetano <alessandro.caetanob@gmail.com> Signed-off-by: Artur Bersan de Faria <arturbersan@gmail.com> Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Matheus Miranda <matheusmirandalacerda@gmail.com> Signed-off-by: Sabryna Sousa <sabryna.sousa1323@gmail.com> Signed-off-by: Victor Matias Navarro <victor.matias.navarro@gmail.com> Signed-off-by: Vitor Barbosa <vitormga15@gmail.com>
-
Concern needs to be included before first use of setting items
-
Lists and edits followers and circles in control panel of profile that is being viewed instead of logged in person. Also unfollow person in control panel based on current viewed profile instead of current logged in user. This is necessary because sometimes an environment admin is editing someone else's profile and those actions should be performed on that profile instead of admin's profile.
-
Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com>
-
Profile followers feature Signed-off-by: Alessandro Caetano <alessandro.caetanob@gmail.com> Signed-off-by: Artur Bersan de Faria <arturbersan@gmail.com> Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Matheus Miranda <matheusmirandalacerda@gmail.com> Signed-off-by: Sabryna Sousa <sabryna.sousa1323@gmail.com> Signed-off-by: Victor Matias Navarro <victor.matias.navarro@gmail.com> Signed-off-by: Vitor Barbosa <vitormga15@gmail.com> See merge request !976
-
-Fix undefined 'to_model' when creating a new applicationa -Upgrade doorkeeper to 2.2.0 -Change several html forms to conform with the new version Signed-off-by: Gustavo Jaruga Cruz <darksshades@gmail.com> Signed-off-by: Thiago Ribeiro <thiagitosouza@gmail.com>
Showing
300 changed files
Show diff stats
app/api/entities.rb
... | ... | @@ -124,6 +124,7 @@ module Api |
124 | 124 | expose :type |
125 | 125 | expose :custom_header |
126 | 126 | expose :custom_footer |
127 | + expose :layout_template | |
127 | 128 | expose :permissions do |profile, options| |
128 | 129 | Entities.permissions_for_entity(profile, options[:current_person], |
129 | 130 | :allow_post_content?, :allow_edit?, :allow_destroy?) |
... | ... | @@ -264,6 +265,7 @@ module Api |
264 | 265 | expose :name |
265 | 266 | expose :id |
266 | 267 | expose :description |
268 | + expose :layout_template | |
267 | 269 | expose :settings, if: lambda { |instance, options| options[:is_admin] } |
268 | 270 | end |
269 | 271 | ... | ... |
app/api/helpers.rb
... | ... | @@ -302,12 +302,12 @@ module Api |
302 | 302 | end |
303 | 303 | |
304 | 304 | def cant_be_saved_request!(attribute) |
305 | - message = _("(Invalid request) %s can't be saved") % attribute | |
305 | + message = _("(Invalid request) %s can't be saved").html_safe % attribute | |
306 | 306 | render_api_error!(message, 400) |
307 | 307 | end |
308 | 308 | |
309 | 309 | def bad_request!(attribute) |
310 | - message = _("(Invalid request) %s not given") % attribute | |
310 | + message = _("(Invalid request) %s not given").html_safe % attribute | |
311 | 311 | render_api_error!(message, 400) |
312 | 312 | end |
313 | 313 | ... | ... |
app/api/v1/people.rb
... | ... | @@ -119,6 +119,20 @@ module Api |
119 | 119 | members = select_filtered_collection_of(profile, 'members', params) |
120 | 120 | present members, :with => Entities::Person, :current_person => current_person |
121 | 121 | end |
122 | + | |
123 | + post do | |
124 | + authenticate! | |
125 | + profile = environment.profiles.find_by id: params[:profile_id] | |
126 | + profile.add_member(current_person) rescue forbidden! | |
127 | + {pending: !current_person.is_member_of?(profile)} | |
128 | + end | |
129 | + | |
130 | + delete do | |
131 | + authenticate! | |
132 | + profile = environment.profiles.find_by id: params[:profile_id] | |
133 | + profile.remove_member(current_person) | |
134 | + present current_person, :with => Entities::Person, :current_person => current_person | |
135 | + end | |
122 | 136 | end |
123 | 137 | end |
124 | 138 | end | ... | ... |
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/application_controller.rb
... | ... | @@ -14,6 +14,20 @@ class ApplicationController < ActionController::Base |
14 | 14 | before_filter :redirect_to_current_user |
15 | 15 | |
16 | 16 | before_filter :set_session_theme |
17 | + | |
18 | + # FIXME: only include necessary methods | |
19 | + include ApplicationHelper | |
20 | + | |
21 | + # concerns | |
22 | + include PermissionCheck | |
23 | + include CustomDesign | |
24 | + include NeedsProfile | |
25 | + | |
26 | + # implementations | |
27 | + include FindByContents | |
28 | + include Noosfero::Plugin::HotSpot | |
29 | + include SearchTermHelper | |
30 | + | |
17 | 31 | def set_session_theme |
18 | 32 | if params[:theme] |
19 | 33 | session[:theme] = environment.theme_ids.include?(params[:theme]) ? params[:theme] : nil |
... | ... | @@ -48,7 +62,6 @@ class ApplicationController < ActionController::Base |
48 | 62 | end |
49 | 63 | end |
50 | 64 | |
51 | - include ApplicationHelper | |
52 | 65 | layout :get_layout |
53 | 66 | def get_layout |
54 | 67 | return false if request.format == :js or request.xhr? |
... | ... | @@ -74,9 +87,6 @@ class ApplicationController < ActionController::Base |
74 | 87 | helper :document |
75 | 88 | helper :language |
76 | 89 | |
77 | - include DesignHelper | |
78 | - include PermissionCheck | |
79 | - | |
80 | 90 | before_filter :set_locale |
81 | 91 | def set_locale |
82 | 92 | FastGettext.available_locales = environment.available_locales |
... | ... | @@ -89,8 +99,6 @@ class ApplicationController < ActionController::Base |
89 | 99 | end |
90 | 100 | end |
91 | 101 | |
92 | - include NeedsProfile | |
93 | - | |
94 | 102 | attr_reader :environment |
95 | 103 | |
96 | 104 | # declares that the given <tt>actions</tt> cannot be accessed by other HTTP |
... | ... | @@ -107,6 +115,10 @@ class ApplicationController < ActionController::Base |
107 | 115 | |
108 | 116 | protected |
109 | 117 | |
118 | + def accept_only_post | |
119 | + return render_not_found if !request.post? | |
120 | + end | |
121 | + | |
110 | 122 | def verified_request? |
111 | 123 | super || form_authenticity_token == request.headers['X-XSRF-TOKEN'] |
112 | 124 | end |
... | ... | @@ -151,8 +163,6 @@ class ApplicationController < ActionController::Base |
151 | 163 | end |
152 | 164 | end |
153 | 165 | |
154 | - include Noosfero::Plugin::HotSpot | |
155 | - | |
156 | 166 | # FIXME this filter just loads @plugins to children controllers and helpers |
157 | 167 | def init_noosfero_plugins |
158 | 168 | plugins |
... | ... | @@ -184,9 +194,6 @@ class ApplicationController < ActionController::Base |
184 | 194 | end |
185 | 195 | end |
186 | 196 | |
187 | - include SearchTermHelper | |
188 | - include FindByContents | |
189 | - | |
190 | 197 | def find_suggestions(query, context, asset, options={}) |
191 | 198 | plugins.dispatch_first(:find_suggestions, query, context, asset, options) |
192 | 199 | end | ... | ... |
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 | ... | ... |
... | ... | @@ -0,0 +1,169 @@ |
1 | +module AuthenticatedSystem | |
2 | + | |
3 | + protected | |
4 | + | |
5 | + extend ActiveSupport::Concern | |
6 | + | |
7 | + included do | |
8 | + if self < ActionController::Base | |
9 | + around_filter :user_set_current | |
10 | + before_filter :override_user | |
11 | + before_filter :login_from_cookie | |
12 | + end | |
13 | + | |
14 | + # Inclusion hook to make #current_user and #logged_in? | |
15 | + # available as ActionView helper methods. | |
16 | + helper_method :current_user, :logged_in? | |
17 | + end | |
18 | + | |
19 | + # Returns true or false if the user is logged in. | |
20 | + # Preloads @current_user with the user model if they're logged in. | |
21 | + def logged_in? | |
22 | + current_user != nil | |
23 | + end | |
24 | + | |
25 | + # Accesses the current user from the session. | |
26 | + def current_user user_id = session[:user] | |
27 | + @current_user ||= begin | |
28 | + user = User.find_by id: user_id if user_id | |
29 | + user.session = session if user | |
30 | + User.current = user | |
31 | + user | |
32 | + end | |
33 | + end | |
34 | + | |
35 | + # Store the given user in the session. | |
36 | + def current_user=(new_user) | |
37 | + if new_user.nil? | |
38 | + session.delete(:user) | |
39 | + else | |
40 | + session[:user] = new_user.id | |
41 | + new_user.session = session | |
42 | + new_user.register_login | |
43 | + end | |
44 | + @current_user = User.current = new_user | |
45 | + end | |
46 | + | |
47 | + # See impl. from http://stackoverflow.com/a/2513456/670229 | |
48 | + def user_set_current | |
49 | + User.current = current_user | |
50 | + yield | |
51 | + ensure | |
52 | + # to address the thread variable leak issues in Puma/Thin webserver | |
53 | + User.current = nil | |
54 | + end | |
55 | + | |
56 | + # Check if the user is authorized. | |
57 | + # | |
58 | + # Override this method in your controllers if you want to restrict access | |
59 | + # to only a few actions or if you want to check if the user | |
60 | + # has the correct rights. | |
61 | + # | |
62 | + # Example: | |
63 | + # | |
64 | + # # only allow nonbobs | |
65 | + # def authorize? | |
66 | + # current_user.login != "bob" | |
67 | + # end | |
68 | + def authorized? | |
69 | + true | |
70 | + end | |
71 | + | |
72 | + # Filter method to enforce a login requirement. | |
73 | + # | |
74 | + # To require logins for all actions, use this in your controllers: | |
75 | + # | |
76 | + # before_filter :login_required | |
77 | + # | |
78 | + # To require logins for specific actions, use this in your controllers: | |
79 | + # | |
80 | + # before_filter :login_required, :only => [ :edit, :update ] | |
81 | + # | |
82 | + # To skip this in a subclassed controller: | |
83 | + # | |
84 | + # skip_before_filter :login_required | |
85 | + # | |
86 | + def login_required | |
87 | + username, passwd = get_auth_data | |
88 | + if username && passwd | |
89 | + self.current_user ||= User.authenticate(username, passwd) || nil | |
90 | + end | |
91 | + if logged_in? && authorized? | |
92 | + true | |
93 | + else | |
94 | + if params[:require_login_popup] | |
95 | + render :json => { :require_login_popup => true } | |
96 | + else | |
97 | + access_denied | |
98 | + end | |
99 | + end | |
100 | + end | |
101 | + | |
102 | + # Redirect as appropriate when an access request fails. | |
103 | + # | |
104 | + # The default action is to redirect to the login screen. | |
105 | + # | |
106 | + # Override this method in your controllers if you want to have special | |
107 | + # behavior in case the user is not authorized | |
108 | + # to access the requested action. For example, a popup window might | |
109 | + # simply close itself. | |
110 | + def access_denied | |
111 | + respond_to do |accepts| | |
112 | + accepts.html do | |
113 | + if request.xhr? | |
114 | + render :text => _('Access denied'), :status => 401 | |
115 | + else | |
116 | + store_location | |
117 | + redirect_to :controller => '/account', :action => 'login' | |
118 | + end | |
119 | + end | |
120 | + accepts.xml do | |
121 | + headers["Status"] = "Unauthorized" | |
122 | + headers["WWW-Authenticate"] = %(Basic realm="Web Password") | |
123 | + render :text => "Could't authenticate you", :status => '401 Unauthorized' | |
124 | + end | |
125 | + end | |
126 | + false | |
127 | + end | |
128 | + | |
129 | + # Store the URI of the current request in the session. | |
130 | + # | |
131 | + # We can return to this location by calling #redirect_back_or_default. | |
132 | + def store_location(location = request.url) | |
133 | + session[:return_to] = location | |
134 | + end | |
135 | + | |
136 | + # Redirect to the URI stored by the most recent store_location call or | |
137 | + # to the passed default. | |
138 | + def redirect_back_or_default(default) | |
139 | + if session[:return_to] | |
140 | + redirect_to(session.delete(:return_to)) | |
141 | + else | |
142 | + redirect_to(default) | |
143 | + end | |
144 | + end | |
145 | + | |
146 | + def override_user | |
147 | + return if params[:override_user].blank? | |
148 | + return unless logged_in? and user.is_admin? environment | |
149 | + @current_user = nil | |
150 | + current_user params[:override_user] | |
151 | + end | |
152 | + | |
153 | + # When called with before_filter :login_from_cookie will check for an :auth_token | |
154 | + # cookie and log the user back in if apropriate | |
155 | + def login_from_cookie | |
156 | + return if cookies[:auth_token].blank? or logged_in? | |
157 | + user = User.where(remember_token: cookies[:auth_token]).first | |
158 | + self.current_user = user if user and user.remember_token? | |
159 | + end | |
160 | + | |
161 | + private | |
162 | + @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization) | |
163 | + # gets BASIC auth info | |
164 | + def get_auth_data | |
165 | + auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) } | |
166 | + auth_data = request.env[auth_key].to_s.split unless auth_key.blank? | |
167 | + return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil] | |
168 | + end | |
169 | +end | ... | ... |
... | ... | @@ -0,0 +1,50 @@ |
1 | +module CustomDesign | |
2 | + | |
3 | + extend ActiveSupport::Concern | |
4 | + | |
5 | + included do | |
6 | + extend ClassMethods | |
7 | + include InstanceMethods | |
8 | + before_filter :load_custom_design if self.respond_to? :before_filter | |
9 | + end | |
10 | + | |
11 | + module ClassMethods | |
12 | + | |
13 | + def no_design_blocks | |
14 | + @no_design_blocks = true | |
15 | + end | |
16 | + | |
17 | + def use_custom_design options = {} | |
18 | + @custom_design = options | |
19 | + end | |
20 | + | |
21 | + def custom_design | |
22 | + @custom_design ||= {} | |
23 | + end | |
24 | + | |
25 | + def uses_design_blocks? | |
26 | + !@no_design_blocks | |
27 | + end | |
28 | + | |
29 | + end | |
30 | + | |
31 | + module InstanceMethods | |
32 | + | |
33 | + protected | |
34 | + | |
35 | + def uses_design_blocks? | |
36 | + !@no_design_blocks && self.class.uses_design_blocks? | |
37 | + end | |
38 | + | |
39 | + def load_custom_design | |
40 | + # see also: LayoutHelper#body_classes | |
41 | + @layout_template = self.class.custom_design[:layout_template] | |
42 | + end | |
43 | + | |
44 | + def custom_design | |
45 | + @custom_design || self.class.custom_design | |
46 | + end | |
47 | + | |
48 | + end | |
49 | + | |
50 | +end | ... | ... |
... | ... | @@ -0,0 +1,40 @@ |
1 | +module NeedsProfile | |
2 | + | |
3 | + module ClassMethods | |
4 | + def needs_profile | |
5 | + before_filter :load_profile | |
6 | + end | |
7 | + end | |
8 | + | |
9 | + def self.included(including) | |
10 | + including.send(:extend, NeedsProfile::ClassMethods) | |
11 | + end | |
12 | + | |
13 | + def boxes_holder | |
14 | + profile || environment # prefers profile, but defaults to environment | |
15 | + end | |
16 | + | |
17 | + def profile | |
18 | + @profile | |
19 | + end | |
20 | + | |
21 | + protected | |
22 | + | |
23 | + def load_profile | |
24 | + if params[:profile] | |
25 | + params[:profile].downcase! | |
26 | + @profile ||= environment.profiles.where(identifier: params[:profile]).first | |
27 | + end | |
28 | + | |
29 | + if @profile | |
30 | + profile_hostname = @profile.hostname | |
31 | + if profile_hostname && profile_hostname != request.host | |
32 | + params.delete(:profile) | |
33 | + redirect_to(Noosfero.url_options.merge(params).merge(:host => profile_hostname)) | |
34 | + end | |
35 | + else | |
36 | + render_not_found | |
37 | + end | |
38 | + end | |
39 | + | |
40 | +end | ... | ... |
... | ... | @@ -0,0 +1,58 @@ |
1 | +class CirclesController < MyProfileController | |
2 | + | |
3 | + before_action :accept_only_post, :only => [:create, :update, :destroy] | |
4 | + | |
5 | + def index | |
6 | + @circles = profile.circles | |
7 | + end | |
8 | + | |
9 | + def new | |
10 | + @circle = Circle.new | |
11 | + end | |
12 | + | |
13 | + def create | |
14 | + @circle = Circle.new(params[:circle].merge({ :person => profile })) | |
15 | + if @circle.save | |
16 | + redirect_to :action => 'index' | |
17 | + else | |
18 | + render :action => 'new' | |
19 | + end | |
20 | + end | |
21 | + | |
22 | + def xhr_create | |
23 | + if request.xhr? | |
24 | + circle = Circle.new(params[:circle].merge({:person => profile })) | |
25 | + if circle.save | |
26 | + render :partial => "circle_checkbox", :locals => { :circle => circle }, | |
27 | + :status => 201 | |
28 | + else | |
29 | + render :text => _('The circle could not be saved'), :status => 400 | |
30 | + end | |
31 | + else | |
32 | + render_not_found | |
33 | + end | |
34 | + end | |
35 | + | |
36 | + def edit | |
37 | + @circle = Circle.find_by_id(params[:id]) | |
38 | + render_not_found if @circle.nil? | |
39 | + end | |
40 | + | |
41 | + def update | |
42 | + @circle = Circle.find_by_id(params[:id]) | |
43 | + return render_not_found if @circle.nil? | |
44 | + | |
45 | + if @circle.update(params[:circle]) | |
46 | + redirect_to :action => 'index' | |
47 | + else | |
48 | + render :action => 'edit' | |
49 | + end | |
50 | + end | |
51 | + | |
52 | + def destroy | |
53 | + @circle = Circle.find_by_id(params[:id]) | |
54 | + return render_not_found if @circle.nil? | |
55 | + @circle.destroy | |
56 | + redirect_to :action => 'index' | |
57 | + end | |
58 | +end | ... | ... |
... | ... | @@ -0,0 +1,43 @@ |
1 | +class FollowersController < MyProfileController | |
2 | + | |
3 | + before_action :only_for_person, :only => :index | |
4 | + before_action :accept_only_post, :only => [:update_category] | |
5 | + | |
6 | + def index | |
7 | + @followed_people = profile.followed_profiles.order(:type) | |
8 | + @profile_types = {_('All profiles') => nil}.merge(Circle.profile_types).to_a | |
9 | + | |
10 | + if params['filter'].present? | |
11 | + @followed_people = @followed_people.where(:type => params['filter']) | |
12 | + @active_filter = params['filter'] | |
13 | + end | |
14 | + | |
15 | + @followed_people = @followed_people.paginate(:per_page => 15, :page => params[:npage]) | |
16 | + end | |
17 | + | |
18 | + def set_category_modal | |
19 | + followed_profile = Profile.find(params[:followed_profile_id]) | |
20 | + circles = Circle.where(:person => profile, :profile_type => followed_profile.class.name) | |
21 | + render :partial => 'followers/edit_circles_modal', :locals => { :circles => circles, :followed_profile => followed_profile } | |
22 | + end | |
23 | + | |
24 | + def update_category | |
25 | + followed_profile = Profile.find_by(:id => params["followed_profile_id"]) | |
26 | + | |
27 | + selected_circles = params[:circles].map{ |circle_name, circle_id| Circle.find_by(:id => circle_id) }.select{ |c| c.present? } | |
28 | + | |
29 | + if followed_profile | |
30 | + profile.update_profile_circles(followed_profile, selected_circles) | |
31 | + render :text => _("Circles of %s updated successfully") % followed_profile.name, :status => 200 | |
32 | + else | |
33 | + render :text => _("Error: No profile to follow."), :status => 400 | |
34 | + end | |
35 | + end | |
36 | + | |
37 | + protected | |
38 | + | |
39 | + def only_for_person | |
40 | + render_not_found unless profile.person? | |
41 | + end | |
42 | + | |
43 | +end | ... | ... |
app/controllers/public/account_controller.rb
... | ... | @@ -205,7 +205,7 @@ class AccountController < ApplicationController |
205 | 205 | if params[:value].blank? |
206 | 206 | @change_password.errors[:base] << _('Can not recover user password with blank value.') |
207 | 207 | else |
208 | - @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] | |
208 | + @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".').html_safe % [fields_label, params[:value]] | |
209 | 209 | end |
210 | 210 | rescue ActiveRecord::RecordInvalid |
211 | 211 | @change_password.errors[:base] << _('Could not perform password recovery for the user.') | ... | ... |
app/controllers/public/content_viewer_controller.rb
... | ... | @@ -128,9 +128,9 @@ class ContentViewerController < ApplicationController |
128 | 128 | end |
129 | 129 | |
130 | 130 | unless @page.display_to?(user) |
131 | - if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank? | |
131 | + if !profile.visible? || profile.secret? || (user && profile.in_social_circle?(user)) || user.blank? | |
132 | 132 | render_access_denied |
133 | - else #!profile.public? | |
133 | + else | |
134 | 134 | private_profile_partial_parameters |
135 | 135 | render :template => 'profile/_private_profile', :status => 403, :formats => [:html] |
136 | 136 | end | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -3,7 +3,9 @@ class ProfileController < PublicController |
3 | 3 | needs_profile |
4 | 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] |
5 | 5 | before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse, :send_mail] |
6 | - before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail] | |
6 | + before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail, :follow, :unfollow] | |
7 | + before_filter :allow_followers?, :only => [:follow, :unfollow] | |
8 | + before_filter :accept_only_post, :only => [:follow, :unfollow] | |
7 | 9 | |
8 | 10 | helper TagsHelper |
9 | 11 | helper ActionTrackerHelper |
... | ... | @@ -42,8 +44,8 @@ class ProfileController < PublicController |
42 | 44 | feed_writer = FeedWriter.new |
43 | 45 | data = feed_writer.write( |
44 | 46 | tagged, |
45 | - :title => _("%s's contents tagged with \"%s\"") % [profile.name, @tag], | |
46 | - :description => _("%s's contents tagged with \"%s\"") % [profile.name, @tag], | |
47 | + :title => _("%s's contents tagged with \"%s\"").html_safe % [profile.name, @tag], | |
48 | + :description => _("%s's contents tagged with \"%s\"").html_safe % [profile.name, @tag], | |
47 | 49 | :link => url_for(profile.url) |
48 | 50 | ) |
49 | 51 | render :text => data, :content_type => "text/xml" |
... | ... | @@ -65,6 +67,14 @@ class ProfileController < PublicController |
65 | 67 | end |
66 | 68 | end |
67 | 69 | |
70 | + def following | |
71 | + @followed_people = profile.followed_profiles.paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.followed_profiles.count) | |
72 | + end | |
73 | + | |
74 | + def followed | |
75 | + @followed_by = profile.followers.paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.followers.count) | |
76 | + end | |
77 | + | |
68 | 78 | def members |
69 | 79 | if is_cache_expired?(profile.members_cache_key(params)) |
70 | 80 | sort = (params[:sort] == 'desc') ? params[:sort] : 'asc' |
... | ... | @@ -88,7 +98,7 @@ class ProfileController < PublicController |
88 | 98 | |
89 | 99 | def join_modal |
90 | 100 | profile.add_member(user) |
91 | - session[:notice] = _('%s administrator still needs to accept you as member.') % profile.name | |
101 | + session[:notice] = _('%s administrator still needs to accept you as member.').html_safe % profile.name | |
92 | 102 | redirect_to :action => :index |
93 | 103 | end |
94 | 104 | |
... | ... | @@ -98,12 +108,12 @@ class ProfileController < PublicController |
98 | 108 | |
99 | 109 | profile.add_member(user) |
100 | 110 | if !profile.members.include?(user) |
101 | - render :text => {:message => _('%s administrator still needs to accept you as member.') % profile.name}.to_json | |
111 | + render :text => {:message => _('%s administrator still needs to accept you as member.').html_safe % profile.name}.to_json | |
102 | 112 | else |
103 | - render :text => {:message => _('You just became a member of %s.') % profile.name}.to_json | |
113 | + render :text => {:message => _('You just became a member of %s.').html_safe % profile.name}.to_json | |
104 | 114 | end |
105 | 115 | else |
106 | - render :text => {:message => _('You are already a member of %s.') % profile.name}.to_json | |
116 | + render :text => {:message => _('You are already a member of %s.').html_safe % profile.name}.to_json | |
107 | 117 | end |
108 | 118 | end |
109 | 119 | |
... | ... | @@ -125,7 +135,7 @@ class ProfileController < PublicController |
125 | 135 | render :text => current_person.leave(profile, params[:reload]) |
126 | 136 | end |
127 | 137 | else |
128 | - render :text => {:message => _('You are not a member of %s.') % profile.name}.to_json | |
138 | + render :text => {:message => _('You are not a member of %s.').html_safe % profile.name}.to_json | |
129 | 139 | end |
130 | 140 | end |
131 | 141 | |
... | ... | @@ -145,12 +155,41 @@ class ProfileController < PublicController |
145 | 155 | # FIXME this shouldn't be in Person model? |
146 | 156 | if !user.memberships.include?(profile) |
147 | 157 | AddFriend.create!(:person => user, :friend => profile) |
148 | - render :text => _('%s still needs to accept being your friend.') % profile.name | |
158 | + render :text => _('%s still needs to accept being your friend.').html_safe % profile.name | |
149 | 159 | else |
150 | - render :text => _('You are already a friend of %s.') % profile.name | |
160 | + render :text => _('You are already a friend of %s.').html_safe % profile.name | |
161 | + end | |
162 | + end | |
163 | + | |
164 | + def follow | |
165 | + if profile.followed_by?(current_person) | |
166 | + render :text => _("You are already following %s.") % profile.name, :status => 400 | |
167 | + else | |
168 | + selected_circles = params[:circles].map{ |circle_name, circle_id| Circle.find_by(:id => circle_id) }.select{ |c| c.present? } | |
169 | + if selected_circles.present? | |
170 | + current_person.follow(profile, selected_circles) | |
171 | + render :text => _("You are now following %s") % profile.name, :status => 200 | |
172 | + else | |
173 | + render :text => _("Select at least one circle to follow %s.") % profile.name, :status => 400 | |
174 | + end | |
151 | 175 | end |
152 | 176 | end |
153 | 177 | |
178 | + def find_profile_circles | |
179 | + circles = Circle.where(:person => current_person, :profile_type => profile.class.name) | |
180 | + render :partial => 'blocks/profile_info_actions/circles', :locals => { :circles => circles, :profile_types => Circle.profile_types.to_a } | |
181 | + end | |
182 | + | |
183 | + def unfollow | |
184 | + follower = params[:follower_id].present? ? Person.find_by(id: params[:follower_id]) : current_person | |
185 | + | |
186 | + if follower && follower.follows?(profile) | |
187 | + follower.unfollow(profile) | |
188 | + end | |
189 | + redirect_url = params["redirect_to"] ? params["redirect_to"] : profile.url | |
190 | + redirect_to redirect_url | |
191 | + end | |
192 | + | |
154 | 193 | def check_friendship |
155 | 194 | unless logged_in? |
156 | 195 | render :text => '' |
... | ... | @@ -178,7 +217,7 @@ class ProfileController < PublicController |
178 | 217 | def unblock |
179 | 218 | if current_user.person.is_admin?(profile.environment) |
180 | 219 | profile.unblock |
181 | - session[:notice] = _("You have unblocked %s successfully. ") % profile.name | |
220 | + session[:notice] = _("You have unblocked %s successfully. ").html_safe % profile.name | |
182 | 221 | redirect_to :controller => 'profile', :action => 'index' |
183 | 222 | else |
184 | 223 | message = _('You are not allowed to unblock enterprises in this environment.') |
... | ... | @@ -437,4 +476,8 @@ class ProfileController < PublicController |
437 | 476 | [:image, :domains, :preferred_domain, :environment] |
438 | 477 | end |
439 | 478 | |
479 | + def allow_followers? | |
480 | + render_not_found unless profile.allow_followers? | |
481 | + end | |
482 | + | |
440 | 483 | end | ... | ... |
app/helpers/action_tracker_helper.rb
... | ... | @@ -14,13 +14,23 @@ module ActionTrackerHelper |
14 | 14 | } |
15 | 15 | end |
16 | 16 | |
17 | + def new_follower_description ta | |
18 | + n_('has 1 new follower:<br />%{name}', 'has %{num} new followers:<br />%{name}', ta.get_follower_name.size).html_safe % { | |
19 | + num: ta.get_follower_name.size, | |
20 | + name: safe_join(ta.collect_group_with_index(:follower_name) do |n,i| | |
21 | + link_to image_tag(ta.get_follower_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/person-icon.png")), | |
22 | + ta.get_follower_url[i], title: n | |
23 | + end) | |
24 | + } | |
25 | + end | |
26 | + | |
17 | 27 | def join_community_description ta |
18 | - n_('has joined 1 community:<br />%{name}'.html_safe, 'has joined %{num} communities:<br />%{name}'.html_safe, ta.get_resource_name.size) % { | |
28 | + n_('has joined 1 community:<br />%{name}', 'has joined %{num} communities:<br />%{name}', ta.get_resource_name.size).html_safe % { | |
19 | 29 | num: ta.get_resource_name.size, |
20 | - name: ta.collect_group_with_index(:resource_name) do |n,i| | |
30 | + name: safe_join(ta.collect_group_with_index(:resource_name) do |n,i| | |
21 | 31 | link = link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")), |
22 | 32 | ta.get_resource_url[i], title: n |
23 | - end.join.html_safe | |
33 | + end) | |
24 | 34 | } |
25 | 35 | end |
26 | 36 | |
... | ... | @@ -68,9 +78,9 @@ module ActionTrackerHelper |
68 | 78 | end |
69 | 79 | |
70 | 80 | def favorite_enterprise_description ta |
71 | - _('favorited enterprise %{title}') % { | |
81 | + (_('favorited enterprise %{title}') % { | |
72 | 82 | title: link_to(truncate(ta.get_enterprise_name), ta.get_enterprise_url), |
73 | - } | |
83 | + }).html_safe | |
74 | 84 | end |
75 | 85 | |
76 | 86 | end | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -880,7 +880,7 @@ module ApplicationHelper |
880 | 880 | link_to_all = link_to(content_tag('strong', _('See all')), :controller => 'memberships', :profile => user.identifier) |
881 | 881 | end |
882 | 882 | link = list.map do |element| |
883 | - 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) | |
883 | + 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) | |
884 | 884 | end |
885 | 885 | if link_to_all |
886 | 886 | link << link_to_all |
... | ... | @@ -921,7 +921,7 @@ module ApplicationHelper |
921 | 921 | logout_link = link_to(logout_icon.html_safe, { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) |
922 | 922 | join_result = safe_join( |
923 | 923 | [welcome_span.html_safe, render_environment_features(:usermenu).html_safe, admin_link.html_safe, |
924 | - manage_enterprises.html_safe, manage_communities.html_safe, ctrl_panel_link.html_safe, | |
924 | + manage_enterprises, manage_communities, ctrl_panel_link.html_safe, | |
925 | 925 | pending_tasks_count.html_safe, logout_link.html_safe], "") |
926 | 926 | join_result |
927 | 927 | end | ... | ... |
app/helpers/forms_helper.rb
... | ... | @@ -128,14 +128,14 @@ module FormsHelper |
128 | 128 | counter += 1 |
129 | 129 | row << item |
130 | 130 | if counter % per_row == 0 |
131 | - rows << content_tag('tr', row.join("\n")) | |
131 | + rows << content_tag('tr', row.join("\n").html_safe) | |
132 | 132 | counter = 0 |
133 | 133 | row = [] |
134 | 134 | end |
135 | 135 | end |
136 | - rows << content_tag('tr', row.join("\n")) | |
136 | + rows << content_tag('tr', row.join("\n").html_safe) | |
137 | 137 | |
138 | - content_tag('table',rows.join("\n")) | |
138 | + content_tag('table',rows.join("\n").html_safe) | |
139 | 139 | end |
140 | 140 | |
141 | 141 | def date_field(name, value, datepicker_options = {}, html_options = {}) | ... | ... |
app/helpers/profile_helper.rb
... | ... | @@ -11,7 +11,7 @@ module ProfileHelper |
11 | 11 | PERSON_CATEGORIES[:location] = [:address, :address_reference, :zip_code, :city, :state, :district, :country, :nationality] |
12 | 12 | PERSON_CATEGORIES[:work] = [:organization, :organization_website, :professional_activity] |
13 | 13 | PERSON_CATEGORIES[:study] = [:schooling, :formation, :area_of_study] |
14 | - PERSON_CATEGORIES[:network] = [:friends, :communities, :enterprises] | |
14 | + PERSON_CATEGORIES[:network] = [:friends, :followers, :followed_profiles, :communities, :enterprises] | |
15 | 15 | PERSON_CATEGORIES.merge!(COMMON_CATEGORIES) |
16 | 16 | |
17 | 17 | ORGANIZATION_CATEGORIES = {} |
... | ... | @@ -42,7 +42,8 @@ module ProfileHelper |
42 | 42 | :created_at => _('Profile created at'), |
43 | 43 | :members_count => _('Members'), |
44 | 44 | :privacy_setting => _('Privacy setting'), |
45 | - :article_tags => _('Tags') | |
45 | + :article_tags => _('Tags'), | |
46 | + :followed_profiles => _('Following') | |
46 | 47 | } |
47 | 48 | |
48 | 49 | EXCEPTION = { |
... | ... | @@ -144,6 +145,14 @@ module ProfileHelper |
144 | 145 | link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) |
145 | 146 | end |
146 | 147 | |
148 | + def treat_followers(followers) | |
149 | + link_to(profile.followers.count, {:action=>"followed", :controller=>"profile", :profile=>"#{profile.identifier}"}) | |
150 | + end | |
151 | + | |
152 | + def treat_followed_profiles(followed_profiles) | |
153 | + link_to(profile.followed_profiles.count, {:action=>"following", :controller=>"profile", :profile=>"#{profile.identifier}"}) | |
154 | + end | |
155 | + | |
147 | 156 | def treat_events(events) |
148 | 157 | link_to events.published.count, :controller => 'events', :action => 'events' |
149 | 158 | end | ... | ... |
app/jobs/notify_activity_to_profiles_job.rb
... | ... | @@ -19,8 +19,8 @@ class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id) |
19 | 19 | # Notify the user |
20 | 20 | ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id) |
21 | 21 | |
22 | - # Notify all friends | |
23 | - ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select f.friend_id, #{tracked_action.id} from friendships as f where person_id=#{tracked_action.user.id} and f.friend_id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id})") | |
22 | + # Notify all followers | |
23 | + ActionTrackerNotification.connection.execute("INSERT INTO action_tracker_notifications(profile_id, action_tracker_id) SELECT DISTINCT c.person_id, #{tracked_action.id} FROM profiles_circles AS p JOIN circles as c ON c.id = p.circle_id WHERE p.profile_id = #{tracked_action.user.id} AND (c.person_id NOT IN (SELECT atn.profile_id FROM action_tracker_notifications AS atn WHERE atn.action_tracker_id = #{tracked_action.id}))") | |
24 | 24 | |
25 | 25 | if tracked_action.user.is_a? Organization |
26 | 26 | ActionTrackerNotification.connection.execute "insert into action_tracker_notifications(profile_id, action_tracker_id) " + | ... | ... |
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
app/mailers/mailing.rb
... | ... | @@ -2,7 +2,8 @@ require_dependency 'mailing_job' |
2 | 2 | |
3 | 3 | class Mailing < ApplicationRecord |
4 | 4 | |
5 | - acts_as_having_settings :field => :data | |
5 | + extend ActsAsHavingSettings::ClassMethods | |
6 | + acts_as_having_settings field: :data | |
6 | 7 | |
7 | 8 | attr_accessible :subject, :body, :data |
8 | 9 | |
... | ... | @@ -23,11 +24,11 @@ class Mailing < ApplicationRecord |
23 | 24 | end |
24 | 25 | |
25 | 26 | def generate_from |
26 | - "#{source.name} <#{if source.is_a? Environment then source.noreply_email else source.contact_email end}>" | |
27 | + "#{source.name} <#{if source.is_a? Environment then source.noreply_email else source.contact_email end}>".html_safe | |
27 | 28 | end |
28 | 29 | |
29 | 30 | def generate_subject |
30 | - '[%s] %s' % [source.name, subject] | |
31 | + '[%s] %s'.html_safe % [source.name, subject] | |
31 | 32 | end |
32 | 33 | |
33 | 34 | def signature_message | ... | ... |
app/mailers/organization_mailing.rb
app/mailers/pending_task_notifier.rb
... | ... | @@ -12,8 +12,8 @@ class PendingTaskNotifier < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 |
... | ... | @@ -57,15 +57,15 @@ class AbuseComplaint < Task |
57 | 57 | end |
58 | 58 | |
59 | 59 | def task_activated_message |
60 | - _('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 | |
60 | + _('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 | |
61 | 61 | end |
62 | 62 | |
63 | 63 | def task_finished_message |
64 | - _('Your profile was disabled by the administrators of %s due to inappropriate behavior. To solve this misunderstanding please contact them.') % environment.name | |
64 | + _('Your profile was disabled by the administrators of %s due to inappropriate behavior. To solve this misunderstanding please contact them.').html_safe % environment.name | |
65 | 65 | end |
66 | 66 | |
67 | 67 | def target_notification_description |
68 | - _('%s was reported due to inappropriate behavior.') % reported.name | |
68 | + _('%s was reported due to inappropriate behavior.').html_safe % reported.name | |
69 | 69 | end |
70 | 70 | |
71 | 71 | def target_notification_message | ... | ... |
app/models/add_member.rb
... | ... | @@ -22,6 +22,7 @@ class AddMember < Task |
22 | 22 | self.roles = [Profile::Roles.member(organization.environment.id).id] |
23 | 23 | end |
24 | 24 | target.affiliate(requestor, self.roles.select{|r| !r.to_i.zero? }.map{|i| Role.find(i)}) |
25 | + person.follow(organization, Circle.find_or_create_by(:person => person, :name =>_('memberships'), :profile_type => 'Community')) | |
25 | 26 | end |
26 | 27 | |
27 | 28 | def title |
... | ... | @@ -56,7 +57,7 @@ class AddMember < Task |
56 | 57 | def target_notification_description |
57 | 58 | requestor_email = " (#{requestor.email})" if requestor.may_display_field_to?("email") |
58 | 59 | |
59 | - _("%{requestor}%{requestor_email} wants to be a member of '%{organization}'.") % {:requestor => requestor.name, :requestor_email => requestor_email, :organization => organization.name} | |
60 | + _("%{requestor}%{requestor_email} wants to be a member of '%{organization}'.").html_safe % {:requestor => requestor.name, :requestor_email => requestor_email, :organization => organization.name} | |
60 | 61 | end |
61 | 62 | |
62 | 63 | def target_notification_message | ... | ... |
app/models/article.rb
... | ... | @@ -13,7 +13,9 @@ class Article < ApplicationRecord |
13 | 13 | :image_builder, :show_to_followers, :archived, |
14 | 14 | :author, :display_preview, :published_at, :person_followers |
15 | 15 | |
16 | + extend ActsAsHavingImage::ClassMethods | |
16 | 17 | acts_as_having_image |
18 | + | |
17 | 19 | include Noosfero::Plugin::HotSpot |
18 | 20 | |
19 | 21 | SEARCHABLE_FIELDS = { |
... | ... | @@ -91,7 +93,8 @@ class Article < ApplicationRecord |
91 | 93 | has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization' |
92 | 94 | has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category |
93 | 95 | |
94 | - acts_as_having_settings :field => :setting | |
96 | + extend ActsAsHavingSettings::ClassMethods | |
97 | + acts_as_having_settings field: :setting | |
95 | 98 | |
96 | 99 | settings_items :display_hits, :type => :boolean, :default => true |
97 | 100 | settings_items :author_name, :type => :string, :default => "" |
... | ... | @@ -242,6 +245,7 @@ class Article < ApplicationRecord |
242 | 245 | acts_as_taggable |
243 | 246 | N_('Tag list') |
244 | 247 | |
248 | + extend ActsAsFilesystem::ActsMethods | |
245 | 249 | acts_as_filesystem |
246 | 250 | |
247 | 251 | acts_as_versioned |
... | ... | @@ -534,13 +538,13 @@ class Article < ApplicationRecord |
534 | 538 | |
535 | 539 | scope :display_filter, lambda {|user, profile| |
536 | 540 | return published if (user.nil? && profile && profile.public?) |
537 | - return [] if user.nil? || (profile && !profile.public? && !user.follows?(profile)) | |
541 | + return [] if user.nil? || (profile && !profile.public? && !profile.in_social_circle?(user)) | |
538 | 542 | where( |
539 | 543 | [ |
540 | 544 | "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ? |
541 | 545 | OR (show_to_followers = ? AND ? AND profile_id IN (?))", true, user.id, user.id, |
542 | 546 | profile.nil? ? false : user.has_permission?(:view_private_content, profile), |
543 | - true, (profile.nil? ? true : user.follows?(profile)), ( profile.nil? ? (user.friends.select('profiles.id')) : [profile.id]) | |
547 | + true, (profile.nil? ? true : profile.in_social_circle?(user)), ( profile.nil? ? (user.friends.select('profiles.id')) : [profile.id]) | |
544 | 548 | ] |
545 | 549 | ) |
546 | 550 | } | ... | ... |
app/models/block.rb
... | ... | @@ -17,6 +17,7 @@ class Block < ApplicationRecord |
17 | 17 | belongs_to :mirror_block, :class_name => "Block" |
18 | 18 | has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id" |
19 | 19 | |
20 | + extend ActsAsHavingSettings::ClassMethods | |
20 | 21 | acts_as_having_settings |
21 | 22 | |
22 | 23 | scope :enabled, -> { where :enabled => true } |
... | ... | @@ -88,7 +89,7 @@ class Block < ApplicationRecord |
88 | 89 | end |
89 | 90 | |
90 | 91 | def display_to_user?(user) |
91 | - display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && user.follows?(owner)) | |
92 | + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && owner.in_social_circle?(user)) | |
92 | 93 | end |
93 | 94 | |
94 | 95 | def display_always(context) | ... | ... |
app/models/blog.rb
app/models/category.rb
... | ... | @@ -21,6 +21,7 @@ class Category < ApplicationRecord |
21 | 21 | |
22 | 22 | scope :on_level, -> parent { where :parent_id => parent } |
23 | 23 | |
24 | + extend ActsAsFilesystem::ActsMethods | |
24 | 25 | acts_as_filesystem |
25 | 26 | |
26 | 27 | has_many :article_categorizations |
... | ... | @@ -35,6 +36,7 @@ class Category < ApplicationRecord |
35 | 36 | has_many :people, :through => :profile_categorizations, :source => :profile, :class_name => 'Person' |
36 | 37 | has_many :communities, :through => :profile_categorizations, :source => :profile, :class_name => 'Community' |
37 | 38 | |
39 | + extend ActsAsHavingImage::ClassMethods | |
38 | 40 | acts_as_having_image |
39 | 41 | |
40 | 42 | before_save :normalize_display_color | ... | ... |
... | ... | @@ -0,0 +1,37 @@ |
1 | +class Circle < ApplicationRecord | |
2 | + has_many :profile_followers | |
3 | + belongs_to :person | |
4 | + | |
5 | + attr_accessible :name, :person, :profile_type | |
6 | + | |
7 | + validates :name, presence: true | |
8 | + validates :person_id, presence: true | |
9 | + validates :profile_type, presence: true | |
10 | + validates :person_id, :uniqueness => {:scope => :name, :message => "can't add two circles with the same name"} | |
11 | + | |
12 | + validate :profile_type_must_be_in_list | |
13 | + | |
14 | + scope :by_owner, -> person{ | |
15 | + where(:person => person) | |
16 | + } | |
17 | + | |
18 | + scope :with_name, -> name{ | |
19 | + where(:name => name) | |
20 | + } | |
21 | + | |
22 | + def self.profile_types | |
23 | + { | |
24 | + _("Person") => Person.name, | |
25 | + _("Community") => Community.name, | |
26 | + _("Enterprise") => Enterprise.name | |
27 | + } | |
28 | + end | |
29 | + | |
30 | + def profile_type_must_be_in_list | |
31 | + valid_profile_types = Circle.profile_types.values | |
32 | + unless self.profile_type.in? valid_profile_types | |
33 | + self.errors.add(:profile_type, "invalid profile type") | |
34 | + end | |
35 | + end | |
36 | + | |
37 | +end | ... | ... |
app/models/comment.rb
app/models/community.rb
... | ... | @@ -2,7 +2,7 @@ class Community < 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 < 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 | ... | ... |
... | ... | @@ -0,0 +1,265 @@ |
1 | +module ActsAsFilesystem | |
2 | + | |
3 | + module ActsMethods | |
4 | + | |
5 | + # Declares the ActiveRecord model to acts like a filesystem: objects are | |
6 | + # arranged in a tree (liks acts_as_tree), and . The underlying table must | |
7 | + # have the following fields: | |
8 | + # | |
9 | + # * name (+:string+) - the title of the object | |
10 | + # * slug (+:string+)- the title turned in a URL-friendly string (downcased, | |
11 | + # non-ascii chars transliterated into ascii, all sequences of | |
12 | + # non-alphanumericd characters changed into dashed) | |
13 | + # * path (+:text+)- stores the full path of the object (the full path of | |
14 | + # the parent, a "/" and the slug of the object) | |
15 | + # * children_count - a cache of the number of children elements. | |
16 | + def acts_as_filesystem | |
17 | + # a filesystem is a tree | |
18 | + acts_as_tree :counter_cache => :children_count | |
19 | + | |
20 | + extend ClassMethods | |
21 | + include InstanceMethods | |
22 | + if self.has_path? | |
23 | + after_update :update_children_path | |
24 | + before_create :set_path | |
25 | + include InstanceMethods::PathMethods | |
26 | + end | |
27 | + | |
28 | + before_save :set_ancestry | |
29 | + end | |
30 | + | |
31 | + end | |
32 | + | |
33 | + module ClassMethods | |
34 | + | |
35 | + def build_ancestry(parent_id = nil, ancestry = '') | |
36 | + ActiveRecord::Base.transaction do | |
37 | + self.base_class.where(parent_id: parent_id).each do |node| | |
38 | + node.update_column :ancestry, ancestry | |
39 | + | |
40 | + build_ancestry node.id, (ancestry.empty? ? "#{node.formatted_ancestry_id}" : | |
41 | + "#{ancestry}#{node.ancestry_sep}#{node.formatted_ancestry_id}") | |
42 | + end | |
43 | + end | |
44 | + | |
45 | + #raise "Couldn't reach and set ancestry on every record" if self.base_class.where('ancestry is null').count != 0 | |
46 | + end | |
47 | + | |
48 | + def has_path? | |
49 | + (['name', 'slug', 'path'] - self.column_names).blank? | |
50 | + end | |
51 | + | |
52 | + end | |
53 | + | |
54 | + module InstanceMethods | |
55 | + | |
56 | + def ancestry_column | |
57 | + 'ancestry' | |
58 | + end | |
59 | + def ancestry_sep | |
60 | + '.' | |
61 | + end | |
62 | + def has_ancestry? | |
63 | + self.class.column_names.include? self.ancestry_column | |
64 | + end | |
65 | + | |
66 | + def formatted_ancestry_id | |
67 | + "%010d" % self.id if self.id | |
68 | + end | |
69 | + | |
70 | + def ancestry | |
71 | + self[ancestry_column] | |
72 | + end | |
73 | + def ancestor_ids | |
74 | + return nil if !has_ancestry? or ancestry.nil? | |
75 | + @ancestor_ids ||= ancestry.split(ancestry_sep).map{ |id| id.to_i } | |
76 | + end | |
77 | + | |
78 | + def ancestry=(value) | |
79 | + self[ancestry_column] = value | |
80 | + end | |
81 | + def set_ancestry | |
82 | + return unless self.has_ancestry? | |
83 | + if self.ancestry.nil? or (new_record? or parent_id_changed?) or recalculate_path | |
84 | + self.ancestry = self.hierarchy(true)[0...-1].map{ |p| p.formatted_ancestry_id }.join(ancestry_sep) | |
85 | + end | |
86 | + end | |
87 | + | |
88 | + def descendents_options | |
89 | + ["#{self.ancestry_column} LIKE ?", "%#{self.formatted_ancestry_id}%"] | |
90 | + end | |
91 | + def descendents | |
92 | + self.class.where descendents_options | |
93 | + end | |
94 | + | |
95 | + # calculates the level of the record in the records hierarchy. Top-level | |
96 | + # records have level 0; the children of the top-level records have | |
97 | + # level 1; the children of records with level 1 have level 2, and so on. | |
98 | + # | |
99 | + # A level 0 | |
100 | + # / \ | |
101 | + # B C level 1 | |
102 | + # / \ / \ | |
103 | + # E F G H level 2 | |
104 | + # ... | |
105 | + def level | |
106 | + self.hierarchy.size - 1 | |
107 | + end | |
108 | + | |
109 | + # Is this record a top-level record? | |
110 | + def top_level? | |
111 | + self.parent.nil? | |
112 | + end | |
113 | + | |
114 | + # Is this record a leaf in the hierarchy tree of records? | |
115 | + # | |
116 | + # Being a leaf means that this record has no subrecord. | |
117 | + def leaf? | |
118 | + self.children.empty? | |
119 | + end | |
120 | + | |
121 | + def top_ancestor | |
122 | + if has_ancestry? and !ancestry.blank? | |
123 | + self.class.base_class.find_by id: self.top_ancestor_id | |
124 | + else | |
125 | + self.hierarchy.first | |
126 | + end | |
127 | + end | |
128 | + def top_ancestor_id | |
129 | + if has_ancestry? and !ancestry.nil? | |
130 | + self.ancestor_ids.first | |
131 | + else | |
132 | + self.hierarchy.first.id | |
133 | + end | |
134 | + end | |
135 | + | |
136 | + # returns the full hierarchy from the top-level item to this one. For | |
137 | + # example, if item1 has a children item2 and item2 has a children item3, | |
138 | + # then item3's hierarchy would be [item1, item2, item3]. | |
139 | + # | |
140 | + # If +reload+ is passed as +true+, then the hierarchy is reload (usefull | |
141 | + # when the ActiveRecord object was modified in some way, or just after | |
142 | + # changing parent) | |
143 | + def hierarchy(reload = false) | |
144 | + @hierarchy = nil if reload or recalculate_path | |
145 | + | |
146 | + if @hierarchy.nil? | |
147 | + @hierarchy = [] | |
148 | + | |
149 | + if !reload and !recalculate_path and ancestor_ids | |
150 | + objects = self.class.base_class.where(id: ancestor_ids) | |
151 | + ancestor_ids.each{ |id| @hierarchy << objects.find{ |t| t.id == id } } | |
152 | + @hierarchy << self | |
153 | + else | |
154 | + item = self | |
155 | + while item | |
156 | + @hierarchy.unshift(item) | |
157 | + item = item.parent | |
158 | + end | |
159 | + end | |
160 | + end | |
161 | + | |
162 | + @hierarchy | |
163 | + end | |
164 | + | |
165 | + def map_traversal(&block) | |
166 | + result = [] | |
167 | + current_level = [self] | |
168 | + | |
169 | + while !current_level.empty? | |
170 | + result += current_level | |
171 | + ids = current_level.select {|item| item.children_count > 0}.map(&:id) | |
172 | + break if ids.empty? | |
173 | + current_level = self.class.base_class.where(parent_id: ids) | |
174 | + end | |
175 | + block ||= (lambda { |x| x }) | |
176 | + result.map(&block) | |
177 | + end | |
178 | + | |
179 | + def all_children | |
180 | + res = map_traversal | |
181 | + res.shift | |
182 | + res | |
183 | + end | |
184 | + | |
185 | + ##### | |
186 | + # Path methods | |
187 | + # These methods are used when _path_, _name_ and _slug_ attributes exist | |
188 | + # and should be calculated based on the tree | |
189 | + ##### | |
190 | + module PathMethods | |
191 | + # used to know when to trigger batch renaming | |
192 | + attr_accessor :recalculate_path | |
193 | + | |
194 | + # calculates the full path to this record using parent's path. | |
195 | + def calculate_path | |
196 | + self.hierarchy.map{ |obj| obj.slug }.join('/') | |
197 | + end | |
198 | + def set_path | |
199 | + if self.path == self.slug && !self.top_level? | |
200 | + self.path = self.calculate_path | |
201 | + end | |
202 | + end | |
203 | + def explode_path | |
204 | + path.split(/\//) | |
205 | + end | |
206 | + | |
207 | + def update_children_path | |
208 | + if self.recalculate_path | |
209 | + self.children.each do |child| | |
210 | + child.path = child.calculate_path | |
211 | + child.recalculate_path = true | |
212 | + child.save! | |
213 | + end | |
214 | + end | |
215 | + self.recalculate_path = false | |
216 | + end | |
217 | + | |
218 | + # calculates the full name of a record by accessing the name of all its | |
219 | + # ancestors. | |
220 | + # | |
221 | + # If you have this record hierarchy: | |
222 | + # Record "A" | |
223 | + # Record "B" | |
224 | + # Record "C" | |
225 | + # | |
226 | + # Then Record "C" will have "A/B/C" as its full name. | |
227 | + def full_name(sep = '/') | |
228 | + self.hierarchy.map {|item| item.name || '?' }.join(sep) | |
229 | + end | |
230 | + | |
231 | + # gets the name without leading parents. Useful when dividing records | |
232 | + # in top-level groups and full names must not include the top-level | |
233 | + # record which is already a emphasized label | |
234 | + def full_name_without_leading(count, sep = '/') | |
235 | + parts = self.full_name(sep).split(sep) | |
236 | + count.times { parts.shift } | |
237 | + parts.join(sep) | |
238 | + end | |
239 | + | |
240 | + def set_name(value) | |
241 | + if self.name != value | |
242 | + self.recalculate_path = true | |
243 | + end | |
244 | + self[:name] = value | |
245 | + end | |
246 | + | |
247 | + # sets the name of the record. Also sets #slug accordingly. | |
248 | + def name=(value) | |
249 | + self.set_name(value) | |
250 | + unless self.name.blank? | |
251 | + self.slug = self.name.to_slug | |
252 | + end | |
253 | + end | |
254 | + | |
255 | + # sets the slug of the record. Also sets the path with the new slug value. | |
256 | + def slug=(value) | |
257 | + self[:slug] = value | |
258 | + unless self.slug.blank? | |
259 | + self.path = self.calculate_path | |
260 | + end | |
261 | + end | |
262 | + end | |
263 | + end | |
264 | +end | |
265 | + | ... | ... |
... | ... | @@ -0,0 +1,37 @@ |
1 | +module ActsAsHavingBoxes | |
2 | + | |
3 | + module ClassMethods | |
4 | + def acts_as_having_boxes | |
5 | + has_many :boxes, -> { order :position }, as: :owner, dependent: :destroy | |
6 | + self.send(:include, ActsAsHavingBoxes) | |
7 | + end | |
8 | + end | |
9 | + | |
10 | + module BlockArray | |
11 | + def find(id) | |
12 | + select { |item| item.id == id.to_i }.first | |
13 | + end | |
14 | + end | |
15 | + | |
16 | + def blocks(reload = false) | |
17 | + if (reload) | |
18 | + @blocks = nil | |
19 | + end | |
20 | + if @blocks.nil? | |
21 | + @blocks = boxes.includes(:blocks).inject([]) do |acc,obj| | |
22 | + acc.concat(obj.blocks) | |
23 | + end | |
24 | + @blocks.send(:extend, BlockArray) | |
25 | + end | |
26 | + @blocks | |
27 | + end | |
28 | + | |
29 | + # returns 3 unless the class table has a boxes_limit column. In that case | |
30 | + # return the value of the column. | |
31 | + def boxes_limit layout_template = nil | |
32 | + layout_template ||= self.layout_template | |
33 | + @boxes_limit ||= LayoutTemplate.find(layout_template).number_of_boxes || 3 | |
34 | + end | |
35 | + | |
36 | +end | |
37 | + | ... | ... |
... | ... | @@ -0,0 +1,25 @@ |
1 | +module ActsAsHavingImage | |
2 | + | |
3 | + module ClassMethods | |
4 | + def acts_as_having_image | |
5 | + belongs_to :image, dependent: :destroy | |
6 | + scope :with_image, -> { where "#{table_name}.image_id IS NOT NULL" } | |
7 | + scope :without_image, -> { where "#{table_name}.image_id IS NULL" } | |
8 | + attr_accessible :image_builder | |
9 | + include ActsAsHavingImage | |
10 | + end | |
11 | + end | |
12 | + | |
13 | + def image_builder=(img) | |
14 | + if image && image.id == img[:id] | |
15 | + image.attributes = img | |
16 | + else | |
17 | + build_image(img) | |
18 | + end unless img[:uploaded_data].blank? | |
19 | + if img[:remove_image] == 'true' | |
20 | + self.image_id = nil | |
21 | + end | |
22 | + end | |
23 | + | |
24 | +end | |
25 | + | ... | ... |
... | ... | @@ -0,0 +1,49 @@ |
1 | +module ActsAsHavingPosts | |
2 | + | |
3 | + module ClassMethods | |
4 | + def acts_as_having_posts(scope = nil) | |
5 | + has_many :posts, -> { | |
6 | + s = order('published_at DESC, id DESC').where('articles.type != ?', 'RssFeed') | |
7 | + s = s.instance_exec(&scope) if scope | |
8 | + s | |
9 | + }, class_name: 'Article', foreign_key: 'parent_id', source: :children | |
10 | + | |
11 | + attr_accessor :feed_attrs | |
12 | + | |
13 | + after_create do |blog| | |
14 | + blog.children << RssFeed.new(:name => 'feed', :profile => blog.profile) | |
15 | + blog.feed = blog.feed_attrs | |
16 | + end | |
17 | + | |
18 | + settings_items :posts_per_page, :type => :integer, :default => 5 | |
19 | + | |
20 | + self.send(:include, ActsAsHavingPosts) | |
21 | + end | |
22 | + end | |
23 | + | |
24 | + def has_posts? | |
25 | + true | |
26 | + end | |
27 | + | |
28 | + def feed | |
29 | + children.where(:type => 'RssFeed').first | |
30 | + end | |
31 | + | |
32 | + def feed=(attrs) | |
33 | + if attrs | |
34 | + if self.feed | |
35 | + self.feed.update(attrs) | |
36 | + else | |
37 | + self.feed_attrs = attrs | |
38 | + end | |
39 | + end | |
40 | + self.feed | |
41 | + end | |
42 | + | |
43 | + def name=(value) | |
44 | + self.set_name(value) | |
45 | + self.slug = self.slug.blank? ? self.name.to_slug : self.slug.to_slug | |
46 | + end | |
47 | + | |
48 | +end | |
49 | + | ... | ... |
... | ... | @@ -0,0 +1,89 @@ |
1 | +# declare missing types | |
2 | +module ActiveRecord | |
3 | + module Type | |
4 | + class Symbol < Value | |
5 | + def cast_value value | |
6 | + value.to_sym | |
7 | + end | |
8 | + end | |
9 | + class Array < Value | |
10 | + def cast_value value | |
11 | + ::Array.wrap(value) | |
12 | + end | |
13 | + end | |
14 | + class Hash < Value | |
15 | + def cast_value value | |
16 | + h = ::Hash[value] | |
17 | + h.symbolize_keys! | |
18 | + h | |
19 | + end | |
20 | + end | |
21 | + end | |
22 | +end | |
23 | + | |
24 | +module ActsAsHavingSettings | |
25 | + | |
26 | + def self.type_cast value, type | |
27 | + # do not cast nil | |
28 | + return value if value.nil? | |
29 | + type.send :cast_value, value | |
30 | + end | |
31 | + | |
32 | + module ClassMethods | |
33 | + | |
34 | + def acts_as_having_settings(*args) | |
35 | + options = args.last.is_a?(Hash) ? args.pop : {} | |
36 | + field = (options[:field] || :settings).to_sym | |
37 | + | |
38 | + serialize field, Hash | |
39 | + class_attribute :settings_field | |
40 | + self.settings_field = field | |
41 | + | |
42 | + class_eval do | |
43 | + def settings_field | |
44 | + self[self.class.settings_field] ||= Hash.new | |
45 | + end | |
46 | + | |
47 | + def setting_changed? setting_field | |
48 | + setting_field = setting_field.to_sym | |
49 | + changed_settings = self.changes[self.class.settings_field] | |
50 | + return false if changed_settings.nil? | |
51 | + | |
52 | + old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field] | |
53 | + new_setting_value = changed_settings.last[setting_field] | |
54 | + old_setting_value != new_setting_value | |
55 | + end | |
56 | + end | |
57 | + | |
58 | + settings_items *args | |
59 | + end | |
60 | + | |
61 | + def settings_items *names | |
62 | + | |
63 | + options = names.extract_options! | |
64 | + default = options[:default] | |
65 | + type = options[:type] | |
66 | + type = if type.present? then ActiveRecord::Type.const_get(type.to_s.camelize.to_sym).new else nil end | |
67 | + | |
68 | + names.each do |setting| | |
69 | + # symbolize key | |
70 | + setting = setting.to_sym | |
71 | + | |
72 | + define_method setting do | |
73 | + h = send self.class.settings_field | |
74 | + val = h[setting] | |
75 | + # translate default value if it is used | |
76 | + if not val.nil? then val elsif default.is_a? String then gettext default else default end | |
77 | + end | |
78 | + | |
79 | + define_method "#{setting}=" do |value| | |
80 | + h = send self.class.settings_field | |
81 | + h[setting] = if type then ActsAsHavingSettings.type_cast value, type else value end | |
82 | + end | |
83 | + end | |
84 | + end | |
85 | + | |
86 | + end | |
87 | + | |
88 | +end | |
89 | + | ... | ... |
... | ... | @@ -0,0 +1,57 @@ |
1 | +module CodeNumbering | |
2 | + module ClassMethods | |
3 | + def code_numbering field, options = {} | |
4 | + class_attribute :code_numbering_field | |
5 | + class_attribute :code_numbering_options | |
6 | + | |
7 | + self.code_numbering_field = field | |
8 | + self.code_numbering_options = options | |
9 | + | |
10 | + before_create :create_code_numbering | |
11 | + | |
12 | + include CodeNumbering::InstanceMethods | |
13 | + end | |
14 | + end | |
15 | + | |
16 | + module InstanceMethods | |
17 | + | |
18 | + def code | |
19 | + self.attributes[self.code_numbering_field.to_s] | |
20 | + end | |
21 | + | |
22 | + def code_scope | |
23 | + scope = self.code_numbering_options[:scope] | |
24 | + case scope | |
25 | + when Symbol | |
26 | + self.send scope | |
27 | + when Proc | |
28 | + instance_exec &scope | |
29 | + else | |
30 | + self.class | |
31 | + end | |
32 | + end | |
33 | + | |
34 | + def code_maximum | |
35 | + self.code_scope.maximum(self.code_numbering_field) || 0 | |
36 | + end | |
37 | + | |
38 | + def create_code_numbering | |
39 | + max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start] | |
40 | + max = self.code_maximum | |
41 | + self.send "#{self.code_numbering_field}=", max+1 | |
42 | + end | |
43 | + | |
44 | + def reset_scope_code_numbering | |
45 | + max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start] | |
46 | + max ||= 1 | |
47 | + | |
48 | + self.code_scope.order(:created_at).each do |record| | |
49 | + record.update_column self.code_numbering_field, max | |
50 | + max += 1 | |
51 | + end | |
52 | + self.reload | |
53 | + end | |
54 | + | |
55 | + end | |
56 | +end | |
57 | + | ... | ... |
... | ... | @@ -0,0 +1,124 @@ |
1 | +module Customizable | |
2 | + | |
3 | + def self.included(base) | |
4 | + base.attr_accessible :custom_values | |
5 | + base.extend ClassMethods | |
6 | + end | |
7 | + | |
8 | + module ClassMethods | |
9 | + def acts_as_customizable(options = {}) | |
10 | + attr_accessor :custom_values | |
11 | + has_many :custom_field_values, :dependent => :delete_all, :as => :customized | |
12 | + send :include, Customizable::InstanceMethods | |
13 | + after_save :save_custom_values | |
14 | + validate :valid_custom_values? | |
15 | + end | |
16 | + | |
17 | + def active_custom_fields environment | |
18 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.active} | |
19 | + end | |
20 | + | |
21 | + def required_custom_fields environment | |
22 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.required} | |
23 | + end | |
24 | + | |
25 | + def signup_custom_fields environment | |
26 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.signup} | |
27 | + end | |
28 | + | |
29 | + def custom_fields environment | |
30 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type)} | |
31 | + end | |
32 | + | |
33 | + def customized_ancestors_list | |
34 | + current=self | |
35 | + result=[] | |
36 | + while current.instance_methods.include? :custom_value do | |
37 | + result << current.name | |
38 | + current=current.superclass | |
39 | + end | |
40 | + result | |
41 | + end | |
42 | + | |
43 | + end | |
44 | + | |
45 | + module InstanceMethods | |
46 | + | |
47 | + def valid_custom_values? | |
48 | + is_valid = true | |
49 | + parse_custom_values.each do |cv| | |
50 | + unless cv.valid? | |
51 | + name = cv.custom_field.name | |
52 | + errors.add(name, cv.errors.messages[name.to_sym].first) | |
53 | + is_valid = false | |
54 | + end | |
55 | + end | |
56 | + is_valid | |
57 | + end | |
58 | + | |
59 | + def customized_class | |
60 | + current=self.class | |
61 | + while current.instance_methods.include? :custom_fields do | |
62 | + result=current | |
63 | + current=current.superclass | |
64 | + end | |
65 | + result.name | |
66 | + end | |
67 | + | |
68 | + def is_public(field_name) | |
69 | + cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name} | |
70 | + cv.nil? ? false : cv.public | |
71 | + end | |
72 | + | |
73 | + def public_values | |
74 | + self.custom_field_values.select{|cv| cv.public} | |
75 | + end | |
76 | + | |
77 | + def custom_value(field_name) | |
78 | + cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name} | |
79 | + cv.nil? ? default_value_for(field_name) : cv.value | |
80 | + end | |
81 | + | |
82 | + def default_value_for(field_name) | |
83 | + field=self.class.custom_fields(environment).detect {|c| c.name == field_name} | |
84 | + field.nil? ? nil : field.default_value | |
85 | + end | |
86 | + | |
87 | + def parse_custom_values | |
88 | + return_list = [] | |
89 | + return return_list if custom_values.blank? | |
90 | + custom_values.each_pair do |key, value| | |
91 | + custom_field = environment.custom_fields.detect{|cf|cf.name==key} | |
92 | + next if custom_field.blank? | |
93 | + custom_field_value = self.custom_field_values(true).detect{|cv| cv.custom_field.name==key} | |
94 | + | |
95 | + if custom_field_value.nil? | |
96 | + custom_field_value = CustomFieldValue.new | |
97 | + custom_field_value.custom_field = custom_field | |
98 | + custom_field_value.customized = self | |
99 | + end | |
100 | + | |
101 | + if value.is_a?(Hash) | |
102 | + custom_field_value.value = value['value'].to_s | |
103 | + if value.has_key?('public') | |
104 | + is_public = value['public']=="true" || value['public']==true | |
105 | + custom_field_value.public = is_public | |
106 | + else | |
107 | + custom_field_value.public = false | |
108 | + end | |
109 | + else | |
110 | + custom_field_value.value = value.to_s | |
111 | + custom_field_value.public = false | |
112 | + end | |
113 | + return_list << custom_field_value | |
114 | + end | |
115 | + return_list | |
116 | + end | |
117 | + | |
118 | + def save_custom_values | |
119 | + parse_custom_values.each(&:save) | |
120 | + end | |
121 | + | |
122 | + end | |
123 | +end | |
124 | + | ... | ... |
... | ... | @@ -0,0 +1,55 @@ |
1 | +module DelayedAttachmentFu | |
2 | + | |
3 | + module ClassMethods | |
4 | + def delay_attachment_fu_thumbnails | |
5 | + include DelayedAttachmentFu::InstanceMethods | |
6 | + after_create do |file| | |
7 | + if file.thumbnailable? | |
8 | + Delayed::Job.enqueue CreateThumbnailsJob.new(file.class.name, file.id) | |
9 | + end | |
10 | + end | |
11 | + end | |
12 | + end | |
13 | + | |
14 | + module InstanceMethods | |
15 | + # skip processing with RMagick | |
16 | + def process_attachment | |
17 | + end | |
18 | + | |
19 | + def after_process_attachment | |
20 | + save_to_storage | |
21 | + @temp_paths.clear | |
22 | + @saved_attachment = nil | |
23 | + run_callbacks :after_attachment_saved | |
24 | + end | |
25 | + | |
26 | + def create_thumbnails | |
27 | + if thumbnailable? | |
28 | + self.class.with_image(full_filename) do |img| | |
29 | + self.width = img.columns | |
30 | + self.height = img.rows | |
31 | + self.save! | |
32 | + end | |
33 | + self.class.attachment_options[:thumbnails].each do |suffix, size| | |
34 | + self.create_or_update_thumbnail(self.full_filename, suffix, size) | |
35 | + end | |
36 | + self.thumbnails_processed = true | |
37 | + self.save! | |
38 | + end | |
39 | + end | |
40 | + | |
41 | + def public_filename(size=nil) | |
42 | + force, size = true, nil if size == :uploaded | |
43 | + if !self.thumbnailable? || self.thumbnails_processed || force | |
44 | + super size | |
45 | + else | |
46 | + size ||= :thumb | |
47 | + '/images/icons-app/image-loading-%s.png' % size | |
48 | + end | |
49 | + end | |
50 | + | |
51 | + | |
52 | + end | |
53 | +end | |
54 | + | |
55 | + | ... | ... |
app/models/concerns/set_profile_region_from_city_state.rb
0 → 100644
... | ... | @@ -0,0 +1,44 @@ |
1 | +module SetProfileRegionFromCityState | |
2 | + | |
3 | + module ClassMethods | |
4 | + def set_profile_region_from_city_state | |
5 | + before_save :region_from_city_and_state | |
6 | + | |
7 | + include InstanceMethods | |
8 | + alias_method_chain :city=, :region | |
9 | + alias_method_chain :state=, :region | |
10 | + end | |
11 | + end | |
12 | + | |
13 | + module InstanceMethods | |
14 | + include Noosfero::Plugin::HotSpot | |
15 | + | |
16 | + def city_with_region=(value) | |
17 | + self.city_without_region = value | |
18 | + @change_region = true | |
19 | + end | |
20 | + | |
21 | + def state_with_region=(value) | |
22 | + self.state_without_region = value | |
23 | + @change_region = true | |
24 | + end | |
25 | + | |
26 | + def region_from_city_and_state | |
27 | + if @change_region | |
28 | + self.region = nil | |
29 | + state = search_region(State, self.state) | |
30 | + self.region = search_region(City.where(:parent_id => state.id), self.city) if state | |
31 | + end | |
32 | + end | |
33 | + | |
34 | + private | |
35 | + | |
36 | + def search_region(scope, query) | |
37 | + return nil if !query | |
38 | + query = query.downcase.strip | |
39 | + scope.where(['lower(name)=? OR lower(abbreviation)=? OR lower(acronym)=?', query, query, query]).first | |
40 | + end | |
41 | + | |
42 | + end | |
43 | + | |
44 | +end | ... | ... |
... | ... | @@ -0,0 +1,37 @@ |
1 | +module WhiteListFilter | |
2 | + | |
3 | + def check_iframe_on_content(content, trusted_sites) | |
4 | + if content.blank? || !content.include?('iframe') | |
5 | + return content | |
6 | + end | |
7 | + content.gsub!(/<iframe[^>]*>\s*<\/iframe>/i) do |iframe| | |
8 | + result = '' | |
9 | + unless iframe =~ /src=['"].*src=['"]/ | |
10 | + trusted_sites.each do |trusted_site| | |
11 | + re_dom = trusted_site.gsub('.', '\.') | |
12 | + if iframe =~ /src=["'](https?:)?\/\/(www\.)?#{re_dom}\// | |
13 | + result = iframe | |
14 | + end | |
15 | + end | |
16 | + end | |
17 | + result | |
18 | + end | |
19 | + content | |
20 | + end | |
21 | + | |
22 | + module ClassMethods | |
23 | + def filter_iframes(*opts) | |
24 | + options = opts.last.is_a?(Hash) && opts.pop || {} | |
25 | + white_list_method = options[:whitelist] || :iframe_whitelist | |
26 | + opts.each do |field| | |
27 | + before_validation do |obj| | |
28 | + obj.check_iframe_on_content(obj.send(field), obj.send(white_list_method)) | |
29 | + end | |
30 | + end | |
31 | + end | |
32 | + end | |
33 | + | |
34 | + def self.included(c) | |
35 | + c.send(:extend, WhiteListFilter::ClassMethods) | |
36 | + end | |
37 | +end | ... | ... |
app/models/create_community.rb
... | ... | @@ -12,6 +12,7 @@ class CreateCommunity < Task |
12 | 12 | attr_accessible :environment, :requestor, :target |
13 | 13 | attr_accessible :reject_explanation, :template_id |
14 | 14 | |
15 | + extend ActsAsHavingImage::ClassMethods | |
15 | 16 | acts_as_having_image |
16 | 17 | |
17 | 18 | DATA_FIELDS = Community.fields + ['name', 'closed', 'description'] | ... | ... |
app/models/enterprise.rb
app/models/environment.rb
... | ... | @@ -200,6 +200,7 @@ class Environment < ApplicationRecord |
200 | 200 | # Relationships and applied behaviour |
201 | 201 | # ################################################# |
202 | 202 | |
203 | + extend ActsAsHavingBoxes::ClassMethods | |
203 | 204 | acts_as_having_boxes |
204 | 205 | |
205 | 206 | after_create do |env| |
... | ... | @@ -251,7 +252,8 @@ class Environment < ApplicationRecord |
251 | 252 | # ################################################# |
252 | 253 | |
253 | 254 | # store the Environment settings as YAML-serialized Hash. |
254 | - acts_as_having_settings :field => :settings | |
255 | + extend ActsAsHavingSettings::ClassMethods | |
256 | + acts_as_having_settings field: :settings | |
255 | 257 | |
256 | 258 | # introduce and explain to users something about the signup |
257 | 259 | settings_items :signup_intro, :type => String | ... | ... |
app/models/event.rb
1 | -require 'noosfero/translatable_content' | |
2 | 1 | require 'builder' |
3 | 2 | |
4 | 3 | class Event < Article |
... | ... | @@ -138,7 +137,7 @@ class Event < Article |
138 | 137 | false |
139 | 138 | end |
140 | 139 | |
141 | - include Noosfero::TranslatableContent | |
140 | + include TranslatableContent | |
142 | 141 | include MaybeAddHttp |
143 | 142 | |
144 | 143 | end | ... | ... |
app/models/favorite_enterprise_person.rb
... | ... | @@ -7,6 +7,10 @@ class FavoriteEnterprisePerson < ApplicationRecord |
7 | 7 | belongs_to :enterprise |
8 | 8 | belongs_to :person |
9 | 9 | |
10 | + after_create do |favorite| | |
11 | + favorite.person.follow(favorite.enterprise, Circle.find_or_create_by(:person => favorite.person, :name =>_('favorites'), :profile_type => 'Enterprise')) | |
12 | + end | |
13 | + | |
10 | 14 | protected |
11 | 15 | |
12 | 16 | def is_trackable? | ... | ... |
app/models/folder.rb
... | ... | @@ -10,7 +10,8 @@ class Folder < Article |
10 | 10 | errors.add(:parent, "A folder should not belong to a blog.") if parent && parent.blog? |
11 | 11 | end |
12 | 12 | |
13 | - acts_as_having_settings :field => :setting | |
13 | + extend ActsAsHavingSettings::ClassMethods | |
14 | + acts_as_having_settings field: :setting | |
14 | 15 | |
15 | 16 | xss_terminate :only => [ :name, :body ], :with => 'white_list', :on => 'validation' |
16 | 17 | ... | ... |
app/models/forum.rb
app/models/friendship.rb
... | ... | @@ -9,11 +9,19 @@ class Friendship < ApplicationRecord |
9 | 9 | after_create do |friendship| |
10 | 10 | Friendship.update_cache_counter(:friends_count, friendship.person, 1) |
11 | 11 | Friendship.update_cache_counter(:friends_count, friendship.friend, 1) |
12 | + | |
13 | + circles = friendship.group.blank? ? ['friendships'] : friendship.group.split(',').map(&:strip) | |
14 | + circles.each do |circle| | |
15 | + friendship.person.follow(friendship.friend, Circle.find_or_create_by(:person => friendship.person, :name => circle, :profile_type => 'Person')) | |
16 | + end | |
12 | 17 | end |
13 | 18 | |
14 | 19 | after_destroy do |friendship| |
15 | 20 | Friendship.update_cache_counter(:friends_count, friendship.person, -1) |
16 | 21 | Friendship.update_cache_counter(:friends_count, friendship.friend, -1) |
22 | + | |
23 | + circle = Circle.find_by(:person => friendship.person, :name => (friendship.group.blank? ? 'friendships': friendship.group) ) | |
24 | + friendship.person.remove_profile_from_circle(friendship.friend, circle) if circle | |
17 | 25 | end |
18 | 26 | |
19 | 27 | def self.remove_friendship(person1, person2) | ... | ... |
app/models/image.rb
... | ... | @@ -23,6 +23,7 @@ class Image < ApplicationRecord |
23 | 23 | |
24 | 24 | validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n |
25 | 25 | |
26 | + extend DelayedAttachmentFu::ClassMethods | |
26 | 27 | delay_attachment_fu_thumbnails |
27 | 28 | |
28 | 29 | postgresql_attachment_fu | ... | ... |
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/models/person.rb
... | ... | @@ -8,7 +8,6 @@ class Person < Profile |
8 | 8 | :display => %w[compact] |
9 | 9 | } |
10 | 10 | |
11 | - | |
12 | 11 | def self.type_name |
13 | 12 | _('Person') |
14 | 13 | end |
... | ... | @@ -93,6 +92,7 @@ class Person < Profile |
93 | 92 | has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article |
94 | 93 | has_many :friendships, :dependent => :destroy |
95 | 94 | has_many :friends, :class_name => 'Person', :through => :friendships |
95 | + has_many :circles | |
96 | 96 | |
97 | 97 | scope :online, -> { |
98 | 98 | joins(:user).where("users.chat_status != '' AND users.chat_status_at >= ?", DateTime.now - User.expires_chat_status_every.minutes) |
... | ... | @@ -200,6 +200,33 @@ class Person < Profile |
200 | 200 | end |
201 | 201 | end |
202 | 202 | |
203 | + def follow(profile, circles) | |
204 | + circles = [circles] unless circles.is_a?(Array) | |
205 | + circles.each do |new_circle| | |
206 | + ProfileFollower.create(profile: profile, circle: new_circle) | |
207 | + end | |
208 | + end | |
209 | + | |
210 | + def update_profile_circles(profile, new_circles) | |
211 | + profile_circles = ProfileFollower.with_profile(profile).with_follower(self).map(&:circle) | |
212 | + circles_to_add = new_circles - profile_circles | |
213 | + circles_to_remove = profile_circles - new_circles | |
214 | + circles_to_add.each do |new_circle| | |
215 | + ProfileFollower.create(profile: profile, circle: new_circle) | |
216 | + end | |
217 | + | |
218 | + ProfileFollower.where('circle_id IN (?) AND profile_id = ?', | |
219 | + circles_to_remove.map(&:id), profile.id).destroy_all | |
220 | + end | |
221 | + | |
222 | + def unfollow(profile) | |
223 | + ProfileFollower.with_follower(self).with_profile(profile).destroy_all | |
224 | + end | |
225 | + | |
226 | + def remove_profile_from_circle(profile, circle) | |
227 | + ProfileFollower.with_profile(profile).with_circle(circle).destroy_all | |
228 | + end | |
229 | + | |
203 | 230 | def already_request_friendship?(person) |
204 | 231 | person.tasks.where(requestor_id: self.id, type: 'AddFriend', status: Task::Status::ACTIVE).first |
205 | 232 | end |
... | ... | @@ -580,9 +607,12 @@ class Person < Profile |
580 | 607 | person.has_permission?(:manage_friends, self) |
581 | 608 | end |
582 | 609 | |
583 | - protected | |
610 | + def followed_profiles | |
611 | + Profile.followed_by self | |
612 | + end | |
584 | 613 | |
585 | - def followed_by?(profile) | |
586 | - self == profile || self.is_a_friend?(profile) | |
614 | + def in_social_circle?(person) | |
615 | + self.is_a_friend?(person) || super | |
587 | 616 | end |
617 | + | |
588 | 618 | end | ... | ... |
app/models/profile.rb
... | ... | @@ -5,7 +5,7 @@ class Profile < ApplicationRecord |
5 | 5 | |
6 | 6 | attr_accessible :name, :identifier, :public_profile, :nickname, :custom_footer, :custom_header, :address, :zip_code, :contact_phone, :image_builder, :description, :closed, :template_id, :environment, :lat, :lng, :is_template, :fields_privacy, :preferred_domain_id, :category_ids, :country, :city, :state, :national_region_code, :email, :contact_email, :redirect_l10n, :notification_time, |
7 | 7 | :redirection_after_login, :custom_url_redirection, |
8 | - :email_suggestions, :allow_members_to_invite, :invite_friends_only, :secret, :profile_admin_mail_notification | |
8 | + :email_suggestions, :allow_members_to_invite, :invite_friends_only, :secret, :profile_admin_mail_notification, :allow_followers | |
9 | 9 | |
10 | 10 | # use for internationalizable human type names in search facets |
11 | 11 | # reimplement on subclasses |
... | ... | @@ -88,6 +88,8 @@ class Profile < ApplicationRecord |
88 | 88 | } |
89 | 89 | |
90 | 90 | acts_as_accessible |
91 | + | |
92 | + include Customizable | |
91 | 93 | acts_as_customizable |
92 | 94 | |
93 | 95 | include Noosfero::Plugin::HotSpot |
... | ... | @@ -185,6 +187,21 @@ class Profile < ApplicationRecord |
185 | 187 | Person.members_of(self).by_role(roles) |
186 | 188 | end |
187 | 189 | |
190 | + extend ActsAsHavingSettings::ClassMethods | |
191 | + acts_as_having_settings field: :data | |
192 | + | |
193 | + def settings | |
194 | + data | |
195 | + end | |
196 | + | |
197 | + settings_items :redirect_l10n, :type => :boolean, :default => false | |
198 | + settings_items :public_content, :type => :boolean, :default => true | |
199 | + settings_items :description | |
200 | + settings_items :fields_privacy, :type => :hash, :default => {} | |
201 | + settings_items :email_suggestions, :type => :boolean, :default => false | |
202 | + settings_items :profile_admin_mail_notification, :type => :boolean, :default => true | |
203 | + | |
204 | + extend ActsAsHavingBoxes::ClassMethods | |
188 | 205 | acts_as_having_boxes |
189 | 206 | |
190 | 207 | acts_as_taggable |
... | ... | @@ -203,6 +220,23 @@ class Profile < ApplicationRecord |
203 | 220 | scope :more_active, -> { order 'activities_count DESC' } |
204 | 221 | scope :more_recent, -> { order "created_at DESC" } |
205 | 222 | |
223 | + scope :followed_by, -> person{ | |
224 | + distinct.select('profiles.*'). | |
225 | + joins('left join profiles_circles ON profiles_circles.profile_id = profiles.id'). | |
226 | + joins('left join circles ON circles.id = profiles_circles.circle_id'). | |
227 | + where('circles.person_id = ?', person.id) | |
228 | + } | |
229 | + | |
230 | + scope :in_circle, -> circle{ | |
231 | + distinct.select('profiles.*'). | |
232 | + joins('left join profiles_circles ON profiles_circles.profile_id = profiles.id'). | |
233 | + joins('left join circles ON circles.id = profiles_circles.circle_id'). | |
234 | + where('circles.id = ?', circle.id) | |
235 | + } | |
236 | + | |
237 | + settings_items :allow_followers, :type => :boolean, :default => true | |
238 | + alias_method :allow_followers?, :allow_followers | |
239 | + | |
206 | 240 | acts_as_trackable :dependent => :destroy |
207 | 241 | |
208 | 242 | has_many :profile_activities |
... | ... | @@ -215,6 +249,9 @@ class Profile < ApplicationRecord |
215 | 249 | |
216 | 250 | has_many :email_templates, :foreign_key => :owner_id |
217 | 251 | |
252 | + has_many :profile_followers | |
253 | + has_many :followers, -> { uniq }, :class_name => 'Person', :through => :profile_followers, :source => :person | |
254 | + | |
218 | 255 | # Although this should be a has_one relation, there are no non-silly names for |
219 | 256 | # a foreign key on article to reference the template to which it is |
220 | 257 | # welcome_page... =P |
... | ... | @@ -231,19 +268,6 @@ class Profile < ApplicationRecord |
231 | 268 | scrap.nil? ? Scrap.all_scraps(self) : Scrap.all_scraps(self).find(scrap) |
232 | 269 | end |
233 | 270 | |
234 | - acts_as_having_settings :field => :data | |
235 | - | |
236 | - def settings | |
237 | - data | |
238 | - end | |
239 | - | |
240 | - settings_items :redirect_l10n, :type => :boolean, :default => false | |
241 | - settings_items :public_content, :type => :boolean, :default => true | |
242 | - settings_items :description | |
243 | - settings_items :fields_privacy, :type => :hash, :default => {} | |
244 | - settings_items :email_suggestions, :type => :boolean, :default => false | |
245 | - settings_items :profile_admin_mail_notification, :type => :boolean, :default => true | |
246 | - | |
247 | 271 | validates_length_of :description, :maximum => 550, :allow_nil => true |
248 | 272 | |
249 | 273 | # Valid identifiers must match this format. |
... | ... | @@ -285,6 +309,7 @@ class Profile < ApplicationRecord |
285 | 309 | |
286 | 310 | has_many :files, :class_name => 'UploadedFile' |
287 | 311 | |
312 | + extend ActsAsHavingImage::ClassMethods | |
288 | 313 | acts_as_having_image |
289 | 314 | |
290 | 315 | has_many :tasks, :dependent => :destroy, :as => 'target' |
... | ... | @@ -758,12 +783,13 @@ private :generate_url, :url_options |
758 | 783 | |
759 | 784 | # Adds a person as member of this Profile. |
760 | 785 | def add_member(person, attributes={}) |
761 | - if self.has_members? | |
786 | + if self.has_members? && !self.secret | |
762 | 787 | if self.closed? && members.count > 0 |
763 | 788 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) |
764 | 789 | else |
765 | 790 | self.affiliate(person, Profile::Roles.admin(environment.id), attributes) if members.count == 0 |
766 | 791 | self.affiliate(person, Profile::Roles.member(environment.id), attributes) |
792 | + person.follow(self, Circle.find_or_create_by(:person => person, :name =>_('memberships'), :profile_type => 'Community')) | |
767 | 793 | end |
768 | 794 | person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } |
769 | 795 | remove_from_suggestion_list person |
... | ... | @@ -1107,7 +1133,11 @@ private :generate_url, :url_options |
1107 | 1133 | end |
1108 | 1134 | |
1109 | 1135 | def followed_by?(person) |
1110 | - person.is_member_of?(self) | |
1136 | + (person == self) || (person.in? self.followers) | |
1137 | + end | |
1138 | + | |
1139 | + def in_social_circle?(person) | |
1140 | + (person == self) || (person.is_member_of?(self)) | |
1111 | 1141 | end |
1112 | 1142 | |
1113 | 1143 | def display_private_info_to?(user) |
... | ... | @@ -1148,4 +1178,8 @@ private :generate_url, :url_options |
1148 | 1178 | def allow_destroy?(person = nil) |
1149 | 1179 | person.kind_of?(Profile) && person.has_permission?('destroy_profile', self) |
1150 | 1180 | end |
1181 | + | |
1182 | + def in_circle?(circle, follower) | |
1183 | + ProfileFollower.with_follower(follower).with_circle(circle).with_profile(self).present? | |
1184 | + end | |
1151 | 1185 | end | ... | ... |
... | ... | @@ -0,0 +1,28 @@ |
1 | +class ProfileFollower < ApplicationRecord | |
2 | + self.table_name = :profiles_circles | |
3 | + track_actions :new_follower, :after_create, :keep_params => ["follower.name", "follower.url", "follower.profile_custom_icon"], :custom_user => :profile | |
4 | + | |
5 | + attr_accessible :profile, :circle | |
6 | + | |
7 | + belongs_to :profile | |
8 | + belongs_to :circle | |
9 | + | |
10 | + has_one :person, through: :circle | |
11 | + alias follower person | |
12 | + | |
13 | + validates_presence_of :profile_id, :circle_id | |
14 | + validates :profile_id, :uniqueness => {:scope => :circle_id, :message => "can't put a profile in the same circle twice"} | |
15 | + | |
16 | + scope :with_follower, -> person{ | |
17 | + joins(:circle).where('circles.person_id = ?', person.id) | |
18 | + } | |
19 | + | |
20 | + scope :with_profile, -> profile{ | |
21 | + where(:profile => profile) | |
22 | + } | |
23 | + | |
24 | + scope :with_circle, -> circle{ | |
25 | + where(:circle => circle) | |
26 | + } | |
27 | + | |
28 | +end | ... | ... |
app/models/profile_suggestion.rb
... | ... | @@ -17,7 +17,8 @@ class ProfileSuggestion < ApplicationRecord |
17 | 17 | self.class.generate_profile_suggestions(profile_suggestion.person) |
18 | 18 | end |
19 | 19 | |
20 | - acts_as_having_settings :field => :categories | |
20 | + extend ActsAsHavingSettings::ClassMethods | |
21 | + acts_as_having_settings field: :categories | |
21 | 22 | |
22 | 23 | validate :must_be_a_valid_category, :on => :create |
23 | 24 | def must_be_a_valid_category | ... | ... |
app/models/task.rb
... | ... | @@ -11,7 +11,8 @@ |
11 | 11 | # will need to declare <ttserialize</tt> itself). |
12 | 12 | class Task < ApplicationRecord |
13 | 13 | |
14 | - acts_as_having_settings :field => :data | |
14 | + extend ActsAsHavingSettings::ClassMethods | |
15 | + acts_as_having_settings field: :data | |
15 | 16 | |
16 | 17 | module Status |
17 | 18 | # the status of tasks just created | ... | ... |
app/models/text_article.rb
1 | -require 'noosfero/translatable_content' | |
2 | - | |
3 | 1 | # a base class for all text article types. |
4 | 2 | class TextArticle < Article |
5 | 3 | |
... | ... | @@ -9,7 +7,7 @@ class TextArticle < Article |
9 | 7 | _('Article') |
10 | 8 | end |
11 | 9 | |
12 | - include Noosfero::TranslatableContent | |
10 | + include TranslatableContent | |
13 | 11 | |
14 | 12 | def self.icon_name(article = nil) |
15 | 13 | if article && !article.parent.nil? && article.parent.kind_of?(Blog) | ... | ... |
app/models/tiny_mce_article.rb
app/models/uploaded_file.rb
... | ... | @@ -84,6 +84,7 @@ class UploadedFile < Article |
84 | 84 | |
85 | 85 | validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of %{size}").sub('%{size}', self.max_size.to_humanreadable).fix_i18n |
86 | 86 | |
87 | + extend DelayedAttachmentFu::ClassMethods | |
87 | 88 | delay_attachment_fu_thumbnails |
88 | 89 | |
89 | 90 | postgresql_attachment_fu | ... | ... |
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%')) %> | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +<div class="circles" id='circles-list'> | |
2 | + | |
3 | + <%= form_for :circles, :url => {:controller => 'profile', :action => 'follow'}, :html => {:id => "follow-circles-form"} do |f|%> | |
4 | + <%= render partial: "blocks/profile_info_actions/select_circles", :locals => {:circles => circles, :followed_profile => profile, :follower => current_person } %> | |
5 | + | |
6 | + <div id="circle-actions"> | |
7 | + <%= submit_button :ok, _("Follow") %> | |
8 | + <input type="button" value="<%= _("Cancel") %>" id="cancel-set-circle" class="button with-text icon-cancel"/> | |
9 | + </div> | |
10 | + <% end %> | |
11 | +</div> | ... | ... |
app/views/blocks/profile_info_actions/_common.html.erb
1 | 1 | <li><%= report_abuse(profile, :button) %></li> |
2 | +<% if logged_in? && (user != profile) && profile.allow_followers? %> | |
3 | + <li> | |
4 | + <% follow = user.follows?(profile) %> | |
5 | + <%= button(:unfollow, content_tag('span', _('Unfollow')), {:profile => profile.identifier, :controller => 'profile', :action => 'unfollow'}, :method => :post, :id => 'action-unfollow', :title => _("Unfollow"), :style => follow ? "" : "display: none;") %> | |
6 | + <%= button(:ok, content_tag('span', _('Follow')), {:profile => profile.identifier, :controller => 'profile', :action => 'find_profile_circles'}, :id => 'action-follow', :title => _("Follow"), :style => follow ? "display: none;" : "") %> | |
7 | + <div id="circles-container" style="display: none;"> | |
8 | + </div> | |
9 | + </li> | |
10 | +<% end %> | |
2 | 11 | <%= render_environment_features(:profile_actions) %> | ... | ... |
app/views/blocks/profile_info_actions/_select_circles.html.erb
0 → 100644
... | ... | @@ -0,0 +1,22 @@ |
1 | +<div class="circles" id='circles-list'> | |
2 | + <p><%= _("Select the circles for %s") % followed_profile.name %></p> | |
3 | + <div id="circles-checkboxes"> | |
4 | + <% circles.each do |circle| %> | |
5 | + <div class="circle"> | |
6 | + <%= labelled_check_box circle.name, "circles[#{circle.name}]", circle.id, followed_profile.in_circle?(circle, follower) %> | |
7 | + </div> | |
8 | + <% end %> | |
9 | + </div> | |
10 | + | |
11 | + <%= button(:add, _('New Circle'), '#', :id => "new-circle") %> | |
12 | + | |
13 | + <div id="new-circle-form" style="display: none;"> | |
14 | + <%= labelled_text_field _('Circle name') , 'circle[name]', "",:id => 'text-field-name-new-circle'%> | |
15 | + <%= hidden_field_tag('circle[profile_type]', followed_profile.class.name) %> | |
16 | + | |
17 | + <%= button_bar do %> | |
18 | + <%= button(:save, _('Create'), {:profile => follower.identifier, :controller => 'circles', :action => 'xhr_create'}, :id => "new-circle-submit") %> | |
19 | + <%= button(:cancel, _('Cancel'), '#', :id => "new-circle-cancel") %> | |
20 | + <% end %> | |
21 | + </div> | |
22 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +<%= error_messages_for :circle %> | |
2 | + | |
3 | +<%= labelled_form_for :circle, :url => (mode == :edit) ? {:action => 'update', :id => circle} : {:action => 'create'} do |f| %> | |
4 | + | |
5 | + <%= required_fields_message %> | |
6 | + | |
7 | + <%= required f.text_field(:name) %> | |
8 | + | |
9 | + <%= required labelled_form_field _("Profile type"), f.select(:profile_type, Circle.profile_types.to_a) %> | |
10 | + | |
11 | + <%= button_bar do %> | |
12 | + <%= submit_button('save', (mode == :edit) ? _('Save changes') : _('Create circle'), :cancel => {:action => 'index'} ) %> | |
13 | + <% end %> | |
14 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,30 @@ |
1 | +<h1><%= _('Manage circles') %></h1> | |
2 | + | |
3 | +<table> | |
4 | + <tr> | |
5 | + <th><%= _('Circle name') %></th> | |
6 | + <th><%= _('Profile type') %></th> | |
7 | + <th><%= _('Actions') %></th> | |
8 | + </tr> | |
9 | + <% @circles.each do |circle| %> | |
10 | + <tr> | |
11 | + <td> | |
12 | + <%= circle.name %> | |
13 | + </td> | |
14 | + <td> | |
15 | + <%= _(circle.profile_type) %> | |
16 | + </td> | |
17 | + <td> | |
18 | + <div style="text-align: center;"> | |
19 | + <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => circle %> | |
20 | + <%= button_without_text :delete, _('Delete'), { :action => 'destroy', :id => circle }, { "data-method" => "POST" } %> | |
21 | + </div> | |
22 | + </td> | |
23 | + </tr> | |
24 | + <% end %> | |
25 | +</table> | |
26 | + | |
27 | +<%= button_bar do %> | |
28 | + <%= button :add, _('Create a new circle'), :action => 'new' %> | |
29 | + <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> | |
30 | +<% end %> | ... | ... |
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
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/file_presenter/_image.html.erb
... | ... | @@ -4,15 +4,15 @@ |
4 | 4 | current_index = images.index(image.encapsulated_file) |
5 | 5 | total_of_images = images.count |
6 | 6 | link_to_previous = if current_index >= 1 |
7 | - link_to(_('« Previous'), images[current_index - 1].view_url, :class => 'previous') | |
7 | + link_to(_('« Previous').html_safe, images[current_index - 1].view_url, :class => 'previous') | |
8 | 8 | else |
9 | - content_tag('span', _('« Previous'), :class => 'previous') | |
9 | + content_tag('span', _('« Previous').html_safe, :class => 'previous') | |
10 | 10 | end |
11 | 11 | |
12 | 12 | link_to_next = if current_index < total_of_images - 1 |
13 | - link_to(_('Next »'), images[current_index + 1].view_url, :class => 'next') | |
13 | + link_to(_('Next »').html_safe, images[current_index + 1].view_url, :class => 'next') | |
14 | 14 | else |
15 | - content_tag('span', _('Next »'), :class => 'next') | |
15 | + content_tag('span', _('Next »').html_safe, :class => 'next') | |
16 | 16 | end |
17 | 17 | %> |
18 | 18 | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +<div class="circles" id='circles-list'> | |
2 | + <%= form_for :circles, :url => {:controller => 'followers', :action => 'update_category'}, :html => {:id => "follow-circles-form"} do |f|%> | |
3 | + <%= render partial: "blocks/profile_info_actions/select_circles", :locals => {:circles => circles, :followed_profile => followed_profile, :follower => profile } %> | |
4 | + | |
5 | + <%= hidden_field_tag('followed_profile_id', followed_profile.id) %> | |
6 | + | |
7 | + <div id="circle-actions"> | |
8 | + <div id="actions-container"> | |
9 | + <%= submit_button('save', _('Save')) %> | |
10 | + <%= modal_close_button _("Cancel") %> | |
11 | + </div> | |
12 | + </div> | |
13 | + <% end %> | |
14 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,17 @@ |
1 | +<ul class="profile-list"> | |
2 | + <% profiles.each do |followed_profile| %> | |
3 | + <li> | |
4 | + <%= link_to_profile profile_image(followed_profile) + tag('br') + followed_profile.short_name, | |
5 | + followed_profile.identifier, :class => 'profile-link' %> | |
6 | + <div class="controll"> | |
7 | + <%= button_without_text :remove, content_tag('span',_('unfollow')), | |
8 | + { :controller => "profile", :profile => followed_profile.identifier, :follower_id => profile.id, | |
9 | + :action => 'unfollow', :redirect_to => url_for({:controller => "followers", :profile => profile.identifier}) }, | |
10 | + :method => :post, :title => _('remove') %> | |
11 | + <%= modal_icon_button :edit, _('change category'), | |
12 | + url_for(:controller => 'followers', :action => 'set_category_modal', | |
13 | + :followed_profile_id => followed_profile.id) %> | |
14 | + </div><!-- end class="controll" --> | |
15 | + </li> | |
16 | + <% end %> | |
17 | +</ul> | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +<div id="manage_followed people"> | |
2 | + | |
3 | +<h1><%= _("%s is following") % profile.name %></h1> | |
4 | + | |
5 | +<% cache_timeout(profile.manage_friends_cache_key(params), 4.hours) do %> | |
6 | + <% if @followed_people.empty? %> | |
7 | + <p> | |
8 | + <em> | |
9 | + <%= _("You don't follow anybody yet.") %> | |
10 | + </em> | |
11 | + </p> | |
12 | + <% end %> | |
13 | + | |
14 | + <%= button_bar do %> | |
15 | + <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> | |
16 | + <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> | |
17 | + <% end %> | |
18 | + | |
19 | + <%= labelled_select(_('Profile type')+': ', :filter_profile_type, :last, :first, @active_filter, @profile_types, :id => "profile-type-filter") %> | |
20 | + | |
21 | + <%= render :partial => 'profile_list', :locals => { :profiles => @followed_people } %> | |
22 | + | |
23 | + <br style="clear:both" /> | |
24 | + <%= pagination_links @followed_people, :param_name => 'npage' %> | |
25 | +<% end %> | |
26 | + | |
27 | +</div> | ... | ... |
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/_create_article.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <td> |
6 | 6 | <p> |
7 | 7 | <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span> |
8 | - <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span> | |
8 | + <span style="font-size: 14px;"><%= _("has published on community %s").html_safe % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span> | |
9 | 9 | <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span> |
10 | 10 | </p> |
11 | 11 | <p> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity } %> | ... | ... |
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/person_notifier/mailer/content_summary.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <%= link_to @url, :style => "text-decoration: none;" do %> |
6 | 6 | <span style="font-weight:bold;font-size: 28px;margin: 0;color: white;background-color: #AAAAAA;padding: 5px;"><%= @environment.name %></span> |
7 | 7 | <% end %> |
8 | - <span style="font-weight:bold;color: #333;font-size:19px;margin-left: 8px;"><%= _("%s's Notifications") % @profile.name %></h3> | |
8 | + <span style="font-weight:bold;color: #333;font-size:19px;margin-left: 8px;"><%= _("%s's Notifications").html_safe % @profile.name %></h3> | |
9 | 9 | </div> |
10 | 10 | <div style="margin: 0 20px 20px 20px;border-top:1px solid #e2e2e2;"> |
11 | 11 | <% if @tasks.present? %> |
... | ... | @@ -34,7 +34,7 @@ |
34 | 34 | |
35 | 35 | <div style="color:#444444;font-size:11px;margin-bottom: 20px;"> |
36 | 36 | <p style="margin:0"><%= _("Greetings,") %></p> |
37 | - <p style="margin:0"><%= _('%s team.') % @environment.name %></p> | |
37 | + <p style="margin:0"><%= _('%s team.').html_safe % @environment.name %></p> | |
38 | 38 | <p style="margin:0"><%= link_to @url, url_for(@url) %></p> |
39 | 39 | </div> |
40 | 40 | </div> | ... | ... |
... | ... | @@ -0,0 +1,18 @@ |
1 | +<% cache_timeout(profile.friends_cache_key(params), 4.hours) do %> | |
2 | + <ul class='profile-list'> | |
3 | + <% follow.each do |follower| %> | |
4 | + <%= profile_image_link(follower) %> | |
5 | + <% end%> | |
6 | + </ul> | |
7 | + | |
8 | + <div id='pagination-profiles'> | |
9 | + <%= pagination_links follow, :param_name => 'npage' %> | |
10 | + </div> | |
11 | +<% end %> | |
12 | + | |
13 | +<%= button_bar do %> | |
14 | + <%= button :back, _('Go back'), { :controller => 'profile' } %> | |
15 | + <% if user == profile %> | |
16 | + <%= button :edit, _('Manage followed people'), :controller => 'friends', :action => 'index', :profile => profile.identifier %> | |
17 | + <% end %> | |
18 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity, :tab_action => tab_action } %> | ... | ... |
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,14 +18,16 @@ |
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 | |
25 | 25 | <h2><%= _('Privacy options') %></h2> |
26 | - | |
26 | + <div> | |
27 | + <%= labelled_check_box _("Allow other users to follow me"), 'profile_data[allow_followers]', true, @profile.allow_followers?, :class => "person-can-be-followed" %> | |
28 | + </div> | |
27 | 29 | <% if profile.person? %> |
28 | - <div> | |
30 | + <div id="profile_allow_follows"> | |
29 | 31 | <%= labelled_radio_button _('Public — show my contents to all internet users').html_safe, 'profile_data[public_profile]', true, @profile.public_profile? %> |
30 | 32 | </div> |
31 | 33 | <div> | ... | ... |
app/views/profile_editor/index.html.erb
... | ... | @@ -72,6 +72,11 @@ |
72 | 72 | |
73 | 73 | <%= control_panel_button(_('Email Templates'), 'email-templates', :controller => :profile_email_templates) if profile.organization? %> |
74 | 74 | |
75 | + <% if profile.person? %> | |
76 | + <%= control_panel_button(_('Manage followed profiles'), 'edit-profile', :controller => :followers) %> | |
77 | + <%= control_panel_button(_('Manage circles'), 'edit-profile-group', :controller => :circles) %> | |
78 | + <% end %> | |
79 | + | |
75 | 80 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> |
76 | 81 | <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %> |
77 | 82 | <% end %> | ... | ... |
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 %> | ... | ... |
config/initializers/00_dependencies.rb
... | ... | @@ -16,15 +16,6 @@ end |
16 | 16 | require 'extensions' |
17 | 17 | |
18 | 18 | # locally-developed modules |
19 | -require 'acts_as_filesystem' | |
20 | -require 'acts_as_having_settings' | |
21 | -require 'acts_as_having_boxes' | |
22 | -require 'acts_as_having_image' | |
23 | -require 'acts_as_having_posts' | |
24 | -require 'acts_as_customizable' | |
25 | 19 | require 'route_if' |
26 | 20 | require 'maybe_add_http' |
27 | -require 'set_profile_region_from_city_state' | |
28 | -require 'needs_profile' | |
29 | -require 'white_list_filter' | |
30 | 21 | ... | ... |
config/initializers/action_tracker.rb
db/migrate/20160422163123_enable_products_plugin_on_environments.rb
db/migrate/20160608123748_create_profile_followers_table.rb
0 → 100644
... | ... | @@ -0,0 +1,43 @@ |
1 | +class CreateProfileFollowersTable < ActiveRecord::Migration | |
2 | + def up | |
3 | + create_table :profiles_circles do |t| | |
4 | + t.column :profile_id, :integer | |
5 | + t.column :circle_id, :integer | |
6 | + t.timestamps | |
7 | + end | |
8 | + | |
9 | + create_table :circles do |t| | |
10 | + t.column :name, :string | |
11 | + t.belongs_to :person | |
12 | + t.column :profile_type, :string, :null => false | |
13 | + end | |
14 | + | |
15 | + add_foreign_key :profiles_circles, :circles, :on_delete => :nullify | |
16 | + | |
17 | + add_index :profiles_circles, [:profile_id, :circle_id], :name => "profiles_circles_composite_key_index", :unique => true | |
18 | + add_index :circles, [:person_id, :name], :name => "circles_composite_key_index", :unique => true | |
19 | + | |
20 | + #insert one category for each friend group a person has | |
21 | + execute("INSERT INTO circles(name, person_id, profile_type) SELECT DISTINCT 'friendships', f.person_id, 'Person' FROM friendships as f WHERE f.group IS NULL OR f.group = ''") | |
22 | + execute("INSERT INTO circles(name, person_id, profile_type) SELECT DISTINCT regexp_split_to_table(f.group, ', '), f.person_id, 'Person' FROM friendships as f WHERE f.group IS NOT NULL AND f.group <> ''") | |
23 | + #insert 'memberships' category if a person is in a community as any role | |
24 | + execute("INSERT INTO circles(name, person_id, profile_type) SELECT DISTINCT 'memberships', ra.accessor_id, 'Community' FROM role_assignments as ra JOIN profiles ON ra.resource_id = profiles.id WHERE ra.resource_type = 'Profile' AND profiles.type = 'Community'") | |
25 | + #insert 'favorites' category if a person has any favorited enterprise | |
26 | + execute("INSERT INTO circles(name, person_id, profile_type) SELECT DISTINCT 'favorites', person_id, 'Enterprise' FROM favorite_enterprise_people") | |
27 | + | |
28 | + #insert a follower entry for each friend, with the category the same as the friendship group or equals 'friendships' | |
29 | + execute("INSERT INTO profiles_circles(profile_id, circle_id) SELECT DISTINCT f.friend_id, c.id FROM friendships as f JOIN circles as c ON f.person_id = c.person_id WHERE c.name = ANY(regexp_split_to_array(f.group, ', ')) OR c.name = 'friendships'") | |
30 | + #insert a follower entry for each favorited enterprise, with the category 'favorites' | |
31 | + execute("INSERT INTO profiles_circles(profile_id, circle_id) SELECT DISTINCT f.enterprise_id, c.id FROM favorite_enterprise_people AS f JOIN circles as c ON f.person_id = c.person_id WHERE c.name = 'favorites' ") | |
32 | + #insert a follower entry for each community a person participates with any role | |
33 | + execute("INSERT INTO profiles_circles(profile_id, circle_id) SELECT DISTINCT ra.resource_id, c.id FROM role_assignments as ra JOIN profiles ON ra.accessor_id = profiles.id JOIN circles as c ON ra.accessor_id = c.person_id WHERE ra.resource_type = 'Profile' AND profiles.type = 'Community' AND c.name = 'memberships'") | |
34 | + end | |
35 | + | |
36 | + def down | |
37 | + remove_foreign_key :profiles_circles, :circles | |
38 | + remove_index :profiles_circles, :name => "profiles_circles_composite_key_index" | |
39 | + remove_index :circles, :name => "circles_composite_key_index" | |
40 | + drop_table :circles | |
41 | + drop_table :profiles_circles | |
42 | + end | |
43 | +end | ... | ... |
db/schema.rb
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | # |
12 | 12 | # It's strongly recommended that you check this file into your version control system. |
13 | 13 | |
14 | -ActiveRecord::Schema.define(version: 20160422163123) do | |
14 | +ActiveRecord::Schema.define(version: 20160608123748) do | |
15 | 15 | |
16 | 16 | # These are extensions that must be enabled in order to support this database |
17 | 17 | enable_extension "plpgsql" |
... | ... | @@ -274,6 +274,14 @@ ActiveRecord::Schema.define(version: 20160422163123) do |
274 | 274 | add_index "chat_messages", ["from_id"], name: "index_chat_messages_on_from_id", using: :btree |
275 | 275 | add_index "chat_messages", ["to_id"], name: "index_chat_messages_on_to_id", using: :btree |
276 | 276 | |
277 | + create_table "circles", force: :cascade do |t| | |
278 | + t.string "name" | |
279 | + t.integer "person_id" | |
280 | + t.string "profile_type", null: false | |
281 | + end | |
282 | + | |
283 | + add_index "circles", ["person_id", "name"], name: "circles_composite_key_index", unique: true, using: :btree | |
284 | + | |
277 | 285 | create_table "comments", force: :cascade do |t| |
278 | 286 | t.string "title" |
279 | 287 | t.text "body" |
... | ... | @@ -639,6 +647,15 @@ ActiveRecord::Schema.define(version: 20160422163123) do |
639 | 647 | add_index "profiles", ["user_id", "type"], name: "index_profiles_on_user_id_and_type", using: :btree |
640 | 648 | add_index "profiles", ["user_id"], name: "index_profiles_on_user_id", using: :btree |
641 | 649 | |
650 | + create_table "profiles_circles", force: :cascade do |t| | |
651 | + t.integer "profile_id" | |
652 | + t.integer "circle_id" | |
653 | + t.datetime "created_at" | |
654 | + t.datetime "updated_at" | |
655 | + end | |
656 | + | |
657 | + add_index "profiles_circles", ["profile_id", "circle_id"], name: "profiles_circles_composite_key_index", unique: true, using: :btree | |
658 | + | |
642 | 659 | create_table "qualifier_certifiers", force: :cascade do |t| |
643 | 660 | t.integer "qualifier_id" |
644 | 661 | t.integer "certifier_id" |
... | ... | @@ -860,4 +877,5 @@ ActiveRecord::Schema.define(version: 20160422163123) do |
860 | 877 | add_index "votes", ["voteable_id", "voteable_type"], name: "fk_voteables", using: :btree |
861 | 878 | add_index "votes", ["voter_id", "voter_type"], name: "fk_voters", using: :btree |
862 | 879 | |
880 | + add_foreign_key "profiles_circles", "circles", on_delete: :nullify | |
863 | 881 | end | ... | ... |
... | ... | @@ -0,0 +1,114 @@ |
1 | +Feature: follow profile | |
2 | + As a noosfero user | |
3 | + I want to follow a profile | |
4 | + So I can receive notifications from it | |
5 | + | |
6 | + Background: | |
7 | + Given the following community | |
8 | + | identifier | name | | |
9 | + | nightswatch | Nights Watch | | |
10 | + And the following users | |
11 | + | login | | |
12 | + | johnsnow | | |
13 | + And the user "johnsnow" has the following circles | |
14 | + | name | profile_type | | |
15 | + | Family | Person | | |
16 | + | Work | Community | | |
17 | + | Favorites | Community | | |
18 | + | |
19 | + @selenium | |
20 | + Scenario: Common noofero user follow a community | |
21 | + Given I am logged in as "johnsnow" | |
22 | + When I go to nightswatch's homepage | |
23 | + When I follow "Follow" | |
24 | + When I check "Work" | |
25 | + When I press "Follow" | |
26 | + And I wait 1 second | |
27 | + Then "johnsnow" should be a follower of "nightswatch" in circle "Work" | |
28 | + | |
29 | + @selenium | |
30 | + Scenario: Common noofero user follow a community in more than one circle | |
31 | + Given I am logged in as "johnsnow" | |
32 | + When I go to nightswatch's homepage | |
33 | + When I follow "Follow" | |
34 | + When I check "Work" | |
35 | + When I check "Favorites" | |
36 | + When I press "Follow" | |
37 | + And I wait 1 second | |
38 | + Then "johnsnow" should be a follower of "nightswatch" in circle "Work" | |
39 | + And "johnsnow" should be a follower of "nightswatch" in circle "Favorites" | |
40 | + | |
41 | + @selenium | |
42 | + Scenario: No see another profile type circle when following a community | |
43 | + Given I am logged in as "johnsnow" | |
44 | + When I go to nightswatch's homepage | |
45 | + When I follow "Follow" | |
46 | + Then I should not see "Family" | |
47 | + And I should see "Favorites" | |
48 | + And I should see "Work" | |
49 | + | |
50 | + @selenium | |
51 | + Scenario: Common noofero user follow a community then cancel the action | |
52 | + Given I am logged in as "johnsnow" | |
53 | + When I go to nightswatch's homepage | |
54 | + When I follow "Follow" | |
55 | + When I press "Cancel" | |
56 | + And I wait 1 second | |
57 | + Then I should not see "Family" | |
58 | + And I should not see "Favorites" | |
59 | + And I should not see "Work" | |
60 | + And I should not see "New Circle" | |
61 | + Then "johnsnow" should not be a follower of "nightswatch" | |
62 | + | |
63 | + @selenium | |
64 | + Scenario: Common noofero user cancel the circle creation action | |
65 | + Given I am logged in as "johnsnow" | |
66 | + When I go to nightswatch's homepage | |
67 | + When I follow "Follow" | |
68 | + When I follow "New Circle" | |
69 | + When I press "Cancel" | |
70 | + And I wait 1 second | |
71 | + Then I should not see "Circle name" | |
72 | + And I should not see "Create" | |
73 | + | |
74 | + @selenium | |
75 | + Scenario: Noosfero user see new circle option when following a community | |
76 | + Given I am logged in as "johnsnow" | |
77 | + When I go to nightswatch's homepage | |
78 | + When I follow "Follow" | |
79 | + Then I should see "New Circle" | |
80 | + | |
81 | + @selenium | |
82 | + Scenario: Common noofero user follow a community with a new circle | |
83 | + Given I am logged in as "johnsnow" | |
84 | + When I go to nightswatch's homepage | |
85 | + When I follow "Follow" | |
86 | + When I follow "New Circle" | |
87 | + And I fill in "text-field-name-new-circle" with "Winterfell" | |
88 | + When I follow "Create" | |
89 | + When I check "Winterfell" | |
90 | + When I press "Follow" | |
91 | + And I wait 1 second | |
92 | + Then "johnsnow" should be a follower of "nightswatch" in circle "Winterfell" | |
93 | + | |
94 | + @selenium | |
95 | + Scenario: Common noofero user create a new circle when following a community | |
96 | + Given I am logged in as "johnsnow" | |
97 | + When I go to nightswatch's homepage | |
98 | + When I follow "Follow" | |
99 | + When I follow "New Circle" | |
100 | + And I fill in "text-field-name-new-circle" with "Winterfell" | |
101 | + When I follow "Create" | |
102 | + And I wait 1 second | |
103 | + Then "johnsnow" should have the circle "Winterfell" with profile type "Community" | |
104 | + Then I should not see "Circle name" | |
105 | + Then I should not see "Create" | |
106 | + | |
107 | + @selenium | |
108 | + Scenario: Common noofero user unfollow a community | |
109 | + Given "johnsnow" is a follower of "nightswatch" in circle "Work" | |
110 | + And I am logged in as "johnsnow" | |
111 | + When I go to nightswatch's homepage | |
112 | + When I follow "Unfollow" | |
113 | + Then "johnsnow" should not be a follower of "nightswatch" | |
114 | + | ... | ... |
... | ... | @@ -0,0 +1,35 @@ |
1 | +Given /^the user "(.+)" has the following circles$/ do |user_name,table| | |
2 | + person = User.find_by(:login => user_name).person | |
3 | + table.hashes.each do |circle| | |
4 | + Circle.create!(:person => person, :name => circle[:name], :profile_type => circle[:profile_type]) | |
5 | + end | |
6 | +end | |
7 | + | |
8 | +Then /^"(.+)" should be a follower of "(.+)" in circle "(.+)"$/ do |person, profile, circle| | |
9 | + profile = Profile.find_by(identifier: profile) | |
10 | + followers = profile.followers | |
11 | + person = Person.find_by(identifier: person) | |
12 | + followers.should include(person) | |
13 | + | |
14 | + circle = Circle.find_by(:name => circle, :person => person) | |
15 | + ProfileFollower.find_by(:circle => circle, :profile => profile).should_not == nil | |
16 | +end | |
17 | + | |
18 | +Then /^"(.+)" should not be a follower of "(.+)"$/ do |person, profile| | |
19 | + profile = Profile.find_by(identifier: profile) | |
20 | + followers = profile.followers | |
21 | + person = Person.find_by(identifier: person) | |
22 | + followers.should_not include(person) | |
23 | +end | |
24 | + | |
25 | +Given /^"(.+)" is a follower of "(.+)" in circle "(.+)"$/ do |person, profile, circle| | |
26 | + profile = Profile.find_by(identifier: profile) | |
27 | + person = Person.find_by(identifier: person) | |
28 | + circle = Circle.find_by(:name => circle, :person => person) | |
29 | + ProfileFollower.create!(:circle => circle, :profile => profile) | |
30 | +end | |
31 | + | |
32 | +Then /^"(.+)" should have the circle "(.+)" with profile type "(.+)"$/ do |user_name, circle, profile_type| | |
33 | + person = User.find_by(:login => user_name).person | |
34 | + Circle.find_by(:name => circle, :person => person, :profile_type => profile_type).should_not == nil | |
35 | +end | ... | ... |
plugins/admin_notifications/test/functional/account_controller_test.rb
... | ... | @@ -8,8 +8,7 @@ end |
8 | 8 | class AccountControllerTest < ActionController::TestCase |
9 | 9 | def setup |
10 | 10 | @controller = AccountController.new |
11 | - @request = ActionController::TestRequest.new | |
12 | - @response = ActionController::TestResponse.new | |
11 | + | |
13 | 12 | @person = create_user('person').person |
14 | 13 | |
15 | 14 | @environment = Environment.default | ... | ... |
plugins/admin_notifications/test/functional/admin_notifications_plugin_admin_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ require_relative '../../controllers/admin_notifications_plugin_admin_controller' |
4 | 4 | class AdminNotificationsPluginAdminControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | @controller = AdminNotificationsPluginAdminController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | @person = create_user('person').person |
10 | 8 | |
11 | 9 | @environment = Environment.default | ... | ... |
plugins/admin_notifications/test/functional/admin_notifications_plugin_myprofile_controller_test.rb
... | ... | @@ -7,8 +7,6 @@ require( |
7 | 7 | class AdminNotificationsPluginMyprofileControllerTest < ActionController::TestCase |
8 | 8 | def setup |
9 | 9 | @controller = AdminNotificationsPluginMyprofileController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
12 | 10 | @person = create_user('person').person |
13 | 11 | @community = fast_create(Community) |
14 | 12 | ... | ... |
plugins/admin_notifications/test/functional/admin_notifications_plugin_public_controller_test.rb
... | ... | @@ -7,8 +7,6 @@ require( |
7 | 7 | class AdminNotificationsPluginPublicControllerTest < ActionController::TestCase |
8 | 8 | def setup |
9 | 9 | @controller = AdminNotificationsPluginPublicController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
12 | 10 | @person = create_user('person').person |
13 | 11 | |
14 | 12 | @environment = Environment.default | ... | ... |
plugins/admin_notifications/test/functional/home_controller_test.rb
... | ... | @@ -7,8 +7,7 @@ end |
7 | 7 | class HomeControllerTest < ActionController::TestCase |
8 | 8 | def setup |
9 | 9 | @controller = HomeController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
10 | + | |
12 | 11 | @person = create_user('person').person |
13 | 12 | |
14 | 13 | @environment = Environment.default | ... | ... |
plugins/analytics/controllers/myprofile/analytics_plugin/stats_controller.rb
... | ... | @@ -7,12 +7,39 @@ class AnalyticsPlugin::StatsController < 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 < 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 < 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 < 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 < 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 < 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: &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: &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
... | ... | @@ -8,24 +8,37 @@ class AnalyticsPlugin::PageView < ApplicationRecord |
8 | 8 | attr_accessor :request |
9 | 9 | attr_accessible :request |
10 | 10 | |
11 | + extend ActsAsHavingSettings::ClassMethods | |
11 | 12 | acts_as_having_settings field: :options |
12 | 13 | |
13 | - belongs_to :visit, class_name: 'AnalyticsPlugin::Visit' | |
14 | - belongs_to :referer_page_view, class_name: 'AnalyticsPlugin::PageView' | |
14 | + belongs_to :profile, validate: true | |
15 | + belongs_to :visit, class_name: 'AnalyticsPlugin::Visit', touch: true, validate: true | |
15 | 16 | |
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 | |
17 | + belongs_to :referer_page_view, class_name: 'AnalyticsPlugin::PageView', validate: false | |
19 | 18 | |
20 | - validates_presence_of :visit | |
21 | - validates_presence_of :request, on: :create | |
22 | - validates_presence_of :url | |
19 | + belongs_to :user, class_name: 'Person', validate: false | |
20 | + belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: 'Session', validate: false | |
21 | + | |
22 | + validates :request, presence: true, on: :create | |
23 | + validates :url, presence: true | |
23 | 24 | |
24 | 25 | before_validation :extract_request_data, on: :create |
25 | 26 | before_validation :fill_referer_page_view, on: :create |
26 | 27 | before_validation :fill_visit, on: :create |
28 | + before_validation :fill_is_bot, on: :create | |
29 | + | |
30 | + after_update :destroy_empty_visit | |
31 | + after_destroy :destroy_empty_visit | |
32 | + | |
33 | + scope :in_sequence, -> { order 'analytics_plugin_page_views.request_started_at ASC' } | |
34 | + | |
35 | + scope :page_loaded, -> { where 'analytics_plugin_page_views.page_loaded_at IS NOT NULL' } | |
36 | + scope :not_page_loaded, -> { where 'analytics_plugin_page_views.page_loaded_at IS NULL' } | |
27 | 37 | |
28 | - scope :latest, -> { order 'request_started_at DESC' } | |
38 | + scope :no_bots, -> { where.not is_bot: true } | |
39 | + scope :bots, -> { where is_bot: true } | |
40 | + | |
41 | + scope :loaded_users, -> { in_sequence.page_loaded.no_bots } | |
29 | 42 | |
30 | 43 | def request_duration |
31 | 44 | self.request_finished_at - self.request_started_at |
... | ... | @@ -43,8 +56,8 @@ class AnalyticsPlugin::PageView < ApplicationRecord |
43 | 56 | Time.now < self.user_last_time_seen + AnalyticsPlugin::TimeOnPageUpdateInterval |
44 | 57 | end |
45 | 58 | |
46 | - def page_load! | |
47 | - self.page_loaded_at = Time.now | |
59 | + def page_load! time | |
60 | + self.page_loaded_at = time | |
48 | 61 | self.update_column :page_loaded_at, self.page_loaded_at |
49 | 62 | end |
50 | 63 | |
... | ... | @@ -56,6 +69,16 @@ class AnalyticsPlugin::PageView < ApplicationRecord |
56 | 69 | self.update_column :time_on_page, self.time_on_page |
57 | 70 | end |
58 | 71 | |
72 | + def find_referer_page_view | |
73 | + return if self.referer_url.blank? | |
74 | + AnalyticsPlugin::PageView.order('request_started_at DESC'). | |
75 | + where(url: self.referer_url, session_id: self.session_id, user_id: self.user_id, profile_id: self.profile_id).first | |
76 | + end | |
77 | + | |
78 | + def browser | |
79 | + @browser ||= Browser.new self.user_agent | |
80 | + end | |
81 | + | |
59 | 82 | protected |
60 | 83 | |
61 | 84 | def extract_request_data |
... | ... | @@ -64,16 +87,29 @@ class AnalyticsPlugin::PageView < ApplicationRecord |
64 | 87 | self.user_agent = self.request.headers['User-Agent'] |
65 | 88 | self.request_id = self.request.env['action_dispatch.request_id'] |
66 | 89 | self.remote_ip = self.request.remote_ip |
90 | + true | |
67 | 91 | end |
68 | 92 | |
69 | 93 | 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? | |
94 | + self.referer_page_view = self.find_referer_page_view | |
95 | + true | |
72 | 96 | end |
73 | 97 | |
74 | 98 | def fill_visit |
75 | 99 | self.visit = self.referer_page_view.visit if self.referer_page_view and self.referer_page_view.user_on_page? |
76 | 100 | self.visit ||= AnalyticsPlugin::Visit.new profile: profile |
101 | + true | |
102 | + end | |
103 | + | |
104 | + def fill_is_bot | |
105 | + self.is_bot = self.browser.bot? | |
106 | + true | |
107 | + end | |
108 | + | |
109 | + def destroy_empty_visit | |
110 | + return unless self.visit_id_changed? | |
111 | + old_visit = AnalyticsPlugin::Visit.find self.visit_id_was | |
112 | + old_visit.destroy if old_visit.page_views.empty? | |
77 | 113 | end |
78 | 114 | |
79 | 115 | end | ... | ... |
plugins/analytics/models/analytics_plugin/visit.rb
... | ... | @@ -5,10 +5,16 @@ class AnalyticsPlugin::Visit < 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
... | ... | @@ -5,8 +5,6 @@ class ContentViewerControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = ContentViewerController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @environment = Environment.default |
12 | 10 | @environment.enabled_plugins += ['AnalyticsPlugin'] |
... | ... | @@ -37,7 +35,7 @@ class ContentViewerControllerTest < ActionController::TestCase |
37 | 35 | @request.env['HTTP_REFERER'] = first_url |
38 | 36 | get :view_page, profile: @community.identifier, page: @community.articles.last.path.split('/') |
39 | 37 | assert_equal 2, @community.page_views.count |
40 | - assert_equal 2, @community.visits.count | |
38 | + assert_equal 1, @community.visits.count | |
41 | 39 | |
42 | 40 | second_page_view = @community.page_views.order(:id).last |
43 | 41 | assert_equal first_page_view, second_page_view.referer_page_view |
... | ... | @@ -48,7 +46,7 @@ class ContentViewerControllerTest < ActionController::TestCase |
48 | 46 | future = Time.now + 2*AnalyticsPlugin::TimeOnPageUpdateInterval |
49 | 47 | Time.stubs(:now).returns(future) |
50 | 48 | get :view_page, profile: @community.identifier, page: @community.articles.last.path.split('/') |
51 | - assert_equal 3, @community.visits.count | |
49 | + assert_equal 2, @community.visits.count | |
52 | 50 | end |
53 | 51 | |
54 | 52 | 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 | - |  | |
17 | - = _'ago' | |
18 | - td | |
19 | - - visit.page_views.each do |page_view| | |
20 | - = link_to page_view.url, page_view.url | |
21 | - | | |
22 | - = "(#{distance_of_time_in_words page_view.time_on_page})" | |
23 | - | -> | |
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 | + |  | |
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 | + | | |
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/comment_group/test/functional/comment_group_plugin_profile_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class CommentGroupPluginProfileControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = CommentGroupPluginProfileController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @profile = create_user('testuser').person |
12 | 10 | @article = profile.articles.build(:name => 'test') | ... | ... |
plugins/comment_group/test/functional/comment_group_plugin_public_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class CommentGroupPluginPublicControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = CommentGroupPluginPublicController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @profile = create_user('testuser').person |
12 | 10 | @article = profile.articles.build(:name => 'test') | ... | ... |
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/test/functional/custom_forms_plugin_myprofile_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ require_relative '../../controllers/custom_forms_plugin_myprofile_controller' |
4 | 4 | class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | @controller = CustomFormsPluginMyprofileController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | @profile = create_user('profile').person |
10 | 9 | login_as(@profile.identifier) |
11 | 10 | environment = Environment.default | ... | ... |
plugins/custom_forms/test/functional/custom_forms_plugin_profile_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ require_relative '../../controllers/custom_forms_plugin_profile_controller' |
4 | 4 | class CustomFormsPluginProfileControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | @controller = CustomFormsPluginProfileController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | @profile = create_user('profile').person |
10 | 9 | login_as(@profile.identifier) |
11 | 10 | environment = Environment.default | ... | ... |
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
plugins/custom_forms/views/shared/_form_submission.html.erb
plugins/display_content/test/functional/display_content_plugin_admin_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class DisplayContentPluginAdminControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = DisplayContentPluginAdminController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @environment = Environment.default |
12 | 10 | user_login = create_admin_user(@environment) | ... | ... |
plugins/display_content/test/functional/display_content_plugin_myprofile_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class DisplayContentPluginMyprofileControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = DisplayContentPluginMyprofileController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | user = create_user('testinguser') |
12 | 10 | login_as(user.login) | ... | ... |
plugins/driven_signup/test/integration/account_controller_test.rb
... | ... | @@ -7,8 +7,7 @@ class AccountControllerTest < ActionDispatch::IntegrationTest |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = AccountController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
10 | + @request = ActionController::TestRequest.new | |
12 | 11 | |
13 | 12 | e = Environment.default |
14 | 13 | e.enable 'skip_new_user_email_confirmation', true | ... | ... |
plugins/fb_app/models/fb_app_plugin/page_tab.rb
... | ... | @@ -9,6 +9,7 @@ class FbAppPlugin::PageTab < ApplicationRecord |
9 | 9 | |
10 | 10 | belongs_to :owner_profile, foreign_key: :profile_id, class_name: 'Profile' |
11 | 11 | |
12 | + extend ActsAsHavingSettings::ClassMethods | |
12 | 13 | acts_as_having_settings field: :config |
13 | 14 | |
14 | 15 | ConfigTypes = [:profile, :profiles, :query] | ... | ... |
plugins/google_analytics/test/functional/profile_editor_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class ProfileEditorControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = ProfileEditorController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | @profile = create_user('default_user').person |
11 | 10 | login_as(@profile.identifier) |
12 | 11 | Environment.default.enable_plugin(GoogleAnalyticsPlugin.name) | ... | ... |
plugins/google_cse/test/functional/google_cse_plugin_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class GoogleCsePluginControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = GoogleCsePluginController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | end |
11 | 9 | |
12 | 10 | should 'get results page' do | ... | ... |
plugins/html5_video/test/functional/content_viewer_controler_test.rb
... | ... | @@ -7,8 +7,6 @@ class ContentViewerControllerTest < ActionController::TestCase |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = ContentViewerController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
12 | 10 | |
13 | 11 | @profile = create_user('testinguser').person |
14 | 12 | @environment = @profile.environment | ... | ... |
plugins/ldap/test/functional/account_controller_plugin_test.rb
... | ... | @@ -4,8 +4,6 @@ class AccountControllerPluginTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = AccountController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | |
10 | 8 | @environment = Environment.default |
11 | 9 | @environment.enabled_plugins = ['LdapPlugin'] | ... | ... |
plugins/mark_comment_as_read/test/functional/mark_comment_as_read_plugin_profile_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ require_relative '../../controllers/mark_comment_as_read_plugin_profile_controll |
4 | 4 | class MarkCommentAsReadPluginProfileControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | @controller = MarkCommentAsReadPluginProfileController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | @profile = create_user('profile').person |
10 | 9 | @article = TinyMceArticle.create!(:profile => @profile, :name => 'An article') |
11 | 10 | @comment = Comment.new(:source => @article, :author => @profile, :body => 'test') | ... | ... |
plugins/metadata/test/functional/content_viewer_controller_test.rb
... | ... | @@ -6,8 +6,6 @@ class ContentViewerControllerTest < ActionController::TestCase |
6 | 6 | |
7 | 7 | def setup |
8 | 8 | @controller = ContentViewerController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
11 | 9 | |
12 | 10 | @profile = create_user('testinguser').person |
13 | 11 | @environment = @profile.environment | ... | ... |
plugins/metadata/test/functional/home_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class HomeControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = HomeController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @environment = Environment.default |
12 | 10 | @environment.enabled_plugins += ['MetadataPlugin'] | ... | ... |
plugins/metadata/test/functional/products_plugin/page_controller_test.rb
... | ... | @@ -6,8 +6,6 @@ if defined? ProductsPlugin |
6 | 6 | |
7 | 7 | def setup |
8 | 8 | @controller = PageController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
11 | 9 | @enterprise = fast_create(Enterprise, name: 'test', identifier: 'test_ent') |
12 | 10 | @user = create_user_with_permission('test_user', 'manage_products', @enterprise) |
13 | 11 | login_as :test_user | ... | ... |
plugins/newsletter/lib/newsletter_plugin/newsletter.rb
plugins/newsletter/test/functional/newsletter_plugin_admin_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ class NewsletterPluginAdminControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = NewsletterPluginAdminController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | |
10 | 8 | @admin = create_user('admin_newsletter').person |
11 | 9 | @environment = @admin.environment | ... | ... |
plugins/newsletter/test/functional/newsletter_plugin_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ class NewsletterPluginControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = NewsletterPluginController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | environment = fast_create(Environment) |
10 | 9 | environment.enable_plugin(NewsletterPlugin) |
11 | 10 | @controller.stubs(:environment).returns(environment) | ... | ... |
plugins/oauth_client/models/oauth_client_plugin/auth.rb
... | ... | @@ -10,6 +10,7 @@ class OauthClientPlugin::Auth < ApplicationRecord |
10 | 10 | validates_presence_of :provider |
11 | 11 | validates_uniqueness_of :profile_id, scope: :provider_id |
12 | 12 | |
13 | + extend ActsAsHavingSettings::ClassMethods | |
13 | 14 | acts_as_having_settings field: :data |
14 | 15 | |
15 | 16 | def expires_in | ... | ... |
plugins/oauth_client/models/oauth_client_plugin/provider.rb
... | ... | @@ -4,7 +4,10 @@ class OauthClientPlugin::Provider < ApplicationRecord |
4 | 4 | |
5 | 5 | validates_presence_of :name, :strategy |
6 | 6 | |
7 | + extend ActsAsHavingImage::ClassMethods | |
7 | 8 | acts_as_having_image |
9 | + | |
10 | + extend ActsAsHavingSettings::ClassMethods | |
8 | 11 | acts_as_having_settings field: :options |
9 | 12 | |
10 | 13 | settings_items :site, type: String |
... | ... | @@ -16,6 +19,4 @@ class OauthClientPlugin::Provider < ApplicationRecord |
16 | 19 | |
17 | 20 | scope :enabled, -> { where enabled: true } |
18 | 21 | |
19 | - acts_as_having_image | |
20 | - | |
21 | 22 | end | ... | ... |
plugins/oauth_provider/Gemfile
plugins/oauth_provider/controllers/doorkeeper/application_controller.rb
plugins/oauth_provider/controllers/doorkeeper/applications_controller.rb
0 → 100644
... | ... | @@ -0,0 +1,54 @@ |
1 | +module Doorkeeper | |
2 | + class ApplicationsController < Doorkeeper::ApplicationController | |
3 | + layout 'doorkeeper/admin' | |
4 | + | |
5 | + before_action :authenticate_admin! | |
6 | + before_action :set_application, only: [:show, :edit, :update, :destroy] | |
7 | + | |
8 | + def index | |
9 | + @applications = Application.all | |
10 | + end | |
11 | + | |
12 | + def new | |
13 | + @application = Application.new | |
14 | + end | |
15 | + | |
16 | + def create | |
17 | + @application = Application.new(application_params) | |
18 | + if @application.save | |
19 | + flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) | |
20 | + redirect_to oauth_application_url(@application) | |
21 | + else | |
22 | + render :new | |
23 | + end | |
24 | + end | |
25 | + | |
26 | + def update | |
27 | + if @application.update_attributes(application_params) | |
28 | + flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :update]) | |
29 | + redirect_to oauth_application_url(@application) | |
30 | + else | |
31 | + render :edit | |
32 | + end | |
33 | + end | |
34 | + | |
35 | + def destroy | |
36 | + flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :destroy]) if @application.destroy | |
37 | + redirect_to oauth_applications_url | |
38 | + end | |
39 | + | |
40 | + private | |
41 | + | |
42 | + def set_application | |
43 | + @application = Application.find(params[:id]) | |
44 | + end | |
45 | + | |
46 | + def application_params | |
47 | + if params.respond_to?(:permit) | |
48 | + params.require(:doorkeeper_application).permit(:name, :redirect_uri, :scopes) | |
49 | + else | |
50 | + params[:doorkeeper_application].slice(:name, :redirect_uri, :scopes) rescue nil | |
51 | + end | |
52 | + end | |
53 | + end | |
54 | +end | ... | ... |
plugins/oauth_provider/controllers/oauth_provider_authorizations_controller.rb
plugins/oauth_provider/db/migrate/20140829153047_create_doorkeeper_tables.rb
... | ... | @@ -1,41 +0,0 @@ |
1 | -class CreateDoorkeeperTables < ActiveRecord::Migration | |
2 | - def change | |
3 | - create_table :oauth_applications do |t| | |
4 | - t.string :name, null: false | |
5 | - t.string :uid, null: false | |
6 | - t.string :secret, null: false | |
7 | - t.text :redirect_uri, null: false | |
8 | - t.timestamps | |
9 | - end | |
10 | - | |
11 | - add_index :oauth_applications, :uid, unique: true | |
12 | - | |
13 | - create_table :oauth_access_grants do |t| | |
14 | - t.integer :resource_owner_id, null: false | |
15 | - t.integer :application_id, null: false | |
16 | - t.string :token, null: false | |
17 | - t.integer :expires_in, null: false | |
18 | - t.text :redirect_uri, null: false | |
19 | - t.datetime :created_at, null: false | |
20 | - t.datetime :revoked_at | |
21 | - t.string :scopes | |
22 | - end | |
23 | - | |
24 | - add_index :oauth_access_grants, :token, unique: true | |
25 | - | |
26 | - create_table :oauth_access_tokens do |t| | |
27 | - t.integer :resource_owner_id | |
28 | - t.integer :application_id | |
29 | - t.string :token, null: false | |
30 | - t.string :refresh_token | |
31 | - t.integer :expires_in | |
32 | - t.datetime :revoked_at | |
33 | - t.datetime :created_at, null: false | |
34 | - t.string :scopes | |
35 | - end | |
36 | - | |
37 | - add_index :oauth_access_tokens, :token, unique: true | |
38 | - add_index :oauth_access_tokens, :resource_owner_id | |
39 | - add_index :oauth_access_tokens, :refresh_token, unique: true | |
40 | - end | |
41 | -end |
plugins/oauth_provider/db/migrate/20170718153047_create_doorkeeper_tables.rb
0 → 100644
... | ... | @@ -0,0 +1,42 @@ |
1 | +class CreateDoorkeeperTables < ActiveRecord::Migration | |
2 | + def change | |
3 | + create_table :oauth_applications do |t| | |
4 | + t.string :name, null: false | |
5 | + t.string :uid, null: false | |
6 | + t.string :secret, null: false | |
7 | + t.text :redirect_uri, null: false | |
8 | + t.string :scopes, null: false, default: '' | |
9 | + t.timestamps | |
10 | + end | |
11 | + | |
12 | + add_index :oauth_applications, :uid, unique: true | |
13 | + | |
14 | + create_table :oauth_access_grants do |t| | |
15 | + t.integer :resource_owner_id, null: false | |
16 | + t.integer :application_id, null: false | |
17 | + t.string :token, null: false | |
18 | + t.integer :expires_in, null: false | |
19 | + t.text :redirect_uri, null: false | |
20 | + t.datetime :created_at, null: false | |
21 | + t.datetime :revoked_at | |
22 | + t.string :scopes | |
23 | + end | |
24 | + | |
25 | + add_index :oauth_access_grants, :token, unique: true | |
26 | + | |
27 | + create_table :oauth_access_tokens do |t| | |
28 | + t.integer :resource_owner_id | |
29 | + t.integer :application_id | |
30 | + t.string :token, null: false | |
31 | + t.string :refresh_token | |
32 | + t.integer :expires_in | |
33 | + t.datetime :revoked_at | |
34 | + t.datetime :created_at, null: false | |
35 | + t.string :scopes | |
36 | + end | |
37 | + | |
38 | + add_index :oauth_access_tokens, :token, unique: true | |
39 | + add_index :oauth_access_tokens, :resource_owner_id | |
40 | + add_index :oauth_access_tokens, :refresh_token, unique: true | |
41 | + end | |
42 | +end | ... | ... |
plugins/oauth_provider/views/doorkeeper/applications/_delete_form.html.erb
1 | 1 | <%- submit_btn_css ||= 'btn btn-link' %> |
2 | -<%= form_tag [:oauth, application] do %> | |
2 | +<%= form_tag oauth_application_path(application) do %> | |
3 | 3 | <input type="hidden" name="_method" value="delete"> |
4 | - <%= submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css %> | |
4 | + <%= submit_tag t('doorkeeper.applications.buttons.destroy'), onclick: "return confirm('#{ t('doorkeeper.applications.confirmations.destroy') }')", class: submit_btn_css %> | |
5 | 5 | <% end %> | ... | ... |
plugins/oauth_provider/views/doorkeeper/applications/_form.html.erb
1 | -<%= form_for [:oauth, application], html: {class: 'form-horizontal', role: 'form'} do |f| %> | |
1 | +<%= form_for application, url: doorkeeper_submit_path(application), html: {class: 'form-horizontal', role: 'form'} do |f| %> | |
2 | 2 | <% if application.errors.any? %> |
3 | 3 | <div class="alert alert-danger" data-alert> |
4 | 4 | <p><%= _('Whoops! Check your form for possible errors') %></p> | ... | ... |
plugins/oauth_provider/views/doorkeeper/applications/index.html.erb
... | ... | @@ -17,15 +17,15 @@ |
17 | 17 | <tbody> |
18 | 18 | <% @applications.each do |application| %> |
19 | 19 | <tr id="application_<%= application.id %>"> |
20 | - <td><%= link_to application.name, [:oauth, application] %></td> | |
20 | + <td><%= link_to application.name, oauth_application_path(application) %></td> | |
21 | 21 | <td><%= application.redirect_uri %></td> |
22 | - <td><%= link_to _('Edit'), edit_oauth_application_path(application), class: 'btn btn-link' %></td> | |
22 | + <td><%= link_to t('doorkeeper.applications.buttons.edit'), edit_oauth_application_path(application), class: 'btn btn-link' %></td> | |
23 | 23 | <td><%= render 'delete_form', application: application %></td> |
24 | 24 | </tr> |
25 | 25 | <% end %> |
26 | 26 | </tbody> |
27 | 27 | </table> |
28 | -<div class="actions"> | |
28 | +<div class="actions" style="padding-top: 5px;"> | |
29 | 29 | <%= button(:back, _('Go back'), {:controller => 'oauth_provider_plugin_admin', :action => 'index'}) %> |
30 | 30 | </div> |
31 | 31 | </div> | ... | ... |
plugins/oauth_provider/views/doorkeeper/applications/show.html.erb
... | ... | @@ -20,7 +20,8 @@ |
20 | 20 | <td> |
21 | 21 | <code><%= uri %></code> |
22 | 22 | </td> |
23 | - <td> | |
23 | + <td> | |
24 | + <%= link_to t('doorkeeper.applications.buttons.authorize'), oauth_authorization_path(client_id: @application.uid, redirect_uri: uri, response_type: 'code', scope: @application.scopes), class: 'btn btn-success', target: '_blank' %> | |
24 | 25 | </td> |
25 | 26 | </tr> |
26 | 27 | <% end %> | ... | ... |
plugins/oauth_provider/views/doorkeeper/authorizations/new.html.erb
... | ... | @@ -6,16 +6,16 @@ |
6 | 6 | |
7 | 7 | <main role="main"> |
8 | 8 | <p class="h4"> |
9 | - <%= _('Authorize %s to use your account?') % "<strong class=\"text-info\">#{@pre_auth.client.name}</strong>" %> | |
9 | + <%= raw _('Authorize %s to use your account?') % "<strong class=\"text-info\">#{@pre_auth.client.name}</strong>" %> | |
10 | 10 | </p> |
11 | 11 | |
12 | - <% if @pre_auth.scopes %> | |
12 | + <% if @pre_auth.scopes.count > 0 %> | |
13 | 13 | <div id="oauth-permissions"> |
14 | 14 | <p><%= _('This application will be able to:') %></p> |
15 | 15 | |
16 | 16 | <ul class="text-info"> |
17 | 17 | <% @pre_auth.scopes.each do |scope| %> |
18 | - <li><%= OauthProviderPlugin::SCOPE_TRANSLATION[scope] %></li> | |
18 | + <li><%= t scope, scope: [:doorkeeper, :scopes] %></li> | |
19 | 19 | <% end %> |
20 | 20 | </ul> |
21 | 21 | </div> | ... | ... |
plugins/oauth_provider/views/doorkeeper/authorized_applications/index.html.erb
plugins/open_graph/test/functional/open_graph_graph/my_profile_controller_test.rb
... | ... | @@ -8,8 +8,7 @@ class OpenGraphPlugin::MyprofileControllerTest < ActionController::TestCase |
8 | 8 | |
9 | 9 | def setup |
10 | 10 | @controller = OpenGraphPlugin::MyprofileController.new |
11 | - @request = ActionController::TestRequest.new | |
12 | - @response = ActionController::TestResponse.new | |
11 | + | |
13 | 12 | @actor = create_user.person |
14 | 13 | end |
15 | 14 | ... | ... |
plugins/organization_ratings/lib/create_organization_rating_comment.rb
... | ... | @@ -14,6 +14,12 @@ class CreateOrganizationRatingComment < Task |
14 | 14 | settings_items field.to_sym |
15 | 15 | end |
16 | 16 | |
17 | + scope :with_rating, -> (user_rating){ | |
18 | + CreateOrganizationRatingComment.find_each do |task| | |
19 | + return task if(task.organization_rating_id == user_rating.id) | |
20 | + end | |
21 | + } | |
22 | + | |
17 | 23 | def perform |
18 | 24 | if (self.body && !self.body.blank?) |
19 | 25 | comment = Comment.create!(:source => self.target, :body => self.body, :author => self.requestor) | ... | ... |
plugins/organization_ratings/test/functional/organization_ratings_plugin_admin_controller_test.rb
... | ... | @@ -8,8 +8,6 @@ class OrganizationRatingsPluginAdminControllerTest < ActionController::TestCase |
8 | 8 | |
9 | 9 | def setup |
10 | 10 | @controller = OrganizationRatingsPluginAdminController.new |
11 | - @request = ActionController::TestRequest.new | |
12 | - @response = ActionController::TestResponse.new | |
13 | 11 | |
14 | 12 | @environment = Environment.default |
15 | 13 | @environment.enabled_plugins = ['OrganizationRatingsPlugin'] | ... | ... |
plugins/organization_ratings/test/functional/organization_ratings_plugin_profile_controller_test.rb
... | ... | @@ -8,8 +8,6 @@ class OrganizationRatingsPluginProfileControllerTest < ActionController::TestCas |
8 | 8 | |
9 | 9 | def setup |
10 | 10 | @controller = OrganizationRatingsPluginProfileController.new |
11 | - @request = ActionController::TestRequest.new | |
12 | - @response = ActionController::TestResponse.new | |
13 | 11 | |
14 | 12 | @environment = Environment.default |
15 | 13 | @environment.enabled_plugins = ['OrganizationRatingsPlugin'] |
... | ... | @@ -148,6 +146,39 @@ class OrganizationRatingsPluginProfileControllerTest < ActionController::TestCas |
148 | 146 | |
149 | 147 | get :new_rating, profile: @community.identifier |
150 | 148 | assert_tag :tag => 'p', :content => /Report waiting for approval/, :attributes => {:class =>/moderation-msg/} |
149 | + assert_tag :tag => 'p', :attributes => {:class =>/comment-body/} | |
150 | + end | |
151 | + | |
152 | + test "display rejected comment to env admin" do | |
153 | + post :new_rating, profile: @community.identifier, :comments => {:body => "rejected comment"}, :organization_rating_value => 3 | |
154 | + | |
155 | + @admin = create_admin_user(@environment) | |
156 | + login_as @admin | |
157 | + @controller.stubs(:current_user).returns(Profile[@admin].user) | |
158 | + | |
159 | + CreateOrganizationRatingComment.last.cancel | |
160 | + | |
161 | + get :new_rating, profile: @community.identifier | |
162 | + assert_tag :tag => 'p', :attributes => {:class =>/comment-body/}, :content => /rejected comment/ | |
163 | + end | |
164 | + | |
165 | + test "not display rejected comment to regular user" do | |
166 | + p1 = create_user('regularUser').person | |
167 | + @community.add_member p1 | |
168 | + login_as(p1.identifier) | |
169 | + @controller.stubs(:logged_in?).returns(true) | |
170 | + @controller.stubs(:current_user).returns(p1.user) | |
171 | + | |
172 | + post :new_rating, profile: @community.identifier, :comments => {:body => "rejected comment"}, :organization_rating_value => 3 | |
173 | + CreateOrganizationRatingComment.last.cancel | |
174 | + get :new_rating, profile: @community.identifier | |
175 | + assert_no_tag :tag => 'p', :attributes => {:class =>/comment-body/} | |
176 | + end | |
177 | + | |
178 | + test "not display rejected comment to community admin" do | |
179 | + post :new_rating, profile: @community.identifier, :comments => {:body => "rejected comment"}, :organization_rating_value => 3 | |
180 | + CreateOrganizationRatingComment.last.cancel | |
181 | + get :new_rating, profile: @community.identifier | |
151 | 182 | assert_no_tag :tag => 'p', :attributes => {:class =>/comment-body/} |
152 | 183 | end |
153 | 184 | ... | ... |
plugins/organization_ratings/views/shared/_user_rating_container.html.erb
... | ... | @@ -29,6 +29,9 @@ |
29 | 29 | <%= status_message_for(user, user_rate) %> |
30 | 30 | <% if user_rate.comment.present? %> |
31 | 31 | <p class="comment-body"> <%= user_rate.comment.body %> </p> |
32 | + <% elsif user && user.is_admin? %> | |
33 | + <% rating_task = CreateOrganizationRatingComment.with_rating(user_rate) %> | |
34 | + <p class="comment-body"> <%= rating_task.body %> </p> | |
32 | 35 | <% end %> |
33 | 36 | </div> |
34 | 37 | <%= @plugins.dispatch(:organization_ratings_plugin_container_extra_fields, user_rate).collect { |content| instance_exec(&content) }.join("") %> | ... | ... |
plugins/people_block/test/functional/people_block_plugin_environment_design_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ class EnvironmentDesignControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = EnvironmentDesignController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([PeopleBlockPlugin.new]) |
10 | 9 | end |
11 | 10 | ... | ... |
plugins/people_block/test/functional/people_block_plugin_profile_design_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ class ProfileDesignControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = ProfileDesignController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([PeopleBlockPlugin.new]) |
10 | 9 | end |
11 | 10 | ... | ... |
plugins/people_block/test/functional/profile_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ class ProfileControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = ProfileController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([PeopleBlockPlugin.new]) |
10 | 9 | end |
11 | 10 | ... | ... |
plugins/products/models/products_plugin/product.rb
... | ... | @@ -45,6 +45,7 @@ class ProductsPlugin::Product < ApplicationRecord |
45 | 45 | has_many :qualifiers, through: :product_qualifiers |
46 | 46 | has_many :certifiers, through: :product_qualifiers |
47 | 47 | |
48 | + extend ActsAsHavingSettings::ClassMethods | |
48 | 49 | acts_as_having_settings field: :data |
49 | 50 | |
50 | 51 | track_actions :create_product, :after_create, keep_params: [:name, :url ], if: Proc.new { |a| a.is_trackable? }, custom_user: :action_tracker_user |
... | ... | @@ -129,6 +130,7 @@ class ProductsPlugin::Product < ApplicationRecord |
129 | 130 | image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size |
130 | 131 | end |
131 | 132 | |
133 | + extend ActsAsHavingImage::ClassMethods | |
132 | 134 | acts_as_having_image |
133 | 135 | |
134 | 136 | def save_image | ... | ... |
plugins/recent_activities/lib/recent_activities_plugin.rb
0 → 100644
... | ... | @@ -0,0 +1,25 @@ |
1 | +class RecentActivitiesPlugin < Noosfero::Plugin | |
2 | + def self.plugin_name | |
3 | + 'RecentActivitiesPlugin' | |
4 | + end | |
5 | + | |
6 | + def self.plugin_description | |
7 | + _('Adds a block that lists recent profile activity.') | |
8 | + end | |
9 | + | |
10 | + def self.extra_blocks | |
11 | + { | |
12 | + RecentActivitiesPlugin::ActivitiesBlock => { type: [Community, Person] } | |
13 | + } | |
14 | + end | |
15 | + | |
16 | + def self.has_admin_url? | |
17 | + false | |
18 | + end | |
19 | + | |
20 | + def stylesheet? | |
21 | + true | |
22 | + end | |
23 | +end | |
24 | + | |
25 | +ApplicationHelper.include ActionTrackerHelper | ... | ... |
plugins/recent_activities/lib/recent_activities_plugin/activities_block.rb
0 → 100644
... | ... | @@ -0,0 +1,46 @@ |
1 | +class RecentActivitiesPlugin::ActivitiesBlock < Block | |
2 | + attr_accessible :limit | |
3 | + settings_items :limit, type: :integer, default: 5 | |
4 | + | |
5 | + def view_title | |
6 | + self.default_title | |
7 | + end | |
8 | + | |
9 | + def activities | |
10 | + activities = owner.activities.where(activity_type: ActionTracker::Record.to_s) | |
11 | + list = self.limit.nil? ? activities : activities.limit(self.get_limit) | |
12 | + list.map(&:activity) | |
13 | + end | |
14 | + | |
15 | + def extra_option | |
16 | + { } | |
17 | + end | |
18 | + | |
19 | + def self.description | |
20 | + _('Display the latest activities by the owner of the context where the block is available.') | |
21 | + end | |
22 | + | |
23 | + def help | |
24 | + _('This block lists your latest activities. By default, any user that goes to your profile will be able to see all activities. Configure the "Display to users" option if you don\'t want that.') | |
25 | + end | |
26 | + | |
27 | + def default_title | |
28 | + _('Recent activities') | |
29 | + end | |
30 | + | |
31 | + def api_content | |
32 | + Api::Entities::Activity.represent(activities).as_json | |
33 | + end | |
34 | + | |
35 | + def display_api_content_by_default? | |
36 | + false | |
37 | + end | |
38 | + | |
39 | + def timeout | |
40 | + 4.hours | |
41 | + end | |
42 | + | |
43 | + def self.expire_on | |
44 | + { profile: [:article] } | |
45 | + end | |
46 | +end | ... | ... |
... | ... | @@ -0,0 +1,29 @@ |
1 | +.recent-activities-block ul { | |
2 | + padding: 0; | |
3 | +} | |
4 | + | |
5 | +.recent-activities-block li { | |
6 | + list-style: none; | |
7 | + border-bottom: 1px solid #ccc; | |
8 | +} | |
9 | + | |
10 | +.recent-activities-block time, | |
11 | +.recent-activities-block p { | |
12 | + margin: 10px 0; | |
13 | +} | |
14 | + | |
15 | +.recent-activities-block time { | |
16 | + display: block; | |
17 | + margin-bottom: 10px; | |
18 | + color: #ccc; | |
19 | +} | |
20 | + | |
21 | +.recent-activities-block img { | |
22 | + padding: 1px; | |
23 | + border: 1px solid #ccc; | |
24 | + margin: 3px 3px 0 0; | |
25 | +} | |
26 | + | |
27 | +.recent-activities-block p:first-letter { | |
28 | + text-transform: capitalize | |
29 | +} | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +require_relative '../../../test/test_helper' | ... | ... |
plugins/recent_activities/test/unit/recent_activities_block_test.rb
0 → 100644
... | ... | @@ -0,0 +1,73 @@ |
1 | +require_relative '../test_helper' | |
2 | + | |
3 | +class RecentActivitiesBlockTest < ActiveSupport::TestCase | |
4 | + should 'describe itself' do | |
5 | + assert_not_equal Block.description, RecentActivitiesPlugin::ActivitiesBlock.description | |
6 | + end | |
7 | + | |
8 | + should 'is editable' do | |
9 | + block = RecentActivitiesPlugin::ActivitiesBlock.new | |
10 | + assert block.editable? | |
11 | + end | |
12 | + | |
13 | + should 'return last activities' do | |
14 | + profile = create_user('testuser').person | |
15 | + a1 = fast_create(ActionTracker::Record, user_id: profile.id, created_at: Time.now, updated_at: Time.now) | |
16 | + a2 = fast_create(ActionTracker::Record, user_id: profile.id, created_at: Time.now, updated_at: Time.now) | |
17 | + ProfileActivity.create! profile_id: profile.id, activity: a1 | |
18 | + ProfileActivity.create! profile_id: profile.id, activity: a2 | |
19 | + | |
20 | + block = RecentActivitiesPlugin::ActivitiesBlock.new | |
21 | + block.stubs(:owner).returns(profile) | |
22 | + | |
23 | + assert_equal [a2, a1].map(&:id), block.activities.map(&:id) | |
24 | + end | |
25 | + | |
26 | + should 'return last activities with limit' do | |
27 | + profile = create_user('testuser').person | |
28 | + a1 = fast_create(ActionTracker::Record, user_id: profile.id, created_at: Time.now, updated_at: Time.now) | |
29 | + a2 = fast_create(ActionTracker::Record, user_id: profile.id, created_at: Time.now, updated_at: Time.now) | |
30 | + ProfileActivity.create! profile_id: profile.id, activity: a1 | |
31 | + ProfileActivity.create! profile_id: profile.id, activity: a2 | |
32 | + | |
33 | + block = RecentActivitiesPlugin::ActivitiesBlock.new | |
34 | + block.stubs(:owner).returns(profile) | |
35 | + block.limit = 1 | |
36 | + | |
37 | + assert_equal [a2].map(&:id), block.activities.map(&:id) | |
38 | + end | |
39 | + | |
40 | + should 'return only action tracker records as activities' do | |
41 | + profile = create_user('testuser').person | |
42 | + friend = create_user('friend').person | |
43 | + scrap = create(Scrap, defaults_for_scrap(sender: friend, receiver: profile)) | |
44 | + a1 = fast_create(ActionTracker::Record, user_id: profile.id, created_at: Time.now, updated_at: Time.now) | |
45 | + a2 = fast_create(ActionTracker::Record, user_id: profile.id, created_at: Time.now, updated_at: Time.now) | |
46 | + ProfileActivity.create! profile_id: profile.id, activity: a1 | |
47 | + ProfileActivity.create! profile_id: profile.id, activity: a2 | |
48 | + | |
49 | + block = RecentActivitiesPlugin::ActivitiesBlock.new | |
50 | + block.stubs(:owner).returns(profile) | |
51 | + | |
52 | + assert_equal [a2, a1, scrap], block.owner.activities.map(&:activity) | |
53 | + assert_equal [a2, a1], block.activities | |
54 | + end | |
55 | +end | |
56 | + | |
57 | +require 'boxes_helper' | |
58 | + | |
59 | +class RecentActivitiesBlockViewTest < ActionView::TestCase | |
60 | + include BoxesHelper | |
61 | + | |
62 | + should 'return activities in api_content' do | |
63 | + profile = create_user('testuser').person | |
64 | + | |
65 | + a = fast_create(ActionTracker::Record, user_id: profile.id, created_at: Time.now, updated_at: Time.now) | |
66 | + ProfileActivity.create! profile_id: profile.id, activity: a | |
67 | + | |
68 | + block = RecentActivitiesPlugin::ActivitiesBlock.new | |
69 | + block.stubs(:owner).returns(profile) | |
70 | + | |
71 | + assert_equal [a.id], block.api_content['activities'].map{ |a| a[:id] } | |
72 | + end | |
73 | +end | ... | ... |
plugins/recent_activities/views/blocks/activities.html.erb
0 → 100644
... | ... | @@ -0,0 +1,16 @@ |
1 | +<%= block_title(block.view_title, block.subtitle) %> | |
2 | + | |
3 | +<div class="recent-activities-block"> | |
4 | + <% unless block.activities.size == 0 %> | |
5 | + <ul> | |
6 | + <% block.activities.each do |activity| %> | |
7 | + <li> | |
8 | + <p><%= describe(activity).html_safe %></p> | |
9 | + <time datetime="<%= activity.created_at %>"><%= time_ago_in_words(activity.created_at) %></time> | |
10 | + </li> | |
11 | + <% end %> | |
12 | + </ul> | |
13 | + <% else %> | |
14 | + <div class="recent-activities-block-none"><%= c_('None') %></div> | |
15 | + <% end %> | |
16 | +</div> | ... | ... |
plugins/recent_activities/views/box_organizer/recent_activities_plugin/_activities_block.html.erb
0 → 100644
plugins/relevant_content/test/unit/article.rb
... | ... | @@ -8,8 +8,7 @@ class RelevantContentBlockTest < ActiveSupport::TestCase |
8 | 8 | |
9 | 9 | def setup |
10 | 10 | @controller = CommentController.new |
11 | - @request = ActionController::TestRequest.new | |
12 | - @response = ActionController::TestResponse.new | |
11 | + | |
13 | 12 | @profile = create_user('testinguser').person |
14 | 13 | @environment = @profile.environment |
15 | 14 | end | ... | ... |
plugins/relevant_content/test/unit/relevant_content_block_test.rb
... | ... | @@ -9,8 +9,6 @@ class RelevantContentBlockTest < ActiveSupport::TestCase |
9 | 9 | |
10 | 10 | def setup |
11 | 11 | @controller = CommentController.new |
12 | - @request = ActionController::TestRequest.new | |
13 | - @response = ActionController::TestResponse.new | |
14 | 12 | |
15 | 13 | @profile = create_user('testinguser').person |
16 | 14 | @environment = @profile.environment | ... | ... |
plugins/remote_user/test/functional/remote_user_plugin_test.rb
... | ... | @@ -2,6 +2,8 @@ require 'test_helper' |
2 | 2 | |
3 | 3 | class AccountControllerTest < ActionController::TestCase |
4 | 4 | def setup |
5 | + @controller = AccountController.new | |
6 | + | |
5 | 7 | @environment = Environment.default |
6 | 8 | @environment.enabled_plugins = ['RemoteUserPlugin'] |
7 | 9 | @environment.save |
... | ... | @@ -9,10 +11,6 @@ class AccountControllerTest < ActionController::TestCase |
9 | 11 | @another_environment = Environment.new(name: "AnotherEnvironment") |
10 | 12 | @another_environment.enabled_plugins = ['RemoteUserPlugin'] |
11 | 13 | @another_environment.save |
12 | - | |
13 | - @controller = AccountController.new | |
14 | - @request = ActionController::TestRequest.new | |
15 | - @response = ActionController::TestResponse.new | |
16 | 14 | end |
17 | 15 | |
18 | 16 | should 'not authenticate user if there is no remote user' do | ... | ... |
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/shopping_cart/db/migrate/20131226125124_move_shopping_cart_purchase_order_to_orders_plugin_order.rb
... | ... | @@ -2,6 +2,7 @@ OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item |
2 | 2 | OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order |
3 | 3 | |
4 | 4 | class ShoppingCartPlugin::PurchaseOrder < ApplicationRecord |
5 | + extend ActsAsHavingSettings::ClassMethods | |
5 | 6 | acts_as_having_settings field: :data |
6 | 7 | |
7 | 8 | module Status | ... | ... |
plugins/shopping_cart/test/functional/shopping_cart_plugin_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class ShoppingCartPluginControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = ShoppingCartPluginController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | @profile = fast_create(Enterprise) |
11 | 10 | @profile.contact_email = 'enterprise@noosfero.org';@profile.save |
12 | 11 | @product = fast_create(Product, profile_id: @profile.id) | ... | ... |
plugins/social_share_privacy/test/functional/content_viewer_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class ContentViewerControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = ContentViewerController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @profile = create_user('testinguser').person |
12 | 10 | @environment = @profile.environment | ... | ... |
plugins/solr/test/functional/search_controller_test.rb
... | ... | @@ -4,14 +4,12 @@ require_relative '../../lib/ext/facets_browse' |
4 | 4 | class SearchControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | + @controller = SearchController.new | |
8 | + | |
7 | 9 | TestSolr.enable |
8 | 10 | p1 = File.join(RAILS_ROOT, 'app', 'views') |
9 | 11 | p2 = File.join(File.dirname(__FILE__) + '/../../views') |
10 | 12 | SearchController.append_view_path([p1,p2]) |
11 | - @controller = SearchController.new | |
12 | - @request = ActionController::TestRequest.new | |
13 | - @request.stubs(:ssl?).returns(false) | |
14 | - @response = ActionController::TestResponse.new | |
15 | 13 | |
16 | 14 | @category = Category.create!(:name => 'my category', :environment => Environment.default) |
17 | 15 | ... | ... |
plugins/spaminator/lib/spaminator_plugin/mailer.rb
... | ... | @@ -2,14 +2,14 @@ class SpaminatorPlugin::Mailer < Noosfero::Plugin::MailerBase |
2 | 2 | |
3 | 3 | include Rails.application.routes.url_helpers |
4 | 4 | def inactive_person_notification(person) |
5 | + @person = person | |
6 | + @environment = person.environment | |
7 | + @url = url_for(:host => person.default_hostname, :controller => 'account', :action => 'forgot_password') | |
5 | 8 | mail( |
6 | 9 | :to => person.email, |
7 | 10 | :from => "#{person.environment.name} <#{person.environment.noreply_email}>", |
8 | 11 | :subject => _("[%s] You must reactivate your account.") % person.environment.name, |
9 | 12 | :content_type => 'text/html', |
10 | - :body => {:person => person, | |
11 | - :environment => person.environment, | |
12 | - :url => url_for(:host => person.default_hostname, :controller => 'account', :action => 'forgot_password')} | |
13 | 13 | ) |
14 | 14 | end |
15 | 15 | ... | ... |
plugins/spaminator/test/functional/spaminator_plugin_admin_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ require_relative '../../controllers/spaminator_plugin_admin_controller' |
4 | 4 | class SpaminatorPluginAdminControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | @controller = SpaminatorPluginAdminController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | @environment = Environment.default |
10 | 9 | @settings = Noosfero::Plugin::Settings.new(@environment, SpaminatorPlugin) |
11 | 10 | login_as(create_admin_user(@environment)) | ... | ... |
plugins/spaminator/views/spaminator_plugin/mailer/inactive_person_notification.html.erb
... | ... | @@ -10,7 +10,7 @@ |
10 | 10 | <%= _('Due to the recent increase in the number of spams on %s, we decided to deactivate all inactive users on the network. It just happens that you are one of them! But there is no need to worry. Your account is completely preserved and if you want to reactivate it you just need to click on the following link and recover your password (since it was changed to a huge scramble of random characters):') % @environment.name %> |
11 | 11 | </p> |
12 | 12 | <p> |
13 | - <%= @url %> | |
13 | + <a href="<%= @url %>"><%= @url %></a> | |
14 | 14 | </p> |
15 | 15 | <p> |
16 | 16 | <%= _("We are sorry that this procedure might bother you a lot, but it's necessary for the healthy of our network.") %> | ... | ... |
plugins/stoa/test/functional/account_controller_test.rb
... | ... | @@ -19,8 +19,6 @@ class AccountControllerTest < ActionController::TestCase |
19 | 19 | |
20 | 20 | def setup |
21 | 21 | @controller = AccountController.new |
22 | - @request = ActionController::TestRequest.new | |
23 | - @response = ActionController::TestResponse.new | |
24 | 22 | StoaPlugin::UspUser.create!({:codpes => 12345678, :cpf => Digest::MD5.hexdigest(SALT+'12345678'), :birth_date => '1970-01-30'}, :without_protection => true) |
25 | 23 | Environment.default.enable_plugin(StoaPlugin.name) |
26 | 24 | @user = create_user('joao-stoa', {:password => 'pass', :password_confirmation => 'pass'},:usp_id=>'87654321') | ... | ... |
plugins/stoa/test/functional/invite_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class InviteControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = InviteController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | environment = Environment.default |
11 | 10 | environment.enabled_plugins = ['StoaPlugin'] |
12 | 11 | environment.save! | ... | ... |
plugins/stoa/test/functional/profile_editor_controller_test.rb
... | ... | @@ -7,8 +7,7 @@ class StoaPluginProfileEditorControllerTest < ActionController::TestCase |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = ProfileEditorController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
10 | + | |
12 | 11 | @person = User.create(:login => 'test_user', :email => 'test_user@example.com', :password => 'test', :password_confirmation => 'test').person |
13 | 12 | login_as(@person.identifier) |
14 | 13 | Environment.default.enable_plugin(StoaPlugin.name) | ... | ... |
plugins/stoa/test/functional/stoa_plugin_controller_test.rb
... | ... | @@ -7,8 +7,6 @@ class StoaPluginControllerTest < ActionController::TestCase |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = StoaPluginController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
12 | 10 | ApplicationRecord.configurations['stoa'] = {:adapter => 'sqlite3', :database => ':memory:', :verbosity => 'quiet'} |
13 | 11 | env = Environment.default |
14 | 12 | env.enable_plugin(StoaPlugin.name) | ... | ... |
plugins/sub_organizations/test/functional/sub_organizations_plugin_myprofile_controller_test.rb
... | ... | @@ -7,8 +7,7 @@ class SubOrganizationsPluginMyprofileController; def rescue_action(e) raise e en |
7 | 7 | class SubOrganizationsPluginMyprofileControllerTest < ActionController::TestCase |
8 | 8 | def setup |
9 | 9 | @controller = SubOrganizationsPluginMyprofileController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
10 | + | |
12 | 11 | @organization = Organization.create!(:name => 'My Organization', :identifier => 'my-organization') |
13 | 12 | @person = create_user('person').person |
14 | 13 | @organization.add_admin(@person) | ... | ... |
plugins/sub_organizations/test/functional/sub_organizations_plugin_profile_controller_test.rb
... | ... | @@ -8,8 +8,7 @@ class SubOrganizationsPluginProfileControllerTest < ActionController::TestCase |
8 | 8 | |
9 | 9 | def setup |
10 | 10 | @controller = SubOrganizationsPluginProfileController.new |
11 | - @request = ActionController::TestRequest.new | |
12 | - @response = ActionController::TestResponse.new | |
11 | + | |
13 | 12 | @organization = Organization.create!(:name => 'My Organization', :identifier => 'my-organization') |
14 | 13 | @person = create_user('person').person |
15 | 14 | @organization.add_admin(@person) | ... | ... |
plugins/video/lib/video_plugin/video.rb
1 | -require 'noosfero/translatable_content' | |
2 | 1 | require 'application_helper' |
3 | 2 | require 'net/http' |
4 | 3 | |
... | ... | @@ -12,8 +11,8 @@ class VideoPlugin::Video < Article |
12 | 11 | settings_items :video_format, :type => :string |
13 | 12 | settings_items :video_id, :type => :string |
14 | 13 | settings_items :video_thumbnail_url, :type => :string, :default => '/plugins/video/images/video_generic_thumbnail.jpg' |
15 | - settings_items :video_thumbnail_width, :type=> :integer | |
16 | - settings_items :video_thumbnail_height, :type=> :integer | |
14 | + settings_items :video_thumbnail_width, :type=> :integer, :default => 239 | |
15 | + settings_items :video_thumbnail_height, :type=> :integer, :default => 210 | |
17 | 16 | settings_items :video_duration, :type=> :integer, :default => 0 |
18 | 17 | |
19 | 18 | attr_accessible :video_url |
... | ... | @@ -35,14 +34,14 @@ class VideoPlugin::Video < Article |
35 | 34 | def self.description |
36 | 35 | _('Display embedded videos.') |
37 | 36 | end |
38 | - | |
37 | + | |
39 | 38 | def is_youtube? |
40 | 39 | VideoPlugin::Video.is_youtube?(self.video_url) |
41 | 40 | end |
42 | 41 | |
43 | 42 | def is_vimeo? |
44 | 43 | VideoPlugin::Video.is_vimeo?(self.video_url) |
45 | - end | |
44 | + end | |
46 | 45 | |
47 | 46 | include ActionView::Helpers::TagHelper |
48 | 47 | def to_html(options={}) | ... | ... |
plugins/video/lib/video_plugin/video_gallery.rb
... | ... | @@ -14,7 +14,8 @@ class VideoPlugin::VideoGallery < Folder |
14 | 14 | errors.add(:parent, "A video gallery should not belong to a blog.") if parent && parent.blog? |
15 | 15 | end |
16 | 16 | |
17 | - acts_as_having_settings :field => :setting | |
17 | + extend ActsAsHavingSettings::ClassMethods | |
18 | + acts_as_having_settings field: :setting | |
18 | 19 | |
19 | 20 | xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation' |
20 | 21 | ... | ... |
plugins/video/test/functional/video_plugin_environment_design_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ class EnvironmentDesignControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = EnvironmentDesignController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | |
10 | 8 | Environment.delete_all |
11 | 9 | User.delete_all | ... | ... |
plugins/video/test/functional/video_plugin_profile_design_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ class ProfileDesignControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = ProfileDesignController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | |
10 | 8 | user = create_user('testinguser') |
11 | 9 | login_as(user.login) | ... | ... |
plugins/video/test/unit/video_test.rb
... | ... | @@ -46,6 +46,11 @@ class VideoTest < ActiveSupport::TestCase |
46 | 46 | assert_equal thumbnail_fitted_height, @video.thumbnail_fitted_height |
47 | 47 | end |
48 | 48 | |
49 | + should "have dimensions of default thumbnail" do | |
50 | + assert @video.video_thumbnail_height.present? && @video.video_thumbnail_height > 0 | |
51 | + assert @video.video_thumbnail_width.present? && @video.video_thumbnail_width > 0 | |
52 | + end | |
53 | + | |
49 | 54 | should "show a no_browser_support_message" do |
50 | 55 | assert_equal @video.no_browser_support_message, '<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>' |
51 | 56 | end | ... | ... |
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/cms_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class CmsControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = CmsController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | @person = create_user('test_user').person |
11 | 10 | login_as :test_user |
12 | 11 | e = Environment.default | ... | ... |
plugins/work_assignment/test/functional/content_viewer_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class ContentViewerControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = ContentViewerController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | @profile = create_user('testinguser').person |
11 | 10 | |
12 | 11 | @organization = fast_create(Organization) |
... | ... | @@ -35,6 +34,14 @@ class ContentViewerControllerTest < ActionController::TestCase |
35 | 34 | assert_response :success |
36 | 35 | end |
37 | 36 | |
37 | + should 'display users submissions' do | |
38 | + folder = work_assignment.find_or_create_author_folder(@person) | |
39 | + submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => folder) | |
40 | + get :view_page, :profile => @organization.identifier, :page => work_assignment.path | |
41 | + assert_response :success | |
42 | + assert_match /rails.png/, @response.body | |
43 | + end | |
44 | + | |
38 | 45 | should "display 'Upload files' when create children of image gallery" do |
39 | 46 | login_as(profile.identifier) |
40 | 47 | f = Gallery.create!(:name => 'gallery', :profile => profile) | ... | ... |
plugins/work_assignment/test/functional/work_assignment_plugin_myprofile_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class WorkAssignmentPluginMyprofileControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = WorkAssignmentPluginMyprofileController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | @person = create_user('test_user').person |
11 | 10 | login_as :test_user |
12 | 11 | e = Environment.default | ... | ... |
public/javascripts/application.js
... | ... | @@ -26,6 +26,8 @@ |
26 | 26 | *= require pagination.js |
27 | 27 | * views speficics |
28 | 28 | *= require add-and-join.js |
29 | +*= require followers.js | |
30 | +*= require manage-followers.js | |
29 | 31 | *= require report-abuse.js |
30 | 32 | *= require autogrow.js |
31 | 33 | *= require require_login.js |
... | ... | @@ -550,6 +552,11 @@ function loading_for_button(selector) { |
550 | 552 | jQuery(selector).css('cursor', 'progress'); |
551 | 553 | } |
552 | 554 | |
555 | +function hide_loading_for_button(selector) { | |
556 | + selector.css("cursor",""); | |
557 | + $(".small-loading").remove(); | |
558 | +} | |
559 | + | |
553 | 560 | function new_qualifier_row(selector, select_qualifiers, delete_button) { |
554 | 561 | index = jQuery(selector + ' tr').size() - 1; |
555 | 562 | jQuery(selector).append("<tr><td>" + select_qualifiers + "</td><td id='certifier-area-" + index + "'><select></select>" + delete_button + "</td></tr>"); | ... | ... |
... | ... | @@ -0,0 +1,81 @@ |
1 | +$("#action-follow").live("click", function() { | |
2 | + var button = $(this); | |
3 | + var url = button.attr("href"); | |
4 | + loading_for_button(button); | |
5 | + | |
6 | + $.post(url, function(data) { | |
7 | + button.fadeOut("fast", function() { | |
8 | + $("#circles-container").html(data); | |
9 | + $("#circles-container").fadeIn(); | |
10 | + }); | |
11 | + }).always(function() { | |
12 | + hide_loading_for_button(button); | |
13 | + }); | |
14 | + return false; | |
15 | +}); | |
16 | + | |
17 | +$("#cancel-set-circle").live("click", function() { | |
18 | + $("#circles-container").fadeOut("fast", function() { | |
19 | + $("#action-follow").fadeIn(); | |
20 | + }); | |
21 | + return false; | |
22 | +}); | |
23 | + | |
24 | +$("#new-circle").live("click", function() { | |
25 | + $(this).fadeOut(); | |
26 | + $("#circle-actions").fadeOut("fast", function() { | |
27 | + $("#new-circle-form").fadeIn(); | |
28 | + }); | |
29 | + return false; | |
30 | +}); | |
31 | + | |
32 | +$("#new-circle-cancel").live("click", function() { | |
33 | + $("#new-circle-form").fadeOut("fast", function() { | |
34 | + $("#circle-actions").fadeIn(); | |
35 | + $("#new-circle").fadeIn(); | |
36 | + $("#text-field-name-new-circle").val('') | |
37 | + }); | |
38 | + return false; | |
39 | +}); | |
40 | + | |
41 | +$('#follow-circles-form').live("submit", function() { | |
42 | + var valuesToSubmit = $(this).serialize(); | |
43 | + $.ajax({ | |
44 | + type: "POST", | |
45 | + url: $(this).attr('action'), | |
46 | + data: valuesToSubmit, | |
47 | + dataType: "JSON", | |
48 | + statusCode: { | |
49 | + 200: function(response){ | |
50 | + $("#circles-container").fadeOut(); | |
51 | + $("#action-unfollow").fadeIn(); | |
52 | + $.colorbox.close(); | |
53 | + display_notice(response.responseText); | |
54 | + }, | |
55 | + 400: function(response) { | |
56 | + display_notice(response.responseText); | |
57 | + } | |
58 | + } | |
59 | + }) | |
60 | + return false; | |
61 | +}); | |
62 | + | |
63 | +$("#new-circle-submit").live("click", function() { | |
64 | + $.ajax({ | |
65 | + method: 'POST', | |
66 | + url: $(this).attr("href"), | |
67 | + data: {'circle[name]': $("#text-field-name-new-circle").val(), | |
68 | + 'circle[profile_type]': $("#circle_profile_type").val()}, | |
69 | + success: function(response) { | |
70 | + $('#circles-checkboxes').append(response); | |
71 | + }, | |
72 | + error: function(response) { | |
73 | + display_notice(response.responseText); | |
74 | + }, | |
75 | + complete: function(response) { | |
76 | + $("#text-field-name-new-circle").val('') | |
77 | + $("#new-circle-cancel").trigger("click"); | |
78 | + } | |
79 | + }) | |
80 | + return false; | |
81 | +}); | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +$('#profile-type-filter').live('change', function() { | |
2 | + var filter_type = $(this).val(); | |
3 | + $(".profile-list").addClass("fetching"); | |
4 | + $.get(window.location.pathname, {filter: filter_type}, function(data) { | |
5 | + $(".main-content").html(data); | |
6 | + }).fail(function(data) { | |
7 | + $(".profile-list").removeClass("fetching"); | |
8 | + }); | |
9 | +}); | ... | ... |
public/stylesheets/blocks/profile-info.scss
... | ... | @@ -99,3 +99,44 @@ |
99 | 99 | margin: 0px 0px 5px 0px; |
100 | 100 | padding: 2px; |
101 | 101 | } |
102 | +#circles-container { | |
103 | + background-color: #eee; | |
104 | + padding: 5px; | |
105 | + display: flex; | |
106 | +} | |
107 | +#circles-container p { | |
108 | + font-size: 12px; | |
109 | + margin-bottom: 5px; | |
110 | +} | |
111 | +#circle-actions { | |
112 | + margin-top: 15px; | |
113 | +} | |
114 | +#new-category-field-actions-block { | |
115 | + float: left; | |
116 | + width: 80%; | |
117 | + margin-bottom: 10px; | |
118 | +} | |
119 | +#new-circle-form { | |
120 | + margin-top: 10px; | |
121 | +} | |
122 | +#new-circle-form input { | |
123 | + width: 90px; | |
124 | +} | |
125 | +#new-circle-form select { | |
126 | + margin-top: 2px; | |
127 | + width: 95px; | |
128 | +} | |
129 | +#new-circle-form label { | |
130 | + font-size: 10px; | |
131 | + margin-right: 5px; | |
132 | +} | |
133 | +#new-circle-form .button-bar { | |
134 | + padding-top: 0px; | |
135 | +} | |
136 | +#new-circle-form .button { | |
137 | + width: 60px; | |
138 | +} | |
139 | +#new-circle-form .button-bar .button { | |
140 | + width: 40px; | |
141 | + font-size: 10px; | |
142 | +} | ... | ... |
public/stylesheets/profile-activity.scss
... | ... | @@ -167,7 +167,9 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { |
167 | 167 | |
168 | 168 | #profile-wall li.profile-activity-item.join_community .profile-activity-text a img, |
169 | 169 | #profile-wall li.profile-activity-item.new_friendship .profile-activity-text a img, |
170 | +#profile-wall li.profile-activity-item.new_follower .profile-activity-text a img, | |
170 | 171 | #profile-network li.profile-activity-item.join_community .profile-activity-text a img, |
172 | +#profile-network li.profile-activity-item.new_follower .profile-activity-text a img, | |
171 | 173 | #profile-network li.profile-activity-item.new_friendship .profile-activity-text a img { |
172 | 174 | margin: 5px 5px 0 0; |
173 | 175 | padding: 1px; | ... | ... |
public/stylesheets/profile-editor.scss
public/stylesheets/profile-list.scss
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | } |
24 | 24 | .controller-favorite_enterprises .profile-list a.profile-link, |
25 | 25 | .controller-friends .profile-list a.profile-link, |
26 | +.controller-followers .profile-list a.profile-link, | |
26 | 27 | .list-profile-connections .profile-list a.profile-link, |
27 | 28 | .profiles-suggestions .profile-list a.profile-link { |
28 | 29 | text-decoration: none; |
... | ... | @@ -32,11 +33,13 @@ |
32 | 33 | } |
33 | 34 | .controller-favorite_enterprises .profile-list a.profile-link:hover, |
34 | 35 | .controller-friends .profile-list a.profile-link:hover, |
36 | +.controller-followers .profile-list a.profile-link:hover, | |
35 | 37 | .profiles-suggestions .profile-list a.profile-link:hover { |
36 | 38 | color: #FFF; |
37 | 39 | } |
38 | 40 | .controller-favorite_enterprises .profile-list .profile_link span, |
39 | 41 | .controller-friends .profile-list .profile_link span, |
42 | +.controller-followers .profile-list .profile_link span, | |
40 | 43 | .box-1 .profiles-suggestions .profile-list .profile_link span { |
41 | 44 | width: 80px; |
42 | 45 | display: block; |
... | ... | @@ -44,12 +47,14 @@ |
44 | 47 | } |
45 | 48 | .controller-favorite_enterprises .profile-list, |
46 | 49 | .controller-friends .profile-list, |
50 | +.controller-followers .profile-list, | |
47 | 51 | .profiles-suggestions .profile-list { |
48 | 52 | position: relative; |
49 | 53 | } |
50 | 54 | |
51 | 55 | .controller-favorite_enterprises .profile-list .controll, |
52 | 56 | .controller-friends .profile-list .controll, |
57 | +.controller-followers .profile-list .controll, | |
53 | 58 | .profiles-suggestions .profile-list .controll { |
54 | 59 | position: absolute; |
55 | 60 | top: 7px; |
... | ... | @@ -57,17 +62,20 @@ |
57 | 62 | } |
58 | 63 | .controller-favorite_enterprises .profile-list .controll a, |
59 | 64 | .controller-friends .profile-list .controll a, |
65 | +.controller-followers .profile-list .controll a, | |
60 | 66 | .profiles-suggestions .profile-list .controll a { |
61 | 67 | display: block; |
62 | 68 | margin-bottom: 2px; |
63 | 69 | } |
64 | 70 | .controller-favorite_enterprises .msie6 .profile-list .controll a, |
65 | 71 | .controller-friends .msie6 .profile-list .controll a, |
72 | +.controller-folloed_people .msie6 .profile-list .controll a, | |
66 | 73 | .profiles-suggestions .msie6 .profile-list .controll a { |
67 | 74 | width: 0px; |
68 | 75 | } |
69 | 76 | .controller-favorite_enterprises .button-bar, |
70 | 77 | .controller-friends .button-bar, |
78 | +.controller-followers .button-bar, | |
71 | 79 | .profiles-suggestions .button-bar { |
72 | 80 | clear: both; |
73 | 81 | padding-top: 20px; |
... | ... | @@ -208,22 +216,35 @@ |
208 | 216 | font-size: 12px; |
209 | 217 | } |
210 | 218 | .action-profile-members .profile_link{ |
211 | - position: relative; | |
219 | + position: relative; | |
212 | 220 | } |
213 | 221 | .action-profile-members .profile_link span.new-profile:last-child{ |
214 | - position: absolute; | |
215 | - top: 3px; | |
216 | - right: 2px; | |
217 | - text-transform: uppercase; | |
218 | - color: #FFF; | |
219 | - font-size: 9px; | |
220 | - background: #66CC33; | |
221 | - padding: 2px; | |
222 | - display: block; | |
223 | - width: 35px; | |
224 | - font-weight: 700; | |
222 | + position: absolute; | |
223 | + top: 3px; | |
224 | + right: 2px; | |
225 | + text-transform: uppercase; | |
226 | + color: #FFF; | |
227 | + font-size: 9px; | |
228 | + background: #66CC33; | |
229 | + padding: 2px; | |
230 | + display: block; | |
231 | + width: 35px; | |
232 | + font-weight: 700; | |
225 | 233 | } |
226 | 234 | .action-profile-members .profile_link .fn{ |
227 | - font-style: normal; | |
228 | - color: #000; | |
235 | + font-style: normal; | |
236 | + color: #000; | |
237 | +} | |
238 | +.category-name { | |
239 | + margin-top: 0px; | |
240 | + margin-bottom: 0px; | |
241 | + font-style: italic; | |
242 | + color: #888a85; | |
243 | + text-align: center; | |
244 | +} | |
245 | +.set-category-modal { | |
246 | + width: 250px; | |
247 | +} | |
248 | +.set-category-modal #actions-container { | |
249 | + margin-top: 20px | |
229 | 250 | } | ... | ... |
public/stylesheets/profile.scss
script/install-dependencies/ubuntu-precise.sh
... | ... | @@ -7,7 +7,7 @@ export DEBIAN_INTERFACE=noninteractive |
7 | 7 | |
8 | 8 | run sudo apt-get install -qy dctrl-tools |
9 | 9 | |
10 | -packages=$(grep-dctrl -n -s Build-Depends,Depends,Recommends -S -X noosfero debian/control | sed -e 's/([^)]*)//g; s/,\s*/\n/g' | grep -v 'rake\|ruby\|thin\|debhelper\|cucumber\|rail\|memcached\|debconf\|dbconfig-common\|misc:Depends\|adduser\|mail-transport-agent') | |
10 | +packages=$(grep-dctrl -n -s Build-Depends,Depends,Recommends -S -X noosfero debian/control | sed -e 's/([^)]*)//g; s/,\s*/\n/g' | grep -v 'rake\|ruby\|thin\|debhelper\|cucumber\|rail\|memcached\|debconf\|dbconfig-common\|misc:Depends\|adduser\|mail-transport-agent\|bundler\|unicorn') | |
11 | 11 | |
12 | 12 | run sudo apt-get install -qy ruby1.9.1-full build-essential libxml2-dev libxslt-dev libpq-dev libmagickcore-dev libmagickwand-dev $packages |
13 | 13 | ... | ... |
test/api/boxes_test.rb
test/api/people_test.rb
... | ... | @@ -397,4 +397,62 @@ class PeopleTest < ActiveSupport::TestCase |
397 | 397 | assert_not_nil person.image |
398 | 398 | assert_equal person.image.filename, base64_image[:filename] |
399 | 399 | end |
400 | + | |
401 | + should 'add logged person as member of a profile' do | |
402 | + login_api | |
403 | + profile = fast_create(Community) | |
404 | + post "/api/v1/profiles/#{profile.id}/members?#{params.to_query}" | |
405 | + json = JSON.parse(last_response.body) | |
406 | + assert_equal json['pending'], false | |
407 | + assert person.is_member_of?(profile) | |
408 | + end | |
409 | + | |
410 | + should 'create task when add logged person as member of a moderated profile' do | |
411 | + login_api | |
412 | + profile = fast_create(Community, public_profile: false) | |
413 | + profile.add_member(create_user.person) | |
414 | + profile.closed = true | |
415 | + profile.save! | |
416 | + post "/api/v1/profiles/#{profile.id}/members?#{params.to_query}" | |
417 | + json = JSON.parse(last_response.body) | |
418 | + assert_equal json['pending'], true | |
419 | + assert !person.is_member_of?(profile) | |
420 | + end | |
421 | + | |
422 | + should 'remove logged person as member of a profile' do | |
423 | + login_api | |
424 | + profile = fast_create(Community) | |
425 | + profile.add_member(person) | |
426 | + delete "/api/v1/profiles/#{profile.id}/members?#{params.to_query}" | |
427 | + json = JSON.parse(last_response.body) | |
428 | + assert_equal person.identifier, json['person']['identifier'] | |
429 | + assert !person.is_member_of?(profile) | |
430 | + end | |
431 | + | |
432 | + should 'forbid access to add members for non logged user' do | |
433 | + profile = fast_create(Community) | |
434 | + post "/api/v1/profiles/#{profile.id}/members?#{params.to_query}" | |
435 | + assert_equal 401, last_response.status | |
436 | + end | |
437 | + | |
438 | + should 'forbid access to remove members for non logged user' do | |
439 | + profile = fast_create(Community) | |
440 | + delete "/api/v1/profiles/#{profile.id}/members?#{params.to_query}" | |
441 | + assert_equal 401, last_response.status | |
442 | + end | |
443 | + | |
444 | + should 'forbid to add person as member when the profile does not allow' do | |
445 | + login_api | |
446 | + profile = fast_create(Person) | |
447 | + post "/api/v1/profiles/#{profile.id}/members?#{params.to_query}" | |
448 | + assert_equal 403, last_response.status | |
449 | + end | |
450 | + | |
451 | + should 'forbid to add person as member when the profile is secret' do | |
452 | + login_api | |
453 | + profile = fast_create(Community, secret: true) | |
454 | + post "/api/v1/profiles/#{profile.id}/members?#{params.to_query}" | |
455 | + assert !person.is_member_of?(profile) | |
456 | + assert_equal 403, last_response.status | |
457 | + end | |
400 | 458 | end | ... | ... |
test/functional/account_controller_test.rb
... | ... | @@ -11,8 +11,7 @@ class AccountControllerTest < ActionController::TestCase |
11 | 11 | |
12 | 12 | def setup |
13 | 13 | @controller = AccountController.new |
14 | - @request = ActionController::TestRequest.new | |
15 | - @response = ActionController::TestResponse.new | |
14 | + | |
16 | 15 | disable_signup_bot_check |
17 | 16 | end |
18 | 17 | ... | ... |
test/functional/admin_panel_controller_test.rb
... | ... | @@ -6,8 +6,7 @@ class AdminPanelControllerTest < ActionController::TestCase |
6 | 6 | all_fixtures |
7 | 7 | def setup |
8 | 8 | @controller = AdminPanelController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
9 | + | |
11 | 10 | login_as(create_admin_user(Environment.default)) |
12 | 11 | end |
13 | 12 | ... | ... |
test/functional/application_controller_test.rb
... | ... | @@ -4,10 +4,9 @@ require 'test_controller' |
4 | 4 | |
5 | 5 | class ApplicationControllerTest < ActionController::TestCase |
6 | 6 | all_fixtures |
7 | + | |
7 | 8 | def setup |
8 | 9 | @controller = TestController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
11 | 10 | end |
12 | 11 | |
13 | 12 | def test_detection_of_environment_by_host |
... | ... | @@ -50,7 +49,7 @@ class ApplicationControllerTest < ActionController::TestCase |
50 | 49 | current = fast_create(Environment, :name => 'test environment') |
51 | 50 | current.domains.create!(:name => 'example.com') |
52 | 51 | |
53 | - @request.expects(:host).returns('example.com').at_least_once | |
52 | + @request.env['HTTP_HOST'] = 'example.com' | |
54 | 53 | get :index |
55 | 54 | |
56 | 55 | assert_equal current, assigns(:environment) | ... | ... |
test/functional/categories_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class CategoriesControllerTest < ActionController::TestCase |
5 | 5 | all_fixtures |
6 | 6 | def setup |
7 | 7 | @controller = CategoriesController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @env = fast_create(Environment, :name => "My test environment") |
12 | 10 | Environment.stubs(:default).returns(env) | ... | ... |
... | ... | @@ -0,0 +1,129 @@ |
1 | +require_relative "../test_helper" | |
2 | +require 'circles_controller' | |
3 | + | |
4 | +class CirclesControllerTest < ActionController::TestCase | |
5 | + | |
6 | + def setup | |
7 | + @controller = CirclesController.new | |
8 | + @person = create_user('person').person | |
9 | + login_as(@person.identifier) | |
10 | + end | |
11 | + | |
12 | + should 'return all circles of a profile' do | |
13 | + circle1 = Circle.create!(:name => "circle1", :person => @person, :profile_type => 'Person') | |
14 | + circle2 = Circle.create!(:name => "circle2", :person => @person, :profile_type => 'Person') | |
15 | + get :index, :profile => @person.identifier | |
16 | + | |
17 | + assert_equivalent [circle1, circle2], assigns[:circles] | |
18 | + end | |
19 | + | |
20 | + should 'initialize an empty circle for creation' do | |
21 | + get :new, :profile => @person.identifier | |
22 | + assert_nil assigns[:circle].id | |
23 | + assert_nil assigns[:circle].name | |
24 | + end | |
25 | + | |
26 | + should 'create a new circle' do | |
27 | + assert_difference '@person.circles.count' do | |
28 | + post :create, :profile => @person.identifier, | |
29 | + :circle => { :name => 'circle' , :profile_type => Person.name} | |
30 | + end | |
31 | + assert_redirected_to :action => :index | |
32 | + end | |
33 | + | |
34 | + should 'not create a circle without a name' do | |
35 | + assert_no_difference '@person.circles.count' do | |
36 | + post :create, :profile => @person.identifier, :circle => { :name => nil } | |
37 | + end | |
38 | + assert_template :new | |
39 | + end | |
40 | + | |
41 | + should 'retrieve an existing circle when editing' do | |
42 | + circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person') | |
43 | + get :edit, :profile => @person.identifier, :id => circle.id | |
44 | + assert_equal circle.name, assigns[:circle].name | |
45 | + end | |
46 | + | |
47 | + should 'return 404 when editing a circle that does not exist' do | |
48 | + get :edit, :profile => @person.identifier, :id => "nope" | |
49 | + assert_response 404 | |
50 | + end | |
51 | + | |
52 | + should 'update an existing circle' do | |
53 | + circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person') | |
54 | + post :update, :profile => @person.identifier, :id => circle.id, | |
55 | + :circle => { :name => "new name" } | |
56 | + | |
57 | + circle.reload | |
58 | + assert_equal "new name", circle.name | |
59 | + assert_redirected_to :action => :index | |
60 | + end | |
61 | + | |
62 | + should 'not update an existing circle without a name' do | |
63 | + circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person') | |
64 | + post :update, :profile => @person.identifier, :id => circle.id, | |
65 | + :circle => { :name => nil } | |
66 | + | |
67 | + circle.reload | |
68 | + assert_equal "circle", circle.name | |
69 | + assert_template :edit | |
70 | + end | |
71 | + | |
72 | + should 'return 404 when updating a circle that does not exist' do | |
73 | + post :update, :profile => @person.identifier, :id => "nope", :name => "new name" | |
74 | + assert_response 404 | |
75 | + end | |
76 | + | |
77 | + should 'destroy an existing circle and update related profiles' do | |
78 | + circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person') | |
79 | + follower = fast_create(ProfileFollower, :profile_id => fast_create(Person).id, | |
80 | + :circle_id => circle.id) | |
81 | + | |
82 | + assert_difference "@person.circles.count", -1 do | |
83 | + post :destroy, :profile => @person.identifier, :id => circle.id | |
84 | + end | |
85 | + | |
86 | + follower.reload | |
87 | + assert_nil follower.circle | |
88 | + end | |
89 | + | |
90 | + should 'not destroy an existing circle if action is not post' do | |
91 | + circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person') | |
92 | + | |
93 | + assert_no_difference "@person.circles.count" do | |
94 | + get :destroy, :profile => @person.identifier, :id => circle.id | |
95 | + end | |
96 | + assert_response 404 | |
97 | + end | |
98 | + | |
99 | + should 'return 404 when deleting and circle that does not exist' do | |
100 | + get :destroy, :profile => @person.identifier, :id => "nope" | |
101 | + assert_response 404 | |
102 | + end | |
103 | + | |
104 | + should 'return 404 for xhr_create if request is not xhr' do | |
105 | + post :xhr_create, :profile => @person.identifier | |
106 | + assert_response 404 | |
107 | + end | |
108 | + | |
109 | + should 'return 400 if not possible to create circle via xhr' do | |
110 | + xhr :post, :xhr_create, :profile => @person.identifier, | |
111 | + :circle => { :name => 'Invalid Circle' } | |
112 | + assert_response 400 | |
113 | + end | |
114 | + | |
115 | + should 'create a new circle via xhr' do | |
116 | + xhr :post, :xhr_create, :profile => @person.identifier, | |
117 | + :circle => { :name => 'A Brand New Circle', | |
118 | + :profile_type => Person.name } | |
119 | + assert_response 201 | |
120 | + assert_match /A Brand New Circle/, response.body | |
121 | + end | |
122 | + | |
123 | + should 'not create a new circle via xhr with an invalid profile_type' do | |
124 | + xhr :post, :xhr_create, :profile => @person.identifier, | |
125 | + :circle => { :name => 'A Brand New Circle', | |
126 | + :profile_type => '__invalid__' } | |
127 | + assert_response 400 | |
128 | + end | |
129 | +end | ... | ... |
test/functional/comment_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class CommentControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = CommentController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @profile = create_user('testinguser').person |
12 | 10 | @environment = @profile.environment | ... | ... |
test/functional/contact_controller_test.rb
... | ... | @@ -8,8 +8,6 @@ class ContactControllerTest < ActionController::TestCase |
8 | 8 | |
9 | 9 | def setup |
10 | 10 | @controller = ContactController.new |
11 | - @request = ActionController::TestRequest.new | |
12 | - @response = ActionController::TestResponse.new | |
13 | 11 | |
14 | 12 | @profile = create_user('contact_test_user').person |
15 | 13 | @enterprise = fast_create(Enterprise, :identifier => 'contact_test_enterprise', :name => 'Test contact enteprise') | ... | ... |
test/functional/content_viewer_controller_test.rb
... | ... | @@ -7,8 +7,6 @@ class ContentViewerControllerTest < ActionController::TestCase |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = ContentViewerController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
12 | 10 | |
13 | 11 | @profile = create_user('testinguser').person |
14 | 12 | @environment = @profile.environment |
... | ... | @@ -220,8 +218,7 @@ class ContentViewerControllerTest < ActionController::TestCase |
220 | 218 | profile.domains << Domain.create!(:name => 'micojones.net') |
221 | 219 | profile.save! |
222 | 220 | |
223 | - ActionController::TestRequest.any_instance.expects(:host).returns('www.micojones.net').at_least_once | |
224 | - | |
221 | + @request.env['HTTP_HOST'] = 'www.micojones.net' | |
225 | 222 | get :view_page, :page => [] |
226 | 223 | |
227 | 224 | assert_equal profile, assigns(:profile) | ... | ... |
test/functional/edit_template_controller_test.rb
... | ... | @@ -7,8 +7,7 @@ class EditTemplateControllerTest < ActionController::TestCase |
7 | 7 | all_fixtures |
8 | 8 | def setup |
9 | 9 | @controller = EditTemplateController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
10 | + | |
12 | 11 | login_as 'ze' |
13 | 12 | end |
14 | 13 | ... | ... |
test/functional/enterprise_registration_controller_test.rb
... | ... | @@ -9,8 +9,7 @@ class EnterpriseRegistrationControllerTest < ActionController::TestCase |
9 | 9 | def setup |
10 | 10 | super |
11 | 11 | @controller = EnterpriseRegistrationController.new |
12 | - @request = ActionController::TestRequest.new | |
13 | - @response = ActionController::TestResponse.new | |
12 | + | |
14 | 13 | login_as 'ze' |
15 | 14 | end |
16 | 15 | ... | ... |
test/functional/enterprise_validation_controller_test.rb
... | ... | @@ -7,8 +7,6 @@ class EnterpriseValidationControllerTest < ActionController::TestCase |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = EnterpriseValidationController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
12 | 10 | |
13 | 11 | login_as 'ze' |
14 | 12 | @user = Profile['ze'] | ... | ... |
test/functional/environment_design_controller_test.rb
... | ... | @@ -7,8 +7,7 @@ class EnvironmentDesignControllerTest < ActionController::TestCase |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = EnvironmentDesignController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
10 | + | |
12 | 11 | Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([]) |
13 | 12 | end |
14 | 13 | ... | ... |
test/functional/environment_role_manager_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ require 'environment_role_manager_controller' |
4 | 4 | class EnvironmentRoleManagerControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | @controller = EnvironmentRoleManagerController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | end |
10 | 8 | |
11 | 9 | end | ... | ... |
test/functional/environment_themes_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ class EnvironmentThemesControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = EnvironmentThemesController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | |
10 | 8 | Theme.stubs(:user_themes_dir).returns(TMP_THEMES_DIR) |
11 | 9 | ... | ... |
test/functional/favorite_enterprises_controller_test.rb
... | ... | @@ -6,8 +6,6 @@ class FavoriteEnterprisesControllerTest < ActionController::TestCase |
6 | 6 | self.default_params = {profile: 'testuser'} |
7 | 7 | def setup |
8 | 8 | @controller = FavoriteEnterprisesController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
11 | 9 | |
12 | 10 | self.profile = create_user('testuser').person |
13 | 11 | self.favorite_enterprise = fast_create(Enterprise, :name => 'the_enterprise', :identifier => 'the_enterprise') | ... | ... |
test/functional/features_controller_test.rb
... | ... | @@ -6,8 +6,6 @@ class FeaturesControllerTest < ActionController::TestCase |
6 | 6 | all_fixtures |
7 | 7 | def setup |
8 | 8 | @controller = FeaturesController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
11 | 9 | |
12 | 10 | login_as(create_admin_user(Environment.find(2))) |
13 | 11 | end | ... | ... |
... | ... | @@ -0,0 +1,58 @@ |
1 | +require_relative "../test_helper" | |
2 | +require 'followers_controller' | |
3 | + | |
4 | +class FollowersControllerTest < ActionController::TestCase | |
5 | + def setup | |
6 | + @profile = create_user('testuser').person | |
7 | + end | |
8 | + | |
9 | + should 'return followed people list' do | |
10 | + login_as(@profile.identifier) | |
11 | + person = fast_create(Person) | |
12 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
13 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id) | |
14 | + | |
15 | + get :index, :profile => @profile.identifier | |
16 | + assert_includes assigns(:followed_people), person | |
17 | + end | |
18 | + | |
19 | + should 'return filtered followed people list' do | |
20 | + login_as(@profile.identifier) | |
21 | + person = fast_create(Person) | |
22 | + community = fast_create(Community) | |
23 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
24 | + circle2 = Circle.create!(:person=> @profile, :name => "Teams", :profile_type => 'Community') | |
25 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id) | |
26 | + fast_create(ProfileFollower, :profile_id => community.id, :circle_id => circle2.id) | |
27 | + | |
28 | + get :index, :profile => @profile.identifier, :filter => "Community" | |
29 | + assert_equal assigns(:followed_people), [community] | |
30 | + | |
31 | + get :index, :profile => @profile.identifier, :filter => "Person" | |
32 | + assert_equal assigns(:followed_people), [person] | |
33 | + end | |
34 | + | |
35 | + should 'redirect to login page if not logged in' do | |
36 | + get :index, :profile => @profile.identifier | |
37 | + assert_redirected_to :controller => 'account', :action => 'login' | |
38 | + end | |
39 | + | |
40 | + should 'render set category modal' do | |
41 | + login_as(@profile.identifier) | |
42 | + person = fast_create(Person) | |
43 | + get :set_category_modal, :profile => @profile.identifier, :followed_profile_id => person.id | |
44 | + assert_tag :tag => "input", :attributes => { :id => "followed_profile_id", :value => person.id } | |
45 | + end | |
46 | + | |
47 | + should 'update followed person category' do | |
48 | + login_as(@profile.identifier) | |
49 | + person = fast_create(Person) | |
50 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
51 | + circle2 = Circle.create!(:person=> @profile, :name => "DotA", :profile_type => 'Person') | |
52 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id) | |
53 | + | |
54 | + post :update_category, :profile => @profile.identifier, :circles => {"DotA"=> circle2.id}, :followed_profile_id => person.id | |
55 | + assert_equivalent ProfileFollower.with_profile(person).with_follower(@profile).map(&:circle), [circle2] | |
56 | + end | |
57 | + | |
58 | +end | ... | ... |
test/functional/friends_controller_test.rb
... | ... | @@ -6,8 +6,6 @@ class FriendsControllerTest < ActionController::TestCase |
6 | 6 | self.default_params = {profile: 'testuser'} |
7 | 7 | def setup |
8 | 8 | @controller = FriendsController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
11 | 9 | |
12 | 10 | self.profile = create_user('testuser').person |
13 | 11 | self.friend = create_user('thefriend').person | ... | ... |
test/functional/home_controller_test.rb
... | ... | @@ -10,8 +10,6 @@ class HomeControllerTest < ActionController::TestCase |
10 | 10 | all_fixtures |
11 | 11 | def setup |
12 | 12 | @controller = HomeController.new |
13 | - @request = ActionController::TestRequest.new | |
14 | - @response = ActionController::TestResponse.new | |
15 | 13 | end |
16 | 14 | |
17 | 15 | should 'not display news from portal if disabled in environment' do | ... | ... |
test/functional/licenses_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class LicensesControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = LicensesController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | @environment = Environment.default |
11 | 10 | login_as(create_admin_user(@environment)) |
12 | 11 | end | ... | ... |
test/functional/mailconf_controller_test.rb
... | ... | @@ -4,8 +4,7 @@ class MailconfControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = MailconfController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
7 | + | |
9 | 8 | User.destroy_all |
10 | 9 | @user = create_user('ze') |
11 | 10 | ... | ... |
test/functional/map_balloon_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class MapBalloonControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = MapBalloonController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @profile = create_user('test_profile').person |
12 | 10 | login_as(@profile.identifier) | ... | ... |
test/functional/maps_controller_test.rb
... | ... | @@ -6,8 +6,6 @@ class MapsControllerTest < ActionController::TestCase |
6 | 6 | |
7 | 7 | def setup |
8 | 8 | @controller = MapsController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
11 | 9 | |
12 | 10 | @profile = create_user('test_profile').person |
13 | 11 | login_as(@profile.identifier) | ... | ... |
test/functional/memberships_controller_test.rb
... | ... | @@ -7,8 +7,6 @@ class MembershipsControllerTest < ActionController::TestCase |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = MembershipsController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
12 | 10 | |
13 | 11 | @profile = create_user('testuser').person |
14 | 12 | login_as('testuser') | ... | ... |
test/functional/my_profile_controller_test.rb
... | ... | @@ -13,8 +13,6 @@ class MyProfileControllerTest < ActionController::TestCase |
13 | 13 | all_fixtures |
14 | 14 | def setup |
15 | 15 | @controller = MyProfileController.new |
16 | - @request = ActionController::TestRequest.new | |
17 | - @response = ActionController::TestResponse.new | |
18 | 16 | end |
19 | 17 | |
20 | 18 | def test_should_allow_person | ... | ... |
test/functional/organizations_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class OrganizationsControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = OrganizationsController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @environment = Environment.default |
12 | 10 | ... | ... |
test/functional/plugins_controller_test.rb
... | ... | @@ -6,8 +6,7 @@ class PluginsControllerTest < ActionController::TestCase |
6 | 6 | all_fixtures |
7 | 7 | def setup |
8 | 8 | @controller = PluginsController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
9 | + | |
11 | 10 | @environment = Environment.default |
12 | 11 | login_as(create_admin_user(@environment)) |
13 | 12 | end | ... | ... |
test/functional/profile_controller_test.rb
... | ... | @@ -771,12 +771,15 @@ class ProfileControllerTest < ActionController::TestCase |
771 | 771 | assert_equal 15, assigns(:activities).size |
772 | 772 | end |
773 | 773 | |
774 | - should 'not see the friends activities in the current profile' do | |
774 | + should 'not see the followers activities in the current profile' do | |
775 | + circle = Circle.create!(:person=> profile, :name => "Zombies", :profile_type => 'Person') | |
776 | + | |
775 | 777 | p2 = create_user.person |
776 | - refute profile.is_a_friend?(p2) | |
778 | + refute profile.follows?(p2) | |
777 | 779 | p3 = create_user.person |
778 | - p3.add_friend(profile) | |
779 | - assert p3.is_a_friend?(profile) | |
780 | + profile.follow(p3, circle) | |
781 | + assert profile.follows?(p3) | |
782 | + | |
780 | 783 | ActionTracker::Record.destroy_all |
781 | 784 | |
782 | 785 | scrap1 = create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3)) |
... | ... | @@ -964,7 +967,11 @@ class ProfileControllerTest < ActionController::TestCase |
964 | 967 | should 'have activities defined if logged in and is following profile' do |
965 | 968 | login_as(profile.identifier) |
966 | 969 | p1= fast_create(Person) |
967 | - p1.add_friend(profile) | |
970 | + | |
971 | + circle = Circle.create!(:person=> profile, :name => "Zombies", :profile_type => 'Person') | |
972 | + | |
973 | + profile.follow(p1, circle) | |
974 | + | |
968 | 975 | ActionTracker::Record.destroy_all |
969 | 976 | get :index, :profile => p1.identifier |
970 | 977 | assert_equal [], assigns(:activities) |
... | ... | @@ -1932,4 +1939,110 @@ class ProfileControllerTest < ActionController::TestCase |
1932 | 1939 | assert_redirected_to :controller => 'account', :action => 'login' |
1933 | 1940 | end |
1934 | 1941 | |
1942 | + should 'not follow a user without defining a circle' do | |
1943 | + login_as(@profile.identifier) | |
1944 | + person = fast_create(Person) | |
1945 | + assert_no_difference 'ProfileFollower.count' do | |
1946 | + post :follow, :profile => person.identifier, :circles => {} | |
1947 | + end | |
1948 | + end | |
1949 | + | |
1950 | + should "not follow user if not logged" do | |
1951 | + person = fast_create(Person) | |
1952 | + get :follow, :profile => person.identifier | |
1953 | + | |
1954 | + assert_redirected_to :controller => 'account', :action => 'login' | |
1955 | + end | |
1956 | + | |
1957 | + should 'follow a user with a circle' do | |
1958 | + login_as(@profile.identifier) | |
1959 | + person = fast_create(Person) | |
1960 | + | |
1961 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
1962 | + | |
1963 | + assert_difference 'ProfileFollower.count' do | |
1964 | + post :follow, :profile => person.identifier, :circles => {"Zombies" => circle.id} | |
1965 | + end | |
1966 | + end | |
1967 | + | |
1968 | + should 'follow a user with more than one circle' do | |
1969 | + login_as(@profile.identifier) | |
1970 | + person = fast_create(Person) | |
1971 | + | |
1972 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
1973 | + circle2 = Circle.create!(:person=> @profile, :name => "Brainsss", :profile_type => 'Person') | |
1974 | + | |
1975 | + assert_difference 'ProfileFollower.count', 2 do | |
1976 | + post :follow, :profile => person.identifier, :circles => {"Zombies" => circle.id, "Brainsss"=> circle2.id} | |
1977 | + end | |
1978 | + end | |
1979 | + | |
1980 | + should 'not follow a user with no circle selected' do | |
1981 | + login_as(@profile.identifier) | |
1982 | + person = fast_create(Person) | |
1983 | + | |
1984 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
1985 | + circle2 = Circle.create!(:person=> @profile, :name => "Brainsss", :profile_type => 'Person') | |
1986 | + | |
1987 | + assert_no_difference 'ProfileFollower.count' do | |
1988 | + post :follow, :profile => person.identifier, :circles => {"Zombies" => "0", "Brainsss" => "0"} | |
1989 | + end | |
1990 | + | |
1991 | + assert_match /Select at least one circle to follow/, response.body | |
1992 | + end | |
1993 | + | |
1994 | + should 'not follow if current_person already follows the person' do | |
1995 | + login_as(@profile.identifier) | |
1996 | + person = fast_create(Person) | |
1997 | + | |
1998 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
1999 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id) | |
2000 | + | |
2001 | + assert_no_difference 'ProfileFollower.count' do | |
2002 | + post :follow, :profile => person.identifier, :follow => { :circles => {"Zombies" => circle.id} } | |
2003 | + end | |
2004 | + assert_response 400 | |
2005 | + end | |
2006 | + | |
2007 | + should "not unfollow user if not logged" do | |
2008 | + person = fast_create(Person) | |
2009 | + post :unfollow, :profile => person.identifier | |
2010 | + | |
2011 | + assert_redirected_to :controller => 'account', :action => 'login' | |
2012 | + end | |
2013 | + | |
2014 | + should "unfollow a followed person" do | |
2015 | + login_as(@profile.identifier) | |
2016 | + person = fast_create(Person) | |
2017 | + | |
2018 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
2019 | + follower = fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id) | |
2020 | + | |
2021 | + assert_not_nil follower | |
2022 | + | |
2023 | + post :unfollow, :profile => person.identifier | |
2024 | + follower = ProfileFollower.find_by(:profile_id => person.id, :circle_id => circle.id) | |
2025 | + assert_nil follower | |
2026 | + end | |
2027 | + | |
2028 | + should "not unfollow a not followed person" do | |
2029 | + login_as(@profile.identifier) | |
2030 | + person = fast_create(Person) | |
2031 | + | |
2032 | + assert_no_difference 'ProfileFollower.count' do | |
2033 | + post :unfollow, :profile => person.identifier | |
2034 | + end | |
2035 | + end | |
2036 | + | |
2037 | + should "redirect to page after unfollow" do | |
2038 | + login_as(@profile.identifier) | |
2039 | + person = fast_create(Person) | |
2040 | + | |
2041 | + circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person') | |
2042 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id) | |
2043 | + | |
2044 | + post :unfollow, :profile => person.identifier, :redirect_to => "/some/url" | |
2045 | + assert_redirected_to "/some/url" | |
2046 | + end | |
2047 | + | |
1935 | 2048 | end | ... | ... |
test/functional/profile_design_controller_test.rb
... | ... | @@ -11,8 +11,6 @@ class ProfileDesignControllerTest < ActionController::TestCase |
11 | 11 | attr_reader :holder |
12 | 12 | def setup |
13 | 13 | @controller = ProfileDesignController.new |
14 | - @request = ActionController::TestRequest.new | |
15 | - @response = ActionController::TestResponse.new | |
16 | 14 | |
17 | 15 | @profile = @holder = create_user('designtestuser').person |
18 | 16 | holder.save! | ... | ... |
test/functional/profile_editor_controller_test.rb
... | ... | @@ -6,8 +6,7 @@ class ProfileEditorControllerTest < ActionController::TestCase |
6 | 6 | |
7 | 7 | def setup |
8 | 8 | @controller = ProfileEditorController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
9 | + | |
11 | 10 | @profile = create_user('default_user').person |
12 | 11 | Environment.default.affiliate(@profile, [Environment::Roles.admin(Environment.default.id)] + Profile::Roles.all_roles(Environment.default.id)) |
13 | 12 | login_as('default_user') |
... | ... | @@ -643,9 +642,10 @@ class ProfileEditorControllerTest < ActionController::TestCase |
643 | 642 | |
644 | 643 | profile.domains << Domain.new(:name => 'myowndomain.net') |
645 | 644 | profile.environment.domains << Domain.new(:name => 'myenv.net') |
646 | - ActionController::TestRequest.any_instance.stubs(:host).returns(profile.hostname) | |
647 | 645 | |
646 | + @request.env['HTTP_HOST'] = profile.hostname | |
648 | 647 | get :edit, :profile => profile.identifier |
648 | + | |
649 | 649 | assert_tag :tag => 'select', :attributes => { :name => 'profile_data[preferred_domain_id]' }, :descendant => { :tag => "option", :content => 'myowndomain.net' } |
650 | 650 | assert_tag :tag => 'select', :attributes => { :name => 'profile_data[preferred_domain_id]' }, :descendant => { :tag => "option", :content => 'myenv.net' } |
651 | 651 | |
... | ... | @@ -659,9 +659,10 @@ class ProfileEditorControllerTest < ActionController::TestCase |
659 | 659 | |
660 | 660 | profile.domains << Domain.new(:name => 'myowndomain.net') |
661 | 661 | profile.environment.domains << Domain.new(:name => 'myenv.net') |
662 | - ActionController::TestRequest.any_instance.stubs(:host).returns(profile.hostname) | |
663 | 662 | |
663 | + @request.env['HTTP_HOST'] = profile.hostname | |
664 | 664 | get :edit, :profile => profile.identifier |
665 | + | |
665 | 666 | assert_tag :tag => "select", :attributes => { :name => 'profile_data[preferred_domain_id]'}, :descendant => { :tag => 'option', :content => '<Select domain>', :attributes => { :value => '' } } |
666 | 667 | |
667 | 668 | post :edit, :profile => profile.identifier, :profile_data => { :preferred_domain_id => '' } |
... | ... | @@ -1112,8 +1113,10 @@ class ProfileEditorControllerTest < ActionController::TestCase |
1112 | 1113 | should 'not redirect if the profile_hostname is the same as environment hostname' do |
1113 | 1114 | Person.any_instance.stubs(:hostname).returns('hostname.org') |
1114 | 1115 | Environment.any_instance.stubs(:default_hostname).returns('hostname.org') |
1115 | - ActionController::TestRequest.any_instance.stubs(:host).returns('hostname.org') | |
1116 | + | |
1117 | + @request.env['HTTP_HOST'] = 'hostname.org' | |
1116 | 1118 | get :index, :profile => profile.identifier |
1119 | + | |
1117 | 1120 | assert_response :success |
1118 | 1121 | end |
1119 | 1122 | ... | ... |
test/functional/profile_members_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class ProfileMembersControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | super |
7 | 7 | @controller = ProfileMembersController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | end |
11 | 9 | |
12 | 10 | should 'not access index if dont have permission' do | ... | ... |
test/functional/profile_roles_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class ProfileRolesControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = ProfileRolesController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | @role = Role.first |
11 | 10 | end |
12 | 11 | ... | ... |
test/functional/profile_search_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ require 'profile_search_controller' |
4 | 4 | class ProfileSearchControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | @controller = ProfileSearchController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | |
10 | 8 | @person = fast_create(Person) |
11 | 9 | end | ... | ... |
test/functional/profile_themes_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ class ProfileThemesControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = ProfileThemesController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | |
10 | 8 | Theme.stubs(:user_themes_dir).returns(TMP_THEMES_DIR) |
11 | 9 | ... | ... |
test/functional/region_validators_controller_test.rb
... | ... | @@ -5,8 +5,7 @@ class RegionValidatorsControllerTest < ActionController::TestCase |
5 | 5 | all_fixtures |
6 | 6 | def setup |
7 | 7 | @controller = RegionValidatorsController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
8 | + | |
10 | 9 | login_as('ze') |
11 | 10 | end |
12 | 11 | ... | ... |
test/functional/role_controller_test.rb
... | ... | @@ -6,8 +6,7 @@ class RoleControllerTest < ActionController::TestCase |
6 | 6 | |
7 | 7 | def setup |
8 | 8 | @controller = RoleController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
9 | + | |
11 | 10 | @role = Role.first |
12 | 11 | login_as(:ze) |
13 | 12 | end | ... | ... |
test/functional/search_controller_test.rb
... | ... | @@ -4,9 +4,6 @@ class SearchControllerTest < ActionController::TestCase |
4 | 4 | |
5 | 5 | def setup |
6 | 6 | @controller = SearchController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @request.stubs(:ssl?).returns(false) | |
9 | - @response = ActionController::TestResponse.new | |
10 | 7 | |
11 | 8 | @environment = Environment.default |
12 | 9 | @category = Category.create!(:name => 'my-category', :environment => @environment) | ... | ... |
test/functional/system_controller_test.rb
... | ... | @@ -4,8 +4,6 @@ require 'system_controller' |
4 | 4 | class SystemControllerTest < ActionController::TestCase |
5 | 5 | def setup |
6 | 6 | @controller = SystemController.new |
7 | - @request = ActionController::TestRequest.new | |
8 | - @response = ActionController::TestResponse.new | |
9 | 7 | end |
10 | 8 | |
11 | 9 | # Replace this with your real tests. | ... | ... |
test/functional/tasks_controller_test.rb
... | ... | @@ -7,8 +7,6 @@ class TasksControllerTest < ActionController::TestCase |
7 | 7 | |
8 | 8 | def setup |
9 | 9 | @controller = TasksController.new |
10 | - @request = ActionController::TestRequest.new | |
11 | - @response = ActionController::TestResponse.new | |
12 | 10 | |
13 | 11 | self.profile = create_user('testuser').person |
14 | 12 | @controller.stubs(:profile).returns(profile) | ... | ... |
test/functional/templates_controller_test.rb
... | ... | @@ -5,8 +5,6 @@ class TemplatesControllerTest < ActionController::TestCase |
5 | 5 | |
6 | 6 | def setup |
7 | 7 | @controller = TemplatesController.new |
8 | - @request = ActionController::TestRequest.new | |
9 | - @response = ActionController::TestResponse.new | |
10 | 8 | |
11 | 9 | @environment = Environment.default |
12 | 10 | login_as(create_admin_user(@environment)) | ... | ... |
test/functional/trusted_sites_controller_test.rb
... | ... | @@ -6,8 +6,7 @@ class TrustedSitesControllerTest < ActionController::TestCase |
6 | 6 | |
7 | 7 | def setup |
8 | 8 | @controller = TrustedSitesController.new |
9 | - @request = ActionController::TestRequest.new | |
10 | - @response = ActionController::TestResponse.new | |
9 | + | |
11 | 10 | @role = Role.first |
12 | 11 | @environment = Environment.default |
13 | 12 | @environment.trusted_sites_for_iframe = ['existing.site.com'] | ... | ... |
test/functional/users_controller_test.rb
test/unit/article_test.rb
... | ... | @@ -1099,9 +1099,10 @@ class ArticleTest < ActiveSupport::TestCase |
1099 | 1099 | assert_equal 3, ActionTrackerNotification.where(action_tracker_id: second_activity.id).count |
1100 | 1100 | end |
1101 | 1101 | |
1102 | - should 'create notifications to friends when creating an article' do | |
1102 | + should 'create notifications to followers when creating an article' do | |
1103 | 1103 | friend = fast_create(Person) |
1104 | - profile.add_friend(friend) | |
1104 | + circle = Circle.create!(:person=> friend, :name => "Zombies", :profile_type => 'Person') | |
1105 | + friend.follow(profile, circle) | |
1105 | 1106 | Article.destroy_all |
1106 | 1107 | ActionTracker::Record.destroy_all |
1107 | 1108 | ActionTrackerNotification.destroy_all |
... | ... | @@ -1112,9 +1113,10 @@ class ArticleTest < ActiveSupport::TestCase |
1112 | 1113 | assert_equal friend, ActionTrackerNotification.last.profile |
1113 | 1114 | end |
1114 | 1115 | |
1115 | - should 'create the notification to the friend when one friend has the notification and the other no' do | |
1116 | + should 'create the notification to the follower when one follower has the notification and the other no' do | |
1116 | 1117 | f1 = fast_create(Person) |
1117 | - profile.add_friend(f1) | |
1118 | + circle = Circle.create!(:person=> f1, :name => "Zombies", :profile_type => 'Person') | |
1119 | + f1.follow(profile, circle) | |
1118 | 1120 | |
1119 | 1121 | User.current = profile.user |
1120 | 1122 | article = create TinyMceArticle, :name => 'Tracked Article 1', :profile_id => profile.id |
... | ... | @@ -1123,16 +1125,22 @@ class ArticleTest < ActiveSupport::TestCase |
1123 | 1125 | assert_equal 2, ActionTrackerNotification.where(action_tracker_id: article.activity.id).count |
1124 | 1126 | |
1125 | 1127 | f2 = fast_create(Person) |
1126 | - profile.add_friend(f2) | |
1128 | + circle2 = Circle.create!(:person=> f2, :name => "Zombies", :profile_type => 'Person') | |
1129 | + f2.follow(profile, circle2) | |
1130 | + | |
1127 | 1131 | article2 = create TinyMceArticle, :name => 'Tracked Article 2', :profile_id => profile.id |
1128 | 1132 | assert_equal 2, ActionTracker::Record.where(verb: 'create_article').count |
1129 | 1133 | process_delayed_job_queue |
1130 | 1134 | assert_equal 3, ActionTrackerNotification.where(action_tracker_id: article2.activity.id).count |
1131 | 1135 | end |
1132 | 1136 | |
1133 | - should 'destroy activity and notifications of friends when destroying an article' do | |
1137 | + should 'destroy activity and notifications of followers when destroying an article' do | |
1134 | 1138 | friend = fast_create(Person) |
1135 | - profile.add_friend(friend) | |
1139 | + | |
1140 | + circle = Circle.create!(:person=> friend, :name => "Zombies", :profile_type => 'Person') | |
1141 | + | |
1142 | + friend.follow(profile, circle) | |
1143 | + | |
1136 | 1144 | Article.destroy_all |
1137 | 1145 | ActionTracker::Record.destroy_all |
1138 | 1146 | ActionTrackerNotification.destroy_all | ... | ... |
... | ... | @@ -0,0 +1,19 @@ |
1 | +require_relative "../test_helper" | |
2 | + | |
3 | +class CustomDesignTest < ActionView::TestCase | |
4 | + | |
5 | + include CustomDesign | |
6 | + include ActionView::Helpers::TagHelper | |
7 | + | |
8 | + def setup | |
9 | + end | |
10 | + | |
11 | + should 'allow class instance customization of custom design' do | |
12 | + self.class.use_custom_design boxes_limit: 1 | |
13 | + assert_equal({boxes_limit: 1}, self.custom_design) | |
14 | + @custom_design = {boxes_limit: 2} | |
15 | + assert_equal({boxes_limit: 2}, self.custom_design) | |
16 | + | |
17 | + end | |
18 | + | |
19 | +end | ... | ... |
test/unit/event_test.rb
... | ... | @@ -282,7 +282,7 @@ class EventTest < ActiveSupport::TestCase |
282 | 282 | end |
283 | 283 | |
284 | 284 | should 'be translatable' do |
285 | - assert_kind_of Noosfero::TranslatableContent, Event.new | |
285 | + assert_kind_of TranslatableContent, Event.new | |
286 | 286 | end |
287 | 287 | |
288 | 288 | should 'tiny mce editor is enabled' do | ... | ... |
test/unit/friendship_test.rb
... | ... | @@ -28,14 +28,14 @@ class FriendshipTest < ActiveSupport::TestCase |
28 | 28 | f.person = a |
29 | 29 | f.friend = b |
30 | 30 | f.save! |
31 | - ta = ActionTracker::Record.last | |
31 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last | |
32 | 32 | assert_equal a, ta.user |
33 | 33 | assert_equal 'b', ta.get_friend_name[0] |
34 | 34 | f = Friendship.new |
35 | 35 | f.person = a |
36 | 36 | f.friend = c |
37 | 37 | f.save! |
38 | - ta = ActionTracker::Record.last | |
38 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last | |
39 | 39 | assert_equal a, ta.user |
40 | 40 | assert_equal 'c', ta.get_friend_name[1] |
41 | 41 | end |
... | ... | @@ -46,14 +46,14 @@ class FriendshipTest < ActiveSupport::TestCase |
46 | 46 | f.person = a |
47 | 47 | f.friend = b |
48 | 48 | f.save! |
49 | - ta = ActionTracker::Record.last | |
49 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last | |
50 | 50 | assert_equal a, ta.user |
51 | 51 | assert_equal ['b'], ta.get_friend_name |
52 | 52 | f = Friendship.new |
53 | 53 | f.person = b |
54 | 54 | f.friend = a |
55 | 55 | f.save! |
56 | - ta = ActionTracker::Record.last | |
56 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last | |
57 | 57 | assert_equal b, ta.user |
58 | 58 | assert_equal ['a'], ta.get_friend_name |
59 | 59 | end |
... | ... | @@ -72,4 +72,55 @@ class FriendshipTest < ActiveSupport::TestCase |
72 | 72 | assert_not_includes p2.friends(true), p1 |
73 | 73 | end |
74 | 74 | |
75 | + should 'add follower when adding friend' do | |
76 | + p1 = create_user('testuser1').person | |
77 | + p2 = create_user('testuser2').person | |
78 | + | |
79 | + assert_difference 'ProfileFollower.count', 2 do | |
80 | + p1.add_friend(p2, 'friends') | |
81 | + p2.add_friend(p1, 'friends') | |
82 | + end | |
83 | + | |
84 | + assert_includes p1.followers(true), p2 | |
85 | + assert_includes p2.followers(true), p1 | |
86 | + end | |
87 | + | |
88 | + should 'remove follower when a friend removal occurs' do | |
89 | + p1 = create_user('testuser1').person | |
90 | + p2 = create_user('testuser2').person | |
91 | + | |
92 | + p1.add_friend(p2, 'friends') | |
93 | + p2.add_friend(p1, 'friends') | |
94 | + | |
95 | + Friendship.remove_friendship(p1, p2) | |
96 | + | |
97 | + assert_not_includes p1.followers(true), p2 | |
98 | + assert_not_includes p2.followers(true), p1 | |
99 | + end | |
100 | + | |
101 | + should 'keep friendship intact when stop following' do | |
102 | + p1 = create_user('testuser1').person | |
103 | + p2 = create_user('testuser2').person | |
104 | + | |
105 | + p1.add_friend(p2, 'friends') | |
106 | + p2.add_friend(p1, 'friends') | |
107 | + | |
108 | + p1.unfollow(p2) | |
109 | + | |
110 | + assert_includes p1.friends(true), p2 | |
111 | + assert_includes p2.friends(true), p1 | |
112 | + end | |
113 | + | |
114 | + should 'do not add friendship when start following' do | |
115 | + p1 = create_user('testuser1').person | |
116 | + p2 = create_user('testuser2').person | |
117 | + | |
118 | + circle1 = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
119 | + circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person') | |
120 | + p1.follow(p2, circle1) | |
121 | + p2.follow(p1, circle2) | |
122 | + | |
123 | + assert_not_includes p1.friends(true), p2 | |
124 | + assert_not_includes p2.friends(true), p1 | |
125 | + end | |
75 | 126 | end | ... | ... |
test/unit/noosfero_test.rb
... | ... | @@ -43,10 +43,12 @@ class NoosferoTest < 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 | ... | ... |
test/unit/notify_activity_to_profiles_job_test.rb
... | ... | @@ -24,15 +24,21 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase |
24 | 24 | end |
25 | 25 | end |
26 | 26 | |
27 | - should 'notify just the users and his friends tracking user actions' do | |
27 | + should 'notify just the users and his followers tracking user actions' do | |
28 | 28 | person = fast_create(Person) |
29 | 29 | community = fast_create(Community) |
30 | 30 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :verb => 'create_article') |
31 | 31 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) |
32 | 32 | p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person) |
33 | - fast_create(Friendship, :person_id => person.id, :friend_id => p1.id) | |
34 | - fast_create(Friendship, :person_id => person.id, :friend_id => p2.id) | |
35 | - fast_create(Friendship, :person_id => p1.id, :friend_id => m1.id) | |
33 | + | |
34 | + circle1 = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
35 | + circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person') | |
36 | + circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Person') | |
37 | + | |
38 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle1.id) | |
39 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle2.id) | |
40 | + fast_create(ProfileFollower, :profile_id => m1.id, :circle_id => circle.id) | |
41 | + | |
36 | 42 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) |
37 | 43 | ActionTrackerNotification.delete_all |
38 | 44 | job = NotifyActivityToProfilesJob.new(action_tracker.id) |
... | ... | @@ -66,23 +72,24 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase |
66 | 72 | end |
67 | 73 | end |
68 | 74 | |
69 | - should 'notify users its friends, the community and its members' do | |
75 | + should 'notify users its followers, the community and its members' do | |
70 | 76 | person = fast_create(Person) |
71 | 77 | community = fast_create(Community) |
72 | 78 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'create_article') |
73 | 79 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) |
74 | 80 | p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person) |
75 | - fast_create(Friendship, :person_id => person.id, :friend_id => p1.id) | |
76 | - fast_create(Friendship, :person_id => person.id, :friend_id => p2.id) | |
81 | + | |
82 | + circle1 = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
83 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle1.id) | |
84 | + | |
77 | 85 | fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id) |
78 | 86 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) |
79 | 87 | ActionTrackerNotification.delete_all |
80 | 88 | job = NotifyActivityToProfilesJob.new(action_tracker.id) |
81 | 89 | job.perform |
82 | 90 | process_delayed_job_queue |
83 | - | |
84 | - assert_equal 6, ActionTrackerNotification.count | |
85 | - [person, community, p1, p2, m1, m2].each do |profile| | |
91 | + assert_equal 5, ActionTrackerNotification.count | |
92 | + [person, community, p1, m1, m2].each do |profile| | |
86 | 93 | notification = ActionTrackerNotification.find_by profile_id: profile.id |
87 | 94 | assert_equal action_tracker, notification.action_tracker |
88 | 95 | end |
... | ... | @@ -119,8 +126,13 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase |
119 | 126 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'join_community') |
120 | 127 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) |
121 | 128 | p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person) |
122 | - fast_create(Friendship, :person_id => person.id, :friend_id => p1.id) | |
123 | - fast_create(Friendship, :person_id => person.id, :friend_id => p2.id) | |
129 | + | |
130 | + circle1 = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
131 | + circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person') | |
132 | + | |
133 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle1.id) | |
134 | + fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle2.id) | |
135 | + | |
124 | 136 | fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id) |
125 | 137 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) |
126 | 138 | ActionTrackerNotification.delete_all | ... | ... |
test/unit/person_notifier_test.rb
... | ... | @@ -178,6 +178,7 @@ class PersonNotifierTest < ActiveSupport::TestCase |
178 | 178 | update_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) }, |
179 | 179 | remove_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) }, |
180 | 180 | favorite_enterprise: -> { create FavoriteEnterprisePerson, enterprise: create(Enterprise), person: @member }, |
181 | + new_follower: -> { @member } | |
181 | 182 | } |
182 | 183 | |
183 | 184 | ActionTrackerConfig.verb_names.each do |verb| |
... | ... | @@ -197,6 +198,7 @@ class PersonNotifierTest < ActiveSupport::TestCase |
197 | 198 | 'friend_url' => '/', 'friend_profile_custom_icon' => [], 'friend_name' => ['joe'], |
198 | 199 | 'resource_name' => ['resource'], 'resource_profile_custom_icon' => [], 'resource_url' => ['/'], |
199 | 200 | 'enterprise_name' => 'coop', 'enterprise_url' => '/coop', |
201 | + 'follower_url' => '/', 'follower_profile_custom_icon' => [], 'follower_name' => ['joe'], | |
200 | 202 | 'view_url'=> ['/'], 'thumbnail_path' => ['1'], |
201 | 203 | } |
202 | 204 | a.get_url = '' | ... | ... |
test/unit/person_test.rb
... | ... | @@ -728,7 +728,7 @@ class PersonTest < ActiveSupport::TestCase |
728 | 728 | assert_equal [s4], p2.scraps_received.not_replies |
729 | 729 | end |
730 | 730 | |
731 | - should "the followed_by method be protected and true to the person friends and herself by default" do | |
731 | + should "the followed_by method return true to the person friends and herself by default" do | |
732 | 732 | p1 = fast_create(Person) |
733 | 733 | p2 = fast_create(Person) |
734 | 734 | p3 = fast_create(Person) |
... | ... | @@ -740,9 +740,9 @@ class PersonTest < ActiveSupport::TestCase |
740 | 740 | assert p1.is_a_friend?(p4) |
741 | 741 | |
742 | 742 | assert_equal true, p1.send(:followed_by?,p1) |
743 | - assert_equal true, p1.send(:followed_by?,p2) | |
744 | - assert_equal true, p1.send(:followed_by?,p4) | |
745 | - assert_equal false, p1.send(:followed_by?,p3) | |
743 | + assert_equal true, p2.send(:followed_by?,p1) | |
744 | + assert_equal true, p4.send(:followed_by?,p1) | |
745 | + assert_equal false, p3.send(:followed_by?,p1) | |
746 | 746 | end |
747 | 747 | |
748 | 748 | should "the person follows her friends and herself by default" do |
... | ... | @@ -757,9 +757,9 @@ class PersonTest < ActiveSupport::TestCase |
757 | 757 | assert p4.is_a_friend?(p1) |
758 | 758 | |
759 | 759 | assert_equal true, p1.follows?(p1) |
760 | - assert_equal true, p1.follows?(p2) | |
761 | - assert_equal true, p1.follows?(p4) | |
762 | - assert_equal false, p1.follows?(p3) | |
760 | + assert_equal true, p2.follows?(p1) | |
761 | + assert_equal true, p4.follows?(p1) | |
762 | + assert_equal false, p3.follows?(p1) | |
763 | 763 | end |
764 | 764 | |
765 | 765 | should "a person member of a community follows the community" do |
... | ... | @@ -836,18 +836,21 @@ class PersonTest < ActiveSupport::TestCase |
836 | 836 | assert_nil Scrap.find_by(id: scrap.id) |
837 | 837 | end |
838 | 838 | |
839 | - should "the tracked action be notified to person friends and herself" do | |
839 | + should "the tracked action be notified to person followers and herself" do | |
840 | 840 | Person.destroy_all |
841 | 841 | p1 = fast_create(Person) |
842 | 842 | p2 = fast_create(Person) |
843 | 843 | p3 = fast_create(Person) |
844 | 844 | p4 = fast_create(Person) |
845 | 845 | |
846 | - p1.add_friend(p2) | |
847 | - assert p1.is_a_friend?(p2) | |
848 | - refute p1.is_a_friend?(p3) | |
849 | - p1.add_friend(p4) | |
850 | - assert p1.is_a_friend?(p4) | |
846 | + circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person') | |
847 | + circle4 = Circle.create!(:person=> p4, :name => "Zombies", :profile_type => 'Person') | |
848 | + | |
849 | + p2.follow(p1, circle2) | |
850 | + assert p2.follows?(p1) | |
851 | + refute p3.follows?(p1) | |
852 | + p4.follow(p1, circle4) | |
853 | + assert p4.follows?(p1) | |
851 | 854 | |
852 | 855 | action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id) |
853 | 856 | ActionTrackerNotification.delete_all |
... | ... | @@ -880,17 +883,19 @@ class PersonTest < ActiveSupport::TestCase |
880 | 883 | end |
881 | 884 | end |
882 | 885 | |
883 | - should "the tracked action notify friends with one delayed job process" do | |
886 | + should "the tracked action notify followers with one delayed job process" do | |
884 | 887 | p1 = fast_create(Person) |
885 | 888 | p2 = fast_create(Person) |
886 | 889 | p3 = fast_create(Person) |
887 | 890 | p4 = fast_create(Person) |
888 | 891 | |
889 | - p1.add_friend(p2) | |
890 | - assert p1.is_a_friend?(p2) | |
891 | - refute p1.is_a_friend?(p3) | |
892 | - p1.add_friend(p4) | |
893 | - assert p1.is_a_friend?(p4) | |
892 | + circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person') | |
893 | + circle4 = Circle.create!(:person=> p4, :name => "Zombies", :profile_type => 'Person') | |
894 | + p2.follow(p1, circle2) | |
895 | + assert p2.follows?(p1) | |
896 | + refute p3.follows?(p1) | |
897 | + p4.follow(p1, circle4) | |
898 | + assert p4.follows?(p1) | |
894 | 899 | |
895 | 900 | action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id) |
896 | 901 | |
... | ... | @@ -1035,11 +1040,13 @@ class PersonTest < ActiveSupport::TestCase |
1035 | 1040 | p2 = create_user('p2').person |
1036 | 1041 | p3 = create_user('p3').person |
1037 | 1042 | c = fast_create(Community, :name => "Foo") |
1043 | + | |
1038 | 1044 | c.add_member(p1) |
1039 | 1045 | process_delayed_job_queue |
1040 | 1046 | c.add_member(p3) |
1041 | 1047 | process_delayed_job_queue |
1042 | - assert_equal 4, ActionTracker::Record.count | |
1048 | + | |
1049 | + assert_equal 5, ActionTracker::Record.count | |
1043 | 1050 | assert_equal 5, ActionTrackerNotification.count |
1044 | 1051 | has_add_member_notification = false |
1045 | 1052 | ActionTrackerNotification.all.map do |notification| |
... | ... | @@ -1951,4 +1958,51 @@ class PersonTest < ActiveSupport::TestCase |
1951 | 1958 | person.save! |
1952 | 1959 | end |
1953 | 1960 | |
1961 | + should 'update profile circles for a person' do | |
1962 | + person = create_user('testuser').person | |
1963 | + community = fast_create(Community) | |
1964 | + circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') | |
1965 | + circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community') | |
1966 | + circle3 = Circle.create!(:person=> person, :name => "Quadrado", :profile_type => 'Community') | |
1967 | + person.follow(community, [circle, circle2]) | |
1968 | + person.update_profile_circles(community, [circle2, circle3]) | |
1969 | + assert_equivalent [circle2, circle3], ProfileFollower.with_profile(community).with_follower(person).map(&:circle) | |
1970 | + end | |
1971 | + | |
1972 | + should 'a person follow a profile' do | |
1973 | + person = create_user('testuser').person | |
1974 | + community = fast_create(Community) | |
1975 | + circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') | |
1976 | + person.follow(community, circle) | |
1977 | + assert_includes person.followed_profiles, community | |
1978 | + end | |
1979 | + | |
1980 | + should 'a person follow a profile with more than one circle' do | |
1981 | + person = create_user('testuser').person | |
1982 | + community = fast_create(Community) | |
1983 | + circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') | |
1984 | + circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community') | |
1985 | + person.follow(community, [circle, circle2]) | |
1986 | + assert_includes person.followed_profiles, community | |
1987 | + assert_equivalent [circle, circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle) | |
1988 | + end | |
1989 | + | |
1990 | + should 'a person unfollow a profile' do | |
1991 | + person = create_user('testuser').person | |
1992 | + community = fast_create(Community) | |
1993 | + circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') | |
1994 | + person.follow(community, circle) | |
1995 | + person.unfollow(community) | |
1996 | + assert_not_includes person.followed_profiles, community | |
1997 | + end | |
1998 | + | |
1999 | + should 'a person remove a profile from a circle' do | |
2000 | + person = create_user('testuser').person | |
2001 | + community = fast_create(Community) | |
2002 | + circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') | |
2003 | + circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community') | |
2004 | + person.follow(community, [circle, circle2]) | |
2005 | + person.remove_profile_from_circle(community, circle) | |
2006 | + assert_equivalent [circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle) | |
2007 | + end | |
1954 | 2008 | end | ... | ... |
... | ... | @@ -0,0 +1,73 @@ |
1 | +require_relative "../test_helper" | |
2 | + | |
3 | +class ProfileFollowersTest < ActiveSupport::TestCase | |
4 | + | |
5 | + should 'a person follow another' do | |
6 | + p1 = create_user('person_test').person | |
7 | + p2 = create_user('person_test_2').person | |
8 | + circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
9 | + | |
10 | + assert_difference 'ProfileFollower.count' do | |
11 | + p1.follow(p2, circle) | |
12 | + end | |
13 | + | |
14 | + assert_includes p2.followers(true), p1 | |
15 | + assert_not_includes p1.followers(true), p2 | |
16 | + end | |
17 | + | |
18 | + should 'a person unfollow another person' do | |
19 | + p1 = create_user('person_test').person | |
20 | + p2 = create_user('person_test_2').person | |
21 | + circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
22 | + | |
23 | + p1.follow(p2,circle) | |
24 | + | |
25 | + assert_difference 'ProfileFollower.count', -1 do | |
26 | + p1.unfollow(p2) | |
27 | + end | |
28 | + | |
29 | + assert_not_includes p2.followers(true), p1 | |
30 | + end | |
31 | + | |
32 | + should 'get the followed persons for a profile' do | |
33 | + p1 = create_user('person_test').person | |
34 | + p2 = create_user('person_test_2').person | |
35 | + p3 = create_user('person_test_3').person | |
36 | + circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
37 | + | |
38 | + p1.follow(p2, circle) | |
39 | + p1.follow(p3, circle) | |
40 | + | |
41 | + assert_equivalent p1.followed_profiles, [p2,p3] | |
42 | + assert_equivalent Profile.followed_by(p1), [p2,p3] | |
43 | + end | |
44 | + | |
45 | + should 'not follow same person twice' do | |
46 | + p1 = create_user('person_test').person | |
47 | + p2 = create_user('person_test_2').person | |
48 | + circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
49 | + | |
50 | + assert_difference 'ProfileFollower.count' do | |
51 | + p1.follow(p2, circle) | |
52 | + p1.follow(p2, circle) | |
53 | + end | |
54 | + | |
55 | + assert_equivalent p1.followed_profiles, [p2] | |
56 | + assert_equivalent p2.followers, [p1] | |
57 | + end | |
58 | + | |
59 | + should 'show the correct message when a profile is followed by the same person' do | |
60 | + p1 = create_user('person_test').person | |
61 | + p2 = create_user('person_test_2').person | |
62 | + circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') | |
63 | + | |
64 | + p1.follow(p2, circle) | |
65 | + profile_follower = ProfileFollower.new | |
66 | + profile_follower.circle = circle | |
67 | + profile_follower.profile = p2 | |
68 | + profile_follower.valid? | |
69 | + | |
70 | + assert_includes profile_follower.errors.messages[:profile_id], | |
71 | + "can't put a profile in the same circle twice" | |
72 | + end | |
73 | +end | ... | ... |
test/unit/profile_test.rb
... | ... | @@ -2224,4 +2224,12 @@ class ProfileTest < ActiveSupport::TestCase |
2224 | 2224 | assert !profile.send("allow_#{permission.gsub(/_profile/,'')}?", nil) |
2225 | 2225 | end |
2226 | 2226 | end |
2227 | + | |
2228 | + should 'not allow to add members in secret profiles' do | |
2229 | + c = fast_create(Community, secret: true) | |
2230 | + p = create_user('mytestuser').person | |
2231 | + assert_raise RuntimeError do | |
2232 | + c.add_member(p) | |
2233 | + end | |
2234 | + end | |
2227 | 2235 | end | ... | ... |
test/unit/scrap_test.rb
... | ... | @@ -125,11 +125,11 @@ class ScrapTest < ActiveSupport::TestCase |
125 | 125 | assert_equal c, ta.target |
126 | 126 | end |
127 | 127 | |
128 | - should "notify leave_scrap action tracker verb to friends and itself" do | |
128 | + should "notify leave_scrap action tracker verb to followers and itself" do | |
129 | 129 | User.current = create_user |
130 | 130 | p1 = User.current.person |
131 | 131 | p2 = create_user.person |
132 | - p1.add_friend(p2) | |
132 | + p2.add_friend(p1) | |
133 | 133 | process_delayed_job_queue |
134 | 134 | s = Scrap.new |
135 | 135 | s.sender= p1 |
... | ... | @@ -180,11 +180,11 @@ class ScrapTest < ActiveSupport::TestCase |
180 | 180 | assert_equal p, ta.user |
181 | 181 | end |
182 | 182 | |
183 | - should "notify leave_scrap_to_self action tracker verb to friends and itself" do | |
183 | + should "notify leave_scrap_to_self action tracker verb to followers and itself" do | |
184 | 184 | User.current = create_user |
185 | 185 | p1 = User.current.person |
186 | 186 | p2 = create_user.person |
187 | - p1.add_friend(p2) | |
187 | + p2.add_friend(p1) | |
188 | 188 | ActionTrackerNotification.delete_all |
189 | 189 | Delayed::Job.delete_all |
190 | 190 | s = Scrap.new | ... | ... |
test/unit/text_article_test.rb
... | ... | @@ -15,7 +15,7 @@ class TextArticleTest < ActiveSupport::TestCase |
15 | 15 | end |
16 | 16 | |
17 | 17 | should 'be translatable' do |
18 | - assert_kind_of Noosfero::TranslatableContent, TextArticle.new | |
18 | + assert_kind_of TranslatableContent, TextArticle.new | |
19 | 19 | end |
20 | 20 | |
21 | 21 | should 'return article icon name' do | ... | ... |
test/unit/translatable_content_test.rb
vendor/plugins/access_control/test/permission_check_test.rb
vendor/plugins/action_tracker/test/action_tracker_test.rb
... | ... | @@ -54,12 +54,11 @@ ActionController::Routing::Routes.draw { |map| map.resources :things, :collectio |
54 | 54 | class ActionTrackerTest < ActiveSupport::TestCase |
55 | 55 | |
56 | 56 | def setup |
57 | + @controller = ThingsController.new | |
58 | + | |
57 | 59 | ActionTrackerConfig.current_user = proc{ SomeModel.first || SomeModel.create! } |
58 | 60 | ActionTracker::Record.delete_all |
59 | 61 | ActionTrackerConfig.verbs = { :some_verb => { :description => "Did something" } } |
60 | - @request = ActionController::TestRequest.new | |
61 | - @response = ActionController::TestResponse.new | |
62 | - @controller = ThingsController.new | |
63 | 62 | end |
64 | 63 | |
65 | 64 | def test_index | ... | ... |