Commit 45b484729bb6aa46e4902e0deadb2df9b480eaa1
Exists in
master
and in
29 other branches
Merge commit 'refs/merge-requests/248' of git://gitorious.org/noosfero/noosfero …
…into merge-requests/248 Conflicts: app/models/person.rb app/views/catalog/index.rhtml public/stylesheets/application.css test/functional/catalog_controller_test.rb
Showing
223 changed files
with
74020 additions
and
62087 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 223 files displayed.
app/controllers/admin/admin_panel_controller.rb
@@ -8,6 +8,9 @@ class AdminPanelController < AdminController | @@ -8,6 +8,9 @@ class AdminPanelController < AdminController | ||
8 | 8 | ||
9 | def site_info | 9 | def site_info |
10 | if request.post? | 10 | if request.post? |
11 | + if params[:environment][:languages] | ||
12 | + params[:environment][:languages] = params[:environment][:languages].map {|lang, value| lang if value=='true'}.compact | ||
13 | + end | ||
11 | if @environment.update_attributes(params[:environment]) | 14 | if @environment.update_attributes(params[:environment]) |
12 | session[:notice] = _('Environment settings updated') | 15 | session[:notice] = _('Environment settings updated') |
13 | redirect_to :action => 'index' | 16 | redirect_to :action => 'index' |
app/controllers/application_controller.rb
@@ -42,9 +42,9 @@ class ApplicationController < ActionController::Base | @@ -42,9 +42,9 @@ class ApplicationController < ActionController::Base | ||
42 | 42 | ||
43 | before_filter :set_locale | 43 | before_filter :set_locale |
44 | def set_locale | 44 | def set_locale |
45 | - FastGettext.available_locales = Noosfero.available_locales | ||
46 | - FastGettext.default_locale = Noosfero.default_locale | ||
47 | - FastGettext.locale = (params[:lang] || session[:lang] || Noosfero.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en') | 45 | + FastGettext.available_locales = environment.available_locales |
46 | + FastGettext.default_locale = environment.default_locale | ||
47 | + FastGettext.locale = (params[:lang] || session[:lang] || environment.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en') | ||
48 | I18n.locale = FastGettext.locale | 48 | I18n.locale = FastGettext.locale |
49 | if params[:lang] | 49 | if params[:lang] |
50 | session[:lang] = params[:lang] | 50 | session[:lang] = params[:lang] |
app/controllers/box_organizer_controller.rb
@@ -68,7 +68,8 @@ class BoxOrganizerController < ApplicationController | @@ -68,7 +68,8 @@ class BoxOrganizerController < ApplicationController | ||
68 | raise ArgumentError.new("Type %s is not allowed. Go away." % type) | 68 | raise ArgumentError.new("Type %s is not allowed. Go away." % type) |
69 | end | 69 | end |
70 | else | 70 | else |
71 | - @block_types = available_blocks | 71 | + @center_block_types = Box.acceptable_center_blocks & available_blocks |
72 | + @side_block_types = Box.acceptable_side_blocks & available_blocks | ||
72 | @boxes = boxes_holder.boxes | 73 | @boxes = boxes_holder.boxes |
73 | render :action => 'add_block', :layout => false | 74 | render :action => 'add_block', :layout => false |
74 | end | 75 | end |
app/controllers/my_profile/cms_controller.rb
@@ -116,11 +116,11 @@ class CmsController < MyProfileController | @@ -116,11 +116,11 @@ class CmsController < MyProfileController | ||
116 | @parent_id = parent.id | 116 | @parent_id = parent.id |
117 | end | 117 | end |
118 | 118 | ||
119 | - translations if @article.translatable? | ||
120 | - | ||
121 | @article.profile = profile | 119 | @article.profile = profile |
122 | @article.last_changed_by = user | 120 | @article.last_changed_by = user |
123 | 121 | ||
122 | + translations if @article.translatable? | ||
123 | + | ||
124 | continue = params[:continue] | 124 | continue = params[:continue] |
125 | if request.post? | 125 | if request.post? |
126 | if @article.save | 126 | if @article.save |
@@ -149,7 +149,6 @@ class CmsController < MyProfileController | @@ -149,7 +149,6 @@ class CmsController < MyProfileController | ||
149 | @uploaded_files = [] | 149 | @uploaded_files = [] |
150 | @article = @parent = check_parent(params[:parent_id]) | 150 | @article = @parent = check_parent(params[:parent_id]) |
151 | @target = @parent ? ('/%s/%s' % [profile.identifier, @parent.full_name]) : '/%s' % profile.identifier | 151 | @target = @parent ? ('/%s/%s' % [profile.identifier, @parent.full_name]) : '/%s' % profile.identifier |
152 | - @folders = Folder.find(:all, :conditions => { :profile_id => profile }) | ||
153 | if @article | 152 | if @article |
154 | record_coming | 153 | record_coming |
155 | end | 154 | end |
@@ -345,7 +344,7 @@ class CmsController < MyProfileController | @@ -345,7 +344,7 @@ class CmsController < MyProfileController | ||
345 | end | 344 | end |
346 | 345 | ||
347 | def translations | 346 | def translations |
348 | - @locales = Noosfero.locales.invert.reject { |name, lang| !@article.possible_translations.include?(lang) } | 347 | + @locales = environment.locales.invert.reject { |name, lang| !@article.possible_translations.include?(lang) } |
349 | @selected_locale = @article.language || FastGettext.locale | 348 | @selected_locale = @article.language || FastGettext.locale |
350 | end | 349 | end |
351 | 350 |
app/controllers/my_profile/profile_design_controller.rb
@@ -5,7 +5,7 @@ class ProfileDesignController < BoxOrganizerController | @@ -5,7 +5,7 @@ class ProfileDesignController < BoxOrganizerController | ||
5 | protect 'edit_profile_design', :profile | 5 | protect 'edit_profile_design', :profile |
6 | 6 | ||
7 | def available_blocks | 7 | def available_blocks |
8 | - blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock ] | 8 | + blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] |
9 | 9 | ||
10 | # blocks exclusive for organizations | 10 | # blocks exclusive for organizations |
11 | if profile.has_members? | 11 | if profile.has_members? |
app/controllers/my_profile/profile_editor_controller.rb
@@ -14,6 +14,7 @@ class ProfileEditorController < MyProfileController | @@ -14,6 +14,7 @@ class ProfileEditorController < MyProfileController | ||
14 | @profile_data = profile | 14 | @profile_data = profile |
15 | @possible_domains = profile.possible_domains | 15 | @possible_domains = profile.possible_domains |
16 | if request.post? | 16 | if request.post? |
17 | + params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash) | ||
17 | begin | 18 | begin |
18 | Profile.transaction do | 19 | Profile.transaction do |
19 | Image.transaction do | 20 | Image.transaction do |
app/controllers/my_profile/profile_members_controller.rb
@@ -156,18 +156,4 @@ class ProfileMembersController < MyProfileController | @@ -156,18 +156,4 @@ class ProfileMembersController < MyProfileController | ||
156 | end | 156 | end |
157 | end | 157 | end |
158 | 158 | ||
159 | - def send_mail | ||
160 | - @mailing = profile.mailings.build(params[:mailing]) | ||
161 | - if request.post? | ||
162 | - @mailing.locale = locale | ||
163 | - @mailing.person = user | ||
164 | - if @mailing.save | ||
165 | - session[:notice] = _('The e-mails are being sent') | ||
166 | - redirect_to :action => 'index' | ||
167 | - else | ||
168 | - session[:notice] = _('Could not create the e-mail') | ||
169 | - end | ||
170 | - end | ||
171 | - end | ||
172 | - | ||
173 | end | 159 | end |
app/controllers/public/account_controller.rb
@@ -25,11 +25,13 @@ class AccountController < ApplicationController | @@ -25,11 +25,13 @@ class AccountController < ApplicationController | ||
25 | 25 | ||
26 | # action to perform login to the application | 26 | # action to perform login to the application |
27 | def login | 27 | def login |
28 | - @user = User.new | ||
29 | - @person = @user.build_person | ||
30 | store_location(request.referer) unless session[:return_to] | 28 | store_location(request.referer) unless session[:return_to] |
31 | return unless request.post? | 29 | return unless request.post? |
32 | - self.current_user = User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user] | 30 | + |
31 | + self.current_user = plugins_alternative_authentication | ||
32 | + | ||
33 | + self.current_user ||= User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user] | ||
34 | + | ||
33 | if logged_in? | 35 | if logged_in? |
34 | if params[:remember_me] == "1" | 36 | if params[:remember_me] == "1" |
35 | self.current_user.remember_me | 37 | self.current_user.remember_me |
@@ -41,7 +43,6 @@ class AccountController < ApplicationController | @@ -41,7 +43,6 @@ class AccountController < ApplicationController | ||
41 | end | 43 | end |
42 | else | 44 | else |
43 | session[:notice] = _('Incorrect username or password') if redirect? | 45 | session[:notice] = _('Incorrect username or password') if redirect? |
44 | - redirect_to :back if redirect? | ||
45 | end | 46 | end |
46 | end | 47 | end |
47 | 48 | ||
@@ -56,6 +57,11 @@ class AccountController < ApplicationController | @@ -56,6 +57,11 @@ class AccountController < ApplicationController | ||
56 | 57 | ||
57 | # action to register an user to the application | 58 | # action to register an user to the application |
58 | def signup | 59 | def signup |
60 | + if @plugins.dispatch(:allow_user_registration).include?(false) | ||
61 | + redirect_back_or_default(:controller => 'home') | ||
62 | + session[:notice] = _("This environment doesn't allow user registration.") | ||
63 | + end | ||
64 | + | ||
59 | @invitation_code = params[:invitation_code] | 65 | @invitation_code = params[:invitation_code] |
60 | begin | 66 | begin |
61 | if params[:user] | 67 | if params[:user] |
@@ -125,6 +131,10 @@ class AccountController < ApplicationController | @@ -125,6 +131,10 @@ class AccountController < ApplicationController | ||
125 | # | 131 | # |
126 | # Posts back. | 132 | # Posts back. |
127 | def forgot_password | 133 | def forgot_password |
134 | + if @plugins.dispatch(:allow_password_recovery).include?(false) | ||
135 | + redirect_back_or_default(:controller => 'home') | ||
136 | + session[:notice] = _("This environment doesn't allow password recovery.") | ||
137 | + end | ||
128 | @change_password = ChangePassword.new(params[:change_password]) | 138 | @change_password = ChangePassword.new(params[:change_password]) |
129 | 139 | ||
130 | if request.post? | 140 | if request.post? |
@@ -303,10 +313,27 @@ class AccountController < ApplicationController | @@ -303,10 +313,27 @@ class AccountController < ApplicationController | ||
303 | end | 313 | end |
304 | 314 | ||
305 | def go_to_initial_page | 315 | def go_to_initial_page |
306 | - if environment == current_user.environment | ||
307 | - redirect_back_or_default(user.admin_url) | 316 | + if environment.enabled?('allow_change_of_redirection_after_login') |
317 | + case user.preferred_login_redirection | ||
318 | + when 'keep_on_same_page' | ||
319 | + redirect_back_or_default(user.admin_url) | ||
320 | + when 'site_homepage' | ||
321 | + redirect_to :controller => :home | ||
322 | + when 'user_profile_page' | ||
323 | + redirect_to user.public_profile_url | ||
324 | + when 'user_homepage' | ||
325 | + redirect_to user.url | ||
326 | + when 'user_control_panel' | ||
327 | + redirect_to user.admin_url | ||
328 | + else | ||
329 | + redirect_back_or_default(user.admin_url) | ||
330 | + end | ||
308 | else | 331 | else |
309 | - redirect_back_or_default(:controller => 'home') | 332 | + if environment == current_user.environment |
333 | + redirect_back_or_default(user.admin_url) | ||
334 | + else | ||
335 | + redirect_back_or_default(:controller => 'home') | ||
336 | + end | ||
310 | end | 337 | end |
311 | end | 338 | end |
312 | 339 | ||
@@ -316,4 +343,13 @@ class AccountController < ApplicationController | @@ -316,4 +343,13 @@ class AccountController < ApplicationController | ||
316 | end | 343 | end |
317 | end | 344 | end |
318 | 345 | ||
346 | + def plugins_alternative_authentication | ||
347 | + user = nil | ||
348 | + @plugins.each do |plugin| | ||
349 | + user = plugin.alternative_authentication | ||
350 | + break unless user.nil? | ||
351 | + end | ||
352 | + user | ||
353 | + end | ||
354 | + | ||
319 | end | 355 | end |
app/controllers/public/not_found_controller.rb
app/controllers/public/profile_controller.rb
@@ -2,11 +2,13 @@ class ProfileController < PublicController | @@ -2,11 +2,13 @@ class ProfileController < PublicController | ||
2 | 2 | ||
3 | needs_profile | 3 | needs_profile |
4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] | 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] |
5 | - before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse] | ||
6 | - before_filter :login_required, :only => [:add, :join, :join_not_logged, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity] | 5 | + before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse, :send_mail] |
6 | + before_filter :login_required, :only => [:add, :join, :join_not_logged, :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] | ||
7 | 7 | ||
8 | helper TagsHelper | 8 | helper TagsHelper |
9 | 9 | ||
10 | + protect 'send_mail_to_members', :profile, :only => [:send_mail] | ||
11 | + | ||
10 | def index | 12 | def index |
11 | @network_activities = !@profile.is_a?(Person) ? @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) : [] | 13 | @network_activities = !@profile.is_a?(Person) ? @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) : [] |
12 | if logged_in? && current_person.follows?(@profile) | 14 | if logged_in? && current_person.follows?(@profile) |
@@ -49,36 +51,36 @@ class ProfileController < PublicController | @@ -49,36 +51,36 @@ class ProfileController < PublicController | ||
49 | 51 | ||
50 | def communities | 52 | def communities |
51 | if is_cache_expired?(profile.communities_cache_key(params)) | 53 | if is_cache_expired?(profile.communities_cache_key(params)) |
52 | - @communities = profile.communities.paginate(:per_page => per_page, :page => params[:npage]) | 54 | + @communities = profile.communities.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage]) |
53 | end | 55 | end |
54 | end | 56 | end |
55 | 57 | ||
56 | def enterprises | 58 | def enterprises |
57 | - @enterprises = profile.enterprises | 59 | + @enterprises = profile.enterprises.includes(relations_to_include) |
58 | end | 60 | end |
59 | 61 | ||
60 | def friends | 62 | def friends |
61 | if is_cache_expired?(profile.friends_cache_key(params)) | 63 | if is_cache_expired?(profile.friends_cache_key(params)) |
62 | - @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) | 64 | + @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage]) |
63 | end | 65 | end |
64 | end | 66 | end |
65 | 67 | ||
66 | def members | 68 | def members |
67 | if is_cache_expired?(profile.members_cache_key(params)) | 69 | if is_cache_expired?(profile.members_cache_key(params)) |
68 | - @members = profile.members.paginate(:per_page => members_per_page, :page => params[:npage]) | 70 | + @members = profile.members.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage]) |
69 | end | 71 | end |
70 | end | 72 | end |
71 | 73 | ||
72 | def fans | 74 | def fans |
73 | - @fans = profile.fans | 75 | + @fans = profile.fans.includes(relations_to_include) |
74 | end | 76 | end |
75 | 77 | ||
76 | def favorite_enterprises | 78 | def favorite_enterprises |
77 | - @favorite_enterprises = profile.favorite_enterprises | 79 | + @favorite_enterprises = profile.favorite_enterprises.includes(relations_to_include) |
78 | end | 80 | end |
79 | 81 | ||
80 | def sitemap | 82 | def sitemap |
81 | - @articles = profile.top_level_articles | 83 | + @articles = profile.top_level_articles.includes([:profile, :parent]) |
82 | end | 84 | end |
83 | 85 | ||
84 | def join | 86 | def join |
@@ -327,6 +329,20 @@ class ProfileController < PublicController | @@ -327,6 +329,20 @@ class ProfileController < PublicController | ||
327 | end | 329 | end |
328 | end | 330 | end |
329 | 331 | ||
332 | + def send_mail | ||
333 | + @mailing = profile.mailings.build(params[:mailing]) | ||
334 | + if request.post? | ||
335 | + @mailing.locale = locale | ||
336 | + @mailing.person = user | ||
337 | + if @mailing.save | ||
338 | + session[:notice] = _('The e-mails are being sent') | ||
339 | + redirect_to_previous_location | ||
340 | + else | ||
341 | + session[:notice] = _('Could not create the e-mail') | ||
342 | + end | ||
343 | + end | ||
344 | + end | ||
345 | + | ||
330 | protected | 346 | protected |
331 | 347 | ||
332 | def check_access_to_profile | 348 | def check_access_to_profile |
@@ -378,4 +394,8 @@ class ProfileController < PublicController | @@ -378,4 +394,8 @@ class ProfileController < PublicController | ||
378 | @can_edit_profile ||= user && user.has_permission?('edit_profile', profile) | 394 | @can_edit_profile ||= user && user.has_permission?('edit_profile', profile) |
379 | end | 395 | end |
380 | helper_method :can_edit_profile | 396 | helper_method :can_edit_profile |
397 | + | ||
398 | + def relations_to_include | ||
399 | + [:image, :domains, :preferred_domain, :environment] | ||
400 | + end | ||
381 | end | 401 | end |
app/controllers/public/search_controller.rb
@@ -46,7 +46,7 @@ class SearchController < PublicController | @@ -46,7 +46,7 @@ class SearchController < PublicController | ||
46 | if !@empty_query | 46 | if !@empty_query |
47 | full_text_search ['public:true'] | 47 | full_text_search ['public:true'] |
48 | else | 48 | else |
49 | - @results[@asset] = @environment.people.visible.send(@filter).paginate(paginate_options) | 49 | + @results[@asset] = visible_profiles(Person).send(@filter).paginate(paginate_options) |
50 | end | 50 | end |
51 | end | 51 | end |
52 | 52 | ||
@@ -76,7 +76,7 @@ class SearchController < PublicController | @@ -76,7 +76,7 @@ class SearchController < PublicController | ||
76 | full_text_search ['public:true'] | 76 | full_text_search ['public:true'] |
77 | else | 77 | else |
78 | @filter_title = _('Enterprises from network') | 78 | @filter_title = _('Enterprises from network') |
79 | - @results[@asset] = @environment.enterprises.visible.paginate(paginate_options) | 79 | + @results[@asset] = visible_profiles(Enterprise, [{:products => :product_category}]).paginate(paginate_options) |
80 | end | 80 | end |
81 | end | 81 | end |
82 | 82 | ||
@@ -84,7 +84,7 @@ class SearchController < PublicController | @@ -84,7 +84,7 @@ class SearchController < PublicController | ||
84 | if !@empty_query | 84 | if !@empty_query |
85 | full_text_search ['public:true'] | 85 | full_text_search ['public:true'] |
86 | else | 86 | else |
87 | - @results[@asset] = @environment.communities.visible.send(@filter).paginate(paginate_options) | 87 | + @results[@asset] = visible_profiles(Community).send(@filter).paginate(paginate_options) |
88 | end | 88 | end |
89 | end | 89 | end |
90 | 90 | ||
@@ -310,4 +310,12 @@ class SearchController < PublicController | @@ -310,4 +310,12 @@ class SearchController < PublicController | ||
310 | @all_facets = ret[:all_facets] | 310 | @all_facets = ret[:all_facets] |
311 | end | 311 | end |
312 | 312 | ||
313 | + private | ||
314 | + | ||
315 | + def visible_profiles(klass, *extra_relations) | ||
316 | + relations = [:image, :domains, :environment, :preferred_domain] | ||
317 | + relations += extra_relations | ||
318 | + @environment.send(klass.name.underscore.pluralize).visible.includes(relations) | ||
319 | + end | ||
320 | + | ||
313 | end | 321 | end |
app/helpers/application_helper.rb
@@ -265,9 +265,9 @@ module ApplicationHelper | @@ -265,9 +265,9 @@ module ApplicationHelper | ||
265 | 265 | ||
266 | VIEW_EXTENSIONS = %w[.rhtml .html.erb] | 266 | VIEW_EXTENSIONS = %w[.rhtml .html.erb] |
267 | 267 | ||
268 | - def partial_for_class_in_view_path(klass, view_path) | 268 | + def partial_for_class_in_view_path(klass, view_path, suffix = nil) |
269 | return nil if klass.nil? | 269 | return nil if klass.nil? |
270 | - name = klass.name.underscore | 270 | + name = [klass.name.underscore, suffix].compact.map(&:to_s).join('_') |
271 | 271 | ||
272 | search_name = String.new(name) | 272 | search_name = String.new(name) |
273 | if search_name.include?("/") | 273 | if search_name.include?("/") |
@@ -282,31 +282,20 @@ module ApplicationHelper | @@ -282,31 +282,20 @@ module ApplicationHelper | ||
282 | return name if File.exists?(File.join(path)) | 282 | return name if File.exists?(File.join(path)) |
283 | end | 283 | end |
284 | 284 | ||
285 | - partial_for_class_in_view_path(klass.superclass, view_path) | 285 | + partial_for_class_in_view_path(klass.superclass, view_path, suffix) |
286 | end | 286 | end |
287 | 287 | ||
288 | - def partial_for_class(klass) | 288 | + def partial_for_class(klass, suffix=nil) |
289 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? | 289 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? |
290 | name = klass.name.underscore | 290 | name = klass.name.underscore |
291 | @controller.view_paths.each do |view_path| | 291 | @controller.view_paths.each do |view_path| |
292 | - partial = partial_for_class_in_view_path(klass, view_path) | 292 | + partial = partial_for_class_in_view_path(klass, view_path, suffix) |
293 | return partial if partial | 293 | return partial if partial |
294 | end | 294 | end |
295 | 295 | ||
296 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' | 296 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' |
297 | end | 297 | end |
298 | 298 | ||
299 | - def partial_for_task_class(klass, action) | ||
300 | - raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? | ||
301 | - | ||
302 | - name = "#{klass.name.underscore}_#{action.to_s}" | ||
303 | - VIEW_EXTENSIONS.each do |ext| | ||
304 | - return name if File.exists?(File.join(RAILS_ROOT, 'app', 'views', params[:controller], '_'+name+ext)) | ||
305 | - end | ||
306 | - | ||
307 | - partial_for_task_class(klass.superclass, action) | ||
308 | - end | ||
309 | - | ||
310 | def view_for_profile_actions(klass) | 299 | def view_for_profile_actions(klass) |
311 | raise ArgumentError, 'No profile actions view for this class.' if klass.nil? | 300 | raise ArgumentError, 'No profile actions view for this class.' if klass.nil? |
312 | 301 | ||
@@ -664,19 +653,6 @@ module ApplicationHelper | @@ -664,19 +653,6 @@ module ApplicationHelper | ||
664 | content_tag('div', result) | 653 | content_tag('div', result) |
665 | end | 654 | end |
666 | 655 | ||
667 | - def select_folder(label, object, method, collection, html_options = {}, js_options = {}) | ||
668 | - root = profile ? profile.identifier : _("root") | ||
669 | - labelled_form_field(label, select(object, method, | ||
670 | - collection.map {|f| [ root + '/' + f.full_name, f.id ]}, | ||
671 | - {:include_blank => root}, html_options.merge(js_options))) | ||
672 | - end | ||
673 | - | ||
674 | - def select_profile_folder(label, object, method, profile, html_options = {}, js_options = {}) | ||
675 | - labelled_form_field(label, select(object, method, | ||
676 | - profile.folders.map {|f| [ profile.identifier + '/' + f.full_name, f.id ]}, | ||
677 | - {:include_blank => profile.identifier}, html_options.merge(js_options))) | ||
678 | - end | ||
679 | - | ||
680 | def theme_option(opt = nil) | 656 | def theme_option(opt = nil) |
681 | conf = RAILS_ROOT.to_s() + | 657 | conf = RAILS_ROOT.to_s() + |
682 | '/public' + theme_path + | 658 | '/public' + theme_path + |
@@ -877,7 +853,7 @@ module ApplicationHelper | @@ -877,7 +853,7 @@ module ApplicationHelper | ||
877 | end | 853 | end |
878 | else | 854 | else |
879 | if profile.active_fields.include?(name) | 855 | if profile.active_fields.include?(name) |
880 | - result = field_html | 856 | + result = content_tag('div', field_html + profile_field_privacy_selector(profile, name), :class => 'field-with-privacy-selector') |
881 | end | 857 | end |
882 | end | 858 | end |
883 | 859 | ||
@@ -892,6 +868,11 @@ module ApplicationHelper | @@ -892,6 +868,11 @@ module ApplicationHelper | ||
892 | result | 868 | result |
893 | end | 869 | end |
894 | 870 | ||
871 | + def profile_field_privacy_selector(profile, name) | ||
872 | + return '' unless profile.public? | ||
873 | + content_tag('div', labelled_check_box(_('Public'), 'profile_data[fields_privacy]['+name+']', 'public', profile.public_fields.include?(name)), :class => 'field-privacy-selector') | ||
874 | + end | ||
875 | + | ||
895 | def template_stylesheet_path | 876 | def template_stylesheet_path |
896 | if profile.nil? | 877 | if profile.nil? |
897 | "/designs/templates/#{environment.layout_template}/stylesheets/style.css" | 878 | "/designs/templates/#{environment.layout_template}/stylesheets/style.css" |
app/helpers/article_helper.rb
@@ -2,14 +2,19 @@ module ArticleHelper | @@ -2,14 +2,19 @@ module ArticleHelper | ||
2 | 2 | ||
3 | def custom_options_for_article(article) | 3 | def custom_options_for_article(article) |
4 | @article = article | 4 | @article = article |
5 | + content_tag('h4', _('Visibility')) + | ||
6 | + content_tag('div', | ||
7 | + content_tag('div', | ||
8 | + radio_button(:article, :published, true) + | ||
9 | + content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true') | ||
10 | + ) + | ||
11 | + content_tag('div', | ||
12 | + radio_button(:article, :published, false) + | ||
13 | + content_tag('label', _('Private'), :for => 'article_published_false') | ||
14 | + ) | ||
15 | + ) + | ||
5 | content_tag('h4', _('Options')) + | 16 | content_tag('h4', _('Options')) + |
6 | content_tag('div', | 17 | content_tag('div', |
7 | - content_tag( | ||
8 | - 'div', | ||
9 | - check_box(:article, :published) + | ||
10 | - content_tag('label', _('This article must be published (visible to other people)'), :for => 'article_published') | ||
11 | - ) + | ||
12 | - | ||
13 | (article.profile.has_members? ? | 18 | (article.profile.has_members? ? |
14 | content_tag( | 19 | content_tag( |
15 | 'div', | 20 | 'div', |
app/helpers/boxes_helper.rb
@@ -66,7 +66,7 @@ module BoxesHelper | @@ -66,7 +66,7 @@ module BoxesHelper | ||
66 | 66 | ||
67 | def display_box_content(box, main_content) | 67 | def display_box_content(box, main_content) |
68 | context = { :article => @page, :request_path => request.path, :locale => locale } | 68 | context = { :article => @page, :request_path => request.path, :locale => locale } |
69 | - box_decorator.select_blocks(box.blocks, context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box) | 69 | + box_decorator.select_blocks(box.blocks.includes(:box), context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box) |
70 | end | 70 | end |
71 | 71 | ||
72 | def select_blocks(arr, context) | 72 | def select_blocks(arr, context) |
@@ -162,9 +162,6 @@ module BoxesHelper | @@ -162,9 +162,6 @@ module BoxesHelper | ||
162 | # | 162 | # |
163 | # +box+ is always needed | 163 | # +box+ is always needed |
164 | def block_target(box, block = nil) | 164 | def block_target(box, block = nil) |
165 | - # FIXME hardcoded | ||
166 | - return '' if box.position == 1 | ||
167 | - | ||
168 | id = | 165 | id = |
169 | if block.nil? | 166 | if block.nil? |
170 | "end-of-box-#{box.id}" | 167 | "end-of-box-#{box.id}" |
@@ -172,14 +169,11 @@ module BoxesHelper | @@ -172,14 +169,11 @@ module BoxesHelper | ||
172 | "before-block-#{block.id}" | 169 | "before-block-#{block.id}" |
173 | end | 170 | end |
174 | 171 | ||
175 | - content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => 'block', :hoverclass => 'block-target-hover') | 172 | + content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') |
176 | end | 173 | end |
177 | 174 | ||
178 | # makes the given block draggable so it can be moved away. | 175 | # makes the given block draggable so it can be moved away. |
179 | def block_handle(block) | 176 | def block_handle(block) |
180 | - # FIXME hardcoded | ||
181 | - return '' if block.box.position == 1 | ||
182 | - | ||
183 | draggable_element("block-#{block.id}", :revert => true) | 177 | draggable_element("block-#{block.id}", :revert => true) |
184 | end | 178 | end |
185 | 179 | ||
@@ -211,7 +205,7 @@ module BoxesHelper | @@ -211,7 +205,7 @@ module BoxesHelper | ||
211 | end | 205 | end |
212 | 206 | ||
213 | if block.editable? | 207 | if block.editable? |
214 | - buttons << lightbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | 208 | + buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) |
215 | end | 209 | end |
216 | 210 | ||
217 | if !block.main? | 211 | if !block.main? |
app/helpers/colorbox_helper.rb
@@ -8,6 +8,10 @@ module ColorboxHelper | @@ -8,6 +8,10 @@ module ColorboxHelper | ||
8 | button(type, label, url, colorbox_options(options)) | 8 | button(type, label, url, colorbox_options(options)) |
9 | end | 9 | end |
10 | 10 | ||
11 | + def colorbox_icon_button(type, label, url, options = {}) | ||
12 | + icon_button(type, label, url, colorbox_options(options)) | ||
13 | + end | ||
14 | + | ||
11 | # options must be an HTML options hash as passed to link_to etc. | 15 | # options must be an HTML options hash as passed to link_to etc. |
12 | # | 16 | # |
13 | # returns a new hash with colorbox class added. Keeps existing classes. | 17 | # returns a new hash with colorbox class added. Keeps existing classes. |
app/helpers/content_viewer_helper.rb
@@ -42,7 +42,7 @@ module ContentViewerHelper | @@ -42,7 +42,7 @@ module ContentViewerHelper | ||
42 | def article_translations(article) | 42 | def article_translations(article) |
43 | unless article.native_translation.translations.empty? | 43 | unless article.native_translation.translations.empty? |
44 | links = (article.native_translation.translations + [article.native_translation]).map do |translation| | 44 | links = (article.native_translation.translations + [article.native_translation]).map do |translation| |
45 | - { Noosfero.locales[translation.language] => { :href => url_for(translation.url) } } | 45 | + { article.environment.locales[translation.language] => { :href => url_for(translation.url) } } |
46 | end | 46 | end |
47 | content_tag(:div, link_to(_('Translations'), '#', | 47 | content_tag(:div, link_to(_('Translations'), '#', |
48 | :onclick => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false", | 48 | :onclick => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false", |
app/helpers/display_helper.rb
@@ -8,6 +8,14 @@ module DisplayHelper | @@ -8,6 +8,14 @@ module DisplayHelper | ||
8 | opts | 8 | opts |
9 | end | 9 | end |
10 | 10 | ||
11 | + def themed_path(file) | ||
12 | + if File.exists?(File.join(Rails.root, 'public', theme_path, file)) | ||
13 | + File.join(theme_path, file) | ||
14 | + else | ||
15 | + file | ||
16 | + end | ||
17 | + end | ||
18 | + | ||
11 | def image_link_to_product(product, opts={}) | 19 | def image_link_to_product(product, opts={}) |
12 | return _('No product') unless product | 20 | return _('No product') unless product |
13 | target = product_path(product) | 21 | target = product_path(product) |
app/helpers/folder_helper.rb
@@ -58,18 +58,18 @@ module FolderHelper | @@ -58,18 +58,18 @@ module FolderHelper | ||
58 | 58 | ||
59 | def custom_options_for_article(article) | 59 | def custom_options_for_article(article) |
60 | @article = article | 60 | @article = article |
61 | - content_tag('h4', _('Options')) + | 61 | + content_tag('h4', _('Visibility')) + |
62 | + content_tag('div', | ||
63 | + content_tag('div', | ||
64 | + radio_button(:article, :published, true) + | ||
65 | + content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true') | ||
66 | + ) + | ||
67 | + content_tag('div', | ||
68 | + radio_button(:article, :published, false) + | ||
69 | + content_tag('label', _('Private'), :for => 'article_published_false') | ||
70 | + ) | ||
71 | + ) + | ||
62 | content_tag('div', | 72 | content_tag('div', |
63 | - content_tag( | ||
64 | - 'div', | ||
65 | - check_box(:article, :published) + | ||
66 | - content_tag('label', _('This article must be published (visible to other people)'), :for => 'article_published') | ||
67 | - ) + (article.can_display_hits? ? | ||
68 | - content_tag( | ||
69 | - 'div', | ||
70 | - check_box(:article, :display_hits) + | ||
71 | - content_tag('label', _('I want this article to display the number of hits it received'), :for => 'article_display_hits') | ||
72 | - ) : '') + | ||
73 | hidden_field_tag('article[accept_comments]', 0) | 73 | hidden_field_tag('article[accept_comments]', 0) |
74 | ) | 74 | ) |
75 | end | 75 | end |
app/helpers/forms_helper.rb
@@ -123,6 +123,170 @@ module FormsHelper | @@ -123,6 +123,170 @@ module FormsHelper | ||
123 | options_for_select.join("\n") | 123 | options_for_select.join("\n") |
124 | end | 124 | end |
125 | 125 | ||
126 | + def balanced_table(items, per_row=3) | ||
127 | + items = items.map {|item| content_tag('td', item, :style => 'border: none; background: transparent;')} | ||
128 | + rows = [] | ||
129 | + row = [] | ||
130 | + counter = 0 | ||
131 | + items.each do |item| | ||
132 | + counter += 1 | ||
133 | + row << item | ||
134 | + if counter % per_row == 0 | ||
135 | + rows << content_tag('tr', row.join("\n")) | ||
136 | + counter = 0 | ||
137 | + row = [] | ||
138 | + end | ||
139 | + end | ||
140 | + rows << content_tag('tr', row.join("\n")) | ||
141 | + | ||
142 | + content_tag('table',rows.join("\n")) | ||
143 | + end | ||
144 | + | ||
145 | + def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) | ||
146 | + datepicker_options[:disabled] ||= false | ||
147 | + datepicker_options[:alt_field] ||= '' | ||
148 | + datepicker_options[:alt_format] ||= '' | ||
149 | + datepicker_options[:append_text] ||= '' | ||
150 | + datepicker_options[:auto_size] ||= false | ||
151 | + datepicker_options[:button_image] ||= '' | ||
152 | + datepicker_options[:button_image_only] ||= false | ||
153 | + datepicker_options[:button_text] ||= '...' | ||
154 | + datepicker_options[:calculate_week] ||= 'jQuery.datepicker.iso8601Week' | ||
155 | + datepicker_options[:change_month] ||= false | ||
156 | + datepicker_options[:change_year] ||= false | ||
157 | + datepicker_options[:close_text] ||= _('Done') | ||
158 | + datepicker_options[:constrain_input] ||= true | ||
159 | + datepicker_options[:current_text] ||= _('Today') | ||
160 | + datepicker_options[:date_format] ||= 'mm/dd/yy' | ||
161 | + datepicker_options[:day_names] ||= [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')] | ||
162 | + datepicker_options[:day_names_min] ||= [_('Su'), _('Mo'), _('Tu'), _('We'), _('Th'), _('Fr'), _('Sa')] | ||
163 | + datepicker_options[:day_names_short] ||= [_('Sun'), _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat')] | ||
164 | + datepicker_options[:default_date] ||= nil | ||
165 | + datepicker_options[:duration] ||= 'normal' | ||
166 | + datepicker_options[:first_day] ||= 0 | ||
167 | + datepicker_options[:goto_current] ||= false | ||
168 | + datepicker_options[:hide_if_no_prev_next] ||= false | ||
169 | + datepicker_options[:is_rtl] ||= false | ||
170 | + datepicker_options[:max_date] ||= nil | ||
171 | + datepicker_options[:min_date] ||= nil | ||
172 | + datepicker_options[:month_names] ||= [_('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July'), _('August'), _('September'), _('October'), _('November'), _('December')] | ||
173 | + datepicker_options[:month_names_short] ||= [_('Jan'), _('Feb'), _('Mar'), _('Apr'), _('May'), _('Jun'), _('Jul'), _('Aug'), _('Sep'), _('Oct'), _('Nov'), _('Dec')] | ||
174 | + datepicker_options[:navigation_as_date_format] ||= false | ||
175 | + datepicker_options[:next_text] ||= _('Next') | ||
176 | + datepicker_options[:number_of_months] ||= 1 | ||
177 | + datepicker_options[:prev_text] ||= _('Prev') | ||
178 | + datepicker_options[:select_other_months] ||= false | ||
179 | + datepicker_options[:short_year_cutoff] ||= '+10' | ||
180 | + datepicker_options[:show_button_panel] ||= false | ||
181 | + datepicker_options[:show_current_at_pos] ||= 0 | ||
182 | + datepicker_options[:show_month_after_year] ||= false | ||
183 | + datepicker_options[:show_on] ||= 'focus' | ||
184 | + datepicker_options[:show_options] ||= {} | ||
185 | + datepicker_options[:show_other_months] ||= false | ||
186 | + datepicker_options[:show_week] ||= false | ||
187 | + datepicker_options[:step_months] ||= 1 | ||
188 | + datepicker_options[:week_header] ||= _('Wk') | ||
189 | + datepicker_options[:year_range] ||= 'c-10:c+10' | ||
190 | + datepicker_options[:year_suffix] ||= '' | ||
191 | + | ||
192 | + element_id = html_options[:id] || 'datepicker-date' | ||
193 | + value = value.strftime(format) if value.present? | ||
194 | + method = datepicker_options[:time] ? 'datetimepicker' : 'datepicker' | ||
195 | + result = text_field_tag(name, value, html_options) | ||
196 | + result += | ||
197 | + " | ||
198 | + <script type='text/javascript'> | ||
199 | + jQuery('##{element_id}').#{method}({ | ||
200 | + disabled: #{datepicker_options[:disabled].to_json}, | ||
201 | + altField: #{datepicker_options[:alt_field].to_json}, | ||
202 | + altFormat: #{datepicker_options[:alt_format].to_json}, | ||
203 | + appendText: #{datepicker_options[:append_text].to_json}, | ||
204 | + autoSize: #{datepicker_options[:auto_size].to_json}, | ||
205 | + buttonImage: #{datepicker_options[:button_image].to_json}, | ||
206 | + buttonImageOnly: #{datepicker_options[:button_image_only].to_json}, | ||
207 | + buttonText: #{datepicker_options[:button_text].to_json}, | ||
208 | + calculateWeek: #{datepicker_options[:calculate_week].to_json}, | ||
209 | + changeMonth: #{datepicker_options[:change_month].to_json}, | ||
210 | + changeYear: #{datepicker_options[:change_year].to_json}, | ||
211 | + closeText: #{datepicker_options[:close_text].to_json}, | ||
212 | + constrainInput: #{datepicker_options[:constrain_input].to_json}, | ||
213 | + currentText: #{datepicker_options[:current_text].to_json}, | ||
214 | + dateFormat: #{datepicker_options[:date_format].to_json}, | ||
215 | + dayNames: #{datepicker_options[:day_names].to_json}, | ||
216 | + dayNamesMin: #{datepicker_options[:day_names_min].to_json}, | ||
217 | + dayNamesShort: #{datepicker_options[:day_names_short].to_json}, | ||
218 | + defaultDate: #{datepicker_options[:default_date].to_json}, | ||
219 | + duration: #{datepicker_options[:duration].to_json}, | ||
220 | + firstDay: #{datepicker_options[:first_day].to_json}, | ||
221 | + gotoCurrent: #{datepicker_options[:goto_current].to_json}, | ||
222 | + hideIfNoPrevNext: #{datepicker_options[:hide_if_no_prev_next].to_json}, | ||
223 | + isRTL: #{datepicker_options[:is_rtl].to_json}, | ||
224 | + maxDate: #{datepicker_options[:max_date].to_json}, | ||
225 | + minDate: #{datepicker_options[:min_date].to_json}, | ||
226 | + monthNames: #{datepicker_options[:month_names].to_json}, | ||
227 | + monthNamesShort: #{datepicker_options[:month_names_short].to_json}, | ||
228 | + navigationAsDateFormat: #{datepicker_options[:navigation_as_date_format].to_json}, | ||
229 | + nextText: #{datepicker_options[:next_text].to_json}, | ||
230 | + numberOfMonths: #{datepicker_options[:number_of_months].to_json}, | ||
231 | + prevText: #{datepicker_options[:prev_text].to_json}, | ||
232 | + selectOtherMonths: #{datepicker_options[:select_other_months].to_json}, | ||
233 | + shortYearCutoff: #{datepicker_options[:short_year_cutoff].to_json}, | ||
234 | + showButtonPanel: #{datepicker_options[:show_button_panel].to_json}, | ||
235 | + showCurrentAtPos: #{datepicker_options[:show_current_at_pos].to_json}, | ||
236 | + showMonthAfterYear: #{datepicker_options[:show_month_after_year].to_json}, | ||
237 | + showOn: #{datepicker_options[:show_on].to_json}, | ||
238 | + showOptions: #{datepicker_options[:show_options].to_json}, | ||
239 | + showOtherMonths: #{datepicker_options[:show_other_months].to_json}, | ||
240 | + showWeek: #{datepicker_options[:show_week].to_json}, | ||
241 | + stepMonths: #{datepicker_options[:step_months].to_json}, | ||
242 | + weekHeader: #{datepicker_options[:week_header].to_json}, | ||
243 | + yearRange: #{datepicker_options[:year_range].to_json}, | ||
244 | + yearSuffix: #{datepicker_options[:year_suffix].to_json} | ||
245 | + }) | ||
246 | + </script> | ||
247 | + " | ||
248 | + result | ||
249 | + end | ||
250 | + | ||
251 | + def date_range_field(from_name, to_name, from_value, to_value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) | ||
252 | + from_id = html_options[:from_id] || 'datepicker-from-date' | ||
253 | + to_id = html_options[:to_id] || 'datepicker-to-date' | ||
254 | + return _('From') +' '+ date_field(from_name, from_value, format, datepicker_options, html_options.merge({:id => from_id})) + | ||
255 | + ' ' + _('until') +' '+ date_field(to_name, to_value, format, datepicker_options, html_options.merge({:id => to_id})) | ||
256 | + end | ||
257 | + | ||
258 | + def select_folder(label_text, field_id, collection, default_value=nil, html_options = {}, js_options = {}) | ||
259 | + root = profile ? profile.identifier : _("root") | ||
260 | + labelled_form_field( | ||
261 | + label_text, | ||
262 | + select_tag( | ||
263 | + field_id, | ||
264 | + options_for_select( | ||
265 | + [[root, '']] + | ||
266 | + collection.collect {|f| [ root + '/' + f.full_name, f.id ] }, | ||
267 | + default_value | ||
268 | + ), | ||
269 | + html_options.merge(js_options) | ||
270 | + ) | ||
271 | + ) | ||
272 | + end | ||
273 | + | ||
274 | + def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}) | ||
275 | + result = labelled_form_field( | ||
276 | + label_text, | ||
277 | + select_tag( | ||
278 | + field_id, | ||
279 | + options_for_select( | ||
280 | + [[profile.identifier, '']] + | ||
281 | + profile.folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] }, | ||
282 | + default_value | ||
283 | + ), | ||
284 | + html_options.merge(js_options) | ||
285 | + ) | ||
286 | + ) | ||
287 | + return result | ||
288 | + end | ||
289 | + | ||
126 | protected | 290 | protected |
127 | def self.next_id_number | 291 | def self.next_id_number |
128 | if defined? @@id_num | 292 | if defined? @@id_num |
app/helpers/language_helper.rb
@@ -13,18 +13,19 @@ module LanguageHelper | @@ -13,18 +13,19 @@ module LanguageHelper | ||
13 | 13 | ||
14 | alias :calendar_date_select_language :tinymce_language | 14 | alias :calendar_date_select_language :tinymce_language |
15 | 15 | ||
16 | - def language_chooser(options = {}) | 16 | + def language_chooser(environment, options = {}) |
17 | + return if environment.locales.size < 2 | ||
17 | current = language | 18 | current = language |
18 | separator = options[:separator] || ' — ' | 19 | separator = options[:separator] || ' — ' |
19 | 20 | ||
20 | if options[:element] == 'dropdown' | 21 | if options[:element] == 'dropdown' |
21 | select_tag('lang', | 22 | select_tag('lang', |
22 | - options_for_select(Noosfero.locales.map{|code,name| [name, code]}, current), | 23 | + options_for_select(environment.locales.map{|code,name| [name, code]}, current), |
23 | :onchange => "document.location.href= #{url_for(params.merge(:lang => 'LANGUAGE')).inspect}.replace(/LANGUAGE/, this.value) ;", | 24 | :onchange => "document.location.href= #{url_for(params.merge(:lang => 'LANGUAGE')).inspect}.replace(/LANGUAGE/, this.value) ;", |
24 | :help => _('The language you choose here is the language used for options, buttons, etc. It does not affect the language of the content created by other users.') | 25 | :help => _('The language you choose here is the language used for options, buttons, etc. It does not affect the language of the content created by other users.') |
25 | ) | 26 | ) |
26 | else | 27 | else |
27 | - languages = Noosfero.locales.map do |code,name| | 28 | + languages = environment.locales.map do |code,name| |
28 | if code == current | 29 | if code == current |
29 | content_tag('strong', name) | 30 | content_tag('strong', name) |
30 | else | 31 | else |
app/helpers/profile_editor_helper.rb
@@ -145,4 +145,12 @@ module ProfileEditorHelper | @@ -145,4 +145,12 @@ module ProfileEditorHelper | ||
145 | link_to title, url, :class => 'control-panel-%s' % icon | 145 | link_to title, url, :class => 'control-panel-%s' % icon |
146 | end | 146 | end |
147 | 147 | ||
148 | + def unchangeable_privacy_field(profile) | ||
149 | + if profile.public? | ||
150 | + labelled_check_box(_('Public'), '', '', true, :disabled => true, :title => _('This field must be public'), :class => 'disabled') | ||
151 | + else | ||
152 | + '' | ||
153 | + end | ||
154 | + end | ||
155 | + | ||
148 | end | 156 | end |
app/helpers/profile_helper.rb
1 | module ProfileHelper | 1 | module ProfileHelper |
2 | 2 | ||
3 | def display_field(title, profile, field, force = false) | 3 | def display_field(title, profile, field, force = false) |
4 | - if !force && !profile.active_fields.include?(field.to_s) | 4 | + if (!force && !profile.active_fields.include?(field.to_s)) || |
5 | + (profile.active_fields.include?(field.to_s) && !profile.public_fields.include?(field.to_s) && (!user || (user != profile && !user.is_a_friend?(profile)))) | ||
5 | return '' | 6 | return '' |
6 | end | 7 | end |
7 | value = profile.send(field) | 8 | value = profile.send(field) |
@@ -15,4 +16,26 @@ module ProfileHelper | @@ -15,4 +16,26 @@ module ProfileHelper | ||
15 | end | 16 | end |
16 | end | 17 | end |
17 | 18 | ||
19 | + def display_contact(profile) | ||
20 | + address = display_field(_('Address:'), profile, :address) | ||
21 | + zip = display_field(_('ZIP code:'), profile, :zip_code) | ||
22 | + phone = display_field(_('Contact phone:'), profile, :contact_phone) | ||
23 | + email = display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) } | ||
24 | + if address.blank? && zip.blank? && phone.blank? && email.blank? | ||
25 | + '' | ||
26 | + else | ||
27 | + content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + address + zip + phone + email | ||
28 | + end | ||
29 | + end | ||
30 | + | ||
31 | + def display_work_info(profile) | ||
32 | + organization = display_field(_('Organization:'), profile, :organization) | ||
33 | + organization_site = display_field(_('Organization website:'), profile, :organization_website) { |url| link_to(url, url) } | ||
34 | + if organization.blank? && organization_site.blank? | ||
35 | + '' | ||
36 | + else | ||
37 | + content_tag('tr', content_tag('th', _('Work'), { :colspan => 2 })) + organization + organization_site | ||
38 | + end | ||
39 | + end | ||
40 | + | ||
18 | end | 41 | end |
app/models/article.rb
@@ -79,6 +79,25 @@ class Article < ActiveRecord::Base | @@ -79,6 +79,25 @@ class Article < ActiveRecord::Base | ||
79 | validate :native_translation_must_have_language | 79 | validate :native_translation_must_have_language |
80 | validate :translation_must_have_language | 80 | validate :translation_must_have_language |
81 | 81 | ||
82 | + validate :no_self_reference | ||
83 | + validate :no_cyclical_reference, :if => 'parent_id.present?' | ||
84 | + | ||
85 | + def no_self_reference | ||
86 | + errors.add(:parent_id, _('self-reference is not allowed.')) if id && parent_id == id | ||
87 | + end | ||
88 | + | ||
89 | + def no_cyclical_reference | ||
90 | + current_parent = Article.find(parent_id) | ||
91 | + while current_parent | ||
92 | + if current_parent == self | ||
93 | + errors.add(:parent_id, _('cyclical reference is not allowed.')) | ||
94 | + break | ||
95 | + end | ||
96 | + current_parent = current_parent.parent | ||
97 | + end | ||
98 | + end | ||
99 | + | ||
100 | + | ||
82 | def is_trackable? | 101 | def is_trackable? |
83 | self.published? && self.notifiable? && self.advertise? && self.profile.public_profile | 102 | self.published? && self.notifiable? && self.advertise? && self.profile.public_profile |
84 | end | 103 | end |
@@ -154,6 +173,12 @@ class Article < ActiveRecord::Base | @@ -154,6 +173,12 @@ class Article < ActiveRecord::Base | ||
154 | article.advertise = true | 173 | article.advertise = true |
155 | end | 174 | end |
156 | 175 | ||
176 | + before_save do |article| | ||
177 | + article.parent = article.parent_id ? Article.find(article.parent_id) : nil | ||
178 | + parent_path = article.parent ? article.parent.path : nil | ||
179 | + article.path = [parent_path, article.slug].compact.join('/') | ||
180 | + end | ||
181 | + | ||
157 | # retrieves all articles belonging to the given +profile+ that are not | 182 | # retrieves all articles belonging to the given +profile+ that are not |
158 | # sub-articles of any other article. | 183 | # sub-articles of any other article. |
159 | named_scope :top_level_for, lambda { |profile| | 184 | named_scope :top_level_for, lambda { |profile| |
@@ -179,37 +204,23 @@ class Article < ActiveRecord::Base | @@ -179,37 +204,23 @@ class Article < ActiveRecord::Base | ||
179 | end | 204 | end |
180 | 205 | ||
181 | named_scope :more_popular, :order => 'hits DESC' | 206 | named_scope :more_popular, :order => 'hits DESC' |
182 | - | ||
183 | - # retrieves the latest +limit+ articles, sorted from the most recent to the | ||
184 | - # oldest. | ||
185 | - # | ||
186 | - # Only includes articles where advertise == true | ||
187 | - def self.recent(limit = nil, extra_conditions = {}) | ||
188 | - # FIXME this method is a horrible hack | ||
189 | - options = { :page => 1, :per_page => limit, | ||
190 | - :conditions => [ | ||
191 | - "advertise = ? AND | ||
192 | - published = ? AND | ||
193 | - profiles.visible = ? AND | ||
194 | - profiles.public_profile = ? AND | ||
195 | - ((articles.type != ? and articles.type != ? and articles.type != ?) OR articles.type is NULL)", true, true, true, true, 'UploadedFile', 'RssFeed', 'Blog' | ||
196 | - ], | ||
197 | - :include => 'profile', | ||
198 | - :order => 'articles.published_at desc, articles.id desc' | ||
199 | - } | ||
200 | - if ( scoped_methods && scoped_methods.last && | ||
201 | - scoped_methods.last[:find] && | ||
202 | - scoped_methods.last[:find][:joins] && | ||
203 | - scoped_methods.last[:find][:joins].index('profiles') ) | ||
204 | - options.delete(:include) | ||
205 | - end | ||
206 | - if extra_conditions == {} | ||
207 | - self.paginate(options) | ||
208 | - else | ||
209 | - with_scope :find => {:conditions => extra_conditions} do | ||
210 | - self.paginate(options) | ||
211 | - end | 207 | + named_scope :relevant_as_recent, :conditions => ["(articles.type != 'UploadedFile' and articles.type != 'RssFeed' and articles.type != 'Blog') OR articles.type is NULL"] |
208 | + | ||
209 | + def self.recent(limit = nil, extra_conditions = {}, pagination = true) | ||
210 | + result = scoped({:conditions => extra_conditions}). | ||
211 | + public. | ||
212 | + relevant_as_recent. | ||
213 | + limit(limit). | ||
214 | + order(['articles.published_at desc', 'articles.id desc']) | ||
215 | + | ||
216 | + if !( scoped_methods && scoped_methods.last && | ||
217 | + scoped_methods.last[:find] && | ||
218 | + scoped_methods.last[:find][:joins] && | ||
219 | + scoped_methods.last[:find][:joins].index('profiles') ) | ||
220 | + result = result.includes(:profile) | ||
212 | end | 221 | end |
222 | + | ||
223 | + pagination ? result.paginate({:page => 1, :per_page => limit}) : result | ||
213 | end | 224 | end |
214 | 225 | ||
215 | # produces the HTML code that is to be displayed as this article's contents. | 226 | # produces the HTML code that is to be displayed as this article's contents. |
@@ -325,14 +336,14 @@ class Article < ActiveRecord::Base | @@ -325,14 +336,14 @@ class Article < ActiveRecord::Base | ||
325 | end | 336 | end |
326 | 337 | ||
327 | def possible_translations | 338 | def possible_translations |
328 | - possibilities = Noosfero.locales.keys - self.native_translation.translations(:select => :language).map(&:language) - [self.native_translation.language] | 339 | + possibilities = environment.locales.keys - self.native_translation.translations(:select => :language).map(&:language) - [self.native_translation.language] |
329 | possibilities << self.language unless self.language_changed? | 340 | possibilities << self.language unless self.language_changed? |
330 | possibilities | 341 | possibilities |
331 | end | 342 | end |
332 | 343 | ||
333 | def known_language | 344 | def known_language |
334 | unless self.language.blank? | 345 | unless self.language.blank? |
335 | - errors.add(:language, N_('Language not supported by Noosfero')) unless Noosfero.locales.key?(self.language) | 346 | + errors.add(:language, N_('Language not supported by the environment.')) unless environment.locales.key?(self.language) |
336 | end | 347 | end |
337 | end | 348 | end |
338 | 349 | ||
@@ -665,7 +676,7 @@ class Article < ActiveRecord::Base | @@ -665,7 +676,7 @@ class Article < ActiveRecord::Base | ||
665 | self.categories.collect(&:name) | 676 | self.categories.collect(&:name) |
666 | end | 677 | end |
667 | 678 | ||
668 | - delegate :region, :region_id, :environment, :environment_id, :to => :profile | 679 | + delegate :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true |
669 | def name_sortable # give a different name for solr | 680 | def name_sortable # give a different name for solr |
670 | name | 681 | name |
671 | end | 682 | end |
app/models/block.rb
@@ -7,6 +7,8 @@ class Block < ActiveRecord::Base | @@ -7,6 +7,8 @@ class Block < ActiveRecord::Base | ||
7 | # Block-specific stuff | 7 | # Block-specific stuff |
8 | include BlockHelper | 8 | include BlockHelper |
9 | 9 | ||
10 | + delegate :environment, :to => :box, :allow_nil => true | ||
11 | + | ||
10 | acts_as_list :scope => :box | 12 | acts_as_list :scope => :box |
11 | belongs_to :box | 13 | belongs_to :box |
12 | 14 |
app/models/box.rb
@@ -2,4 +2,80 @@ class Box < ActiveRecord::Base | @@ -2,4 +2,80 @@ class Box < ActiveRecord::Base | ||
2 | belongs_to :owner, :polymorphic => true | 2 | belongs_to :owner, :polymorphic => true |
3 | acts_as_list :scope => 'owner_id = #{owner_id} and owner_type = \'#{owner_type}\'' | 3 | acts_as_list :scope => 'owner_id = #{owner_id} and owner_type = \'#{owner_type}\'' |
4 | has_many :blocks, :dependent => :destroy, :order => 'position' | 4 | has_many :blocks, :dependent => :destroy, :order => 'position' |
5 | + | ||
6 | + def environment | ||
7 | + owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil | ||
8 | + end | ||
9 | + | ||
10 | + def acceptable_blocks | ||
11 | + to_css_class_name central? ? Box.acceptable_center_blocks : Box.acceptable_side_blocks | ||
12 | + end | ||
13 | + | ||
14 | + def central? | ||
15 | + position == 1 | ||
16 | + end | ||
17 | + | ||
18 | + def self.acceptable_center_blocks | ||
19 | + [ ArticleBlock, | ||
20 | + BlogArchivesBlock, | ||
21 | + CategoriesBlock, | ||
22 | + CommunitiesBlock, | ||
23 | + EnterprisesBlock, | ||
24 | + EnvironmentStatisticsBlock, | ||
25 | + FansBlock, | ||
26 | + FavoriteEnterprisesBlock, | ||
27 | + FeedReaderBlock, | ||
28 | + FriendsBlock, | ||
29 | + HighlightsBlock, | ||
30 | + LinkListBlock, | ||
31 | + LoginBlock, | ||
32 | + MainBlock, | ||
33 | + MembersBlock, | ||
34 | + MyNetworkBlock, | ||
35 | + PeopleBlock, | ||
36 | + ProfileImageBlock, | ||
37 | + RawHTMLBlock, | ||
38 | + RecentDocumentsBlock, | ||
39 | + SellersSearchBlock, | ||
40 | + TagsBlock ] | ||
41 | + end | ||
42 | + | ||
43 | + def self.acceptable_side_blocks | ||
44 | + [ ArticleBlock, | ||
45 | + BlogArchivesBlock, | ||
46 | + CategoriesBlock, | ||
47 | + CommunitiesBlock, | ||
48 | + DisabledEnterpriseMessageBlock, | ||
49 | + EnterprisesBlock, | ||
50 | + EnvironmentStatisticsBlock, | ||
51 | + FansBlock, | ||
52 | + FavoriteEnterprisesBlock, | ||
53 | + FeaturedProductsBlock, | ||
54 | + FeedReaderBlock, | ||
55 | + FriendsBlock, | ||
56 | + HighlightsBlock, | ||
57 | + LinkListBlock, | ||
58 | + LocationBlock, | ||
59 | + LoginBlock, | ||
60 | + MembersBlock, | ||
61 | + MyNetworkBlock, | ||
62 | + PeopleBlock, | ||
63 | + ProductsBlock, | ||
64 | + ProfileImageBlock, | ||
65 | + ProfileInfoBlock, | ||
66 | + ProfileSearchBlock, | ||
67 | + RawHTMLBlock, | ||
68 | + RecentDocumentsBlock, | ||
69 | + SellersSearchBlock, | ||
70 | + SlideshowBlock, | ||
71 | + TagsBlock | ||
72 | + ] | ||
73 | + end | ||
74 | + | ||
75 | + private | ||
76 | + | ||
77 | + def to_css_class_name(blocks) | ||
78 | + blocks.map{ |block| block.to_s.underscore.tr('_', '-') } | ||
79 | + end | ||
80 | + | ||
5 | end | 81 | end |
app/models/change_password.rb
@@ -7,7 +7,7 @@ class ChangePassword < Task | @@ -7,7 +7,7 @@ class ChangePassword < Task | ||
7 | when :login: | 7 | when :login: |
8 | _('Username') | 8 | _('Username') |
9 | when :email | 9 | when :email |
10 | - _('e-Mail') | 10 | + _('e-mail') |
11 | when :password | 11 | when :password |
12 | _('Password') | 12 | _('Password') |
13 | when :password_confirmation | 13 | when :password_confirmation |
@@ -20,9 +20,7 @@ class ChangePassword < Task | @@ -20,9 +20,7 @@ class ChangePassword < Task | ||
20 | ################################################### | 20 | ################################################### |
21 | # validations for creating a ChangePassword task | 21 | # validations for creating a ChangePassword task |
22 | 22 | ||
23 | - validates_presence_of :login, :email, :environment_id, :on => :create | ||
24 | - | ||
25 | - validates_presence_of :requestor_id | 23 | + validates_presence_of :login, :email, :environment_id, :on => :create, :message => _('must be filled in') |
26 | 24 | ||
27 | validates_format_of :email, :on => :create, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |obj| !obj.email.blank? }) | 25 | validates_format_of :email, :on => :create, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |obj| !obj.email.blank? }) |
28 | 26 | ||
@@ -30,10 +28,10 @@ class ChangePassword < Task | @@ -30,10 +28,10 @@ class ChangePassword < Task | ||
30 | unless data.login.blank? || data.email.blank? | 28 | unless data.login.blank? || data.email.blank? |
31 | user = User.find_by_login_and_environment_id(data.login, data.environment_id) | 29 | user = User.find_by_login_and_environment_id(data.login, data.environment_id) |
32 | if user.nil? | 30 | if user.nil? |
33 | - data.errors.add(:login, _('%{fn} is not a valid username.').fix_i18n) | 31 | + data.errors.add(:login, _('is invalid or user does not exists.')) |
34 | else | 32 | else |
35 | if user.email != data.email | 33 | if user.email != data.email |
36 | - data.errors.add(:email) | 34 | + data.errors.add(:email, _('does not match the username you filled in')) |
37 | end | 35 | end |
38 | end | 36 | end |
39 | end | 37 | end |
app/models/enterprise.rb
@@ -17,7 +17,7 @@ class Enterprise < Organization | @@ -17,7 +17,7 @@ class Enterprise < Organization | ||
17 | after_save_reindex [:products], :with => :delayed_job | 17 | after_save_reindex [:products], :with => :delayed_job |
18 | extra_data_for_index :product_categories | 18 | extra_data_for_index :product_categories |
19 | def product_categories | 19 | def product_categories |
20 | - products.map{|p| p.category_full_name}.compact | 20 | + products.includes(:product_category).map{|p| p.category_full_name}.compact |
21 | end | 21 | end |
22 | 22 | ||
23 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') | 23 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') |
app/models/environment.rb
@@ -123,10 +123,23 @@ class Environment < ActiveRecord::Base | @@ -123,10 +123,23 @@ class Environment < ActiveRecord::Base | ||
123 | 'xmpp_chat' => _('XMPP/Jabber based chat'), | 123 | 'xmpp_chat' => _('XMPP/Jabber based chat'), |
124 | 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'), | 124 | 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'), |
125 | 'captcha_for_logged_users' => _('Ask captcha when a logged user comments too'), | 125 | 'captcha_for_logged_users' => _('Ask captcha when a logged user comments too'), |
126 | - 'skip_new_user_email_confirmation' => _('Skip e-mail confirmation for new users') | 126 | + 'skip_new_user_email_confirmation' => _('Skip e-mail confirmation for new users'), |
127 | + 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), | ||
128 | + 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login') | ||
127 | } | 129 | } |
128 | end | 130 | end |
129 | 131 | ||
132 | + def self.login_redirection_options | ||
133 | + { | ||
134 | + 'keep_on_same_page' => _('Stays on the same page the user was before login.'), | ||
135 | + 'site_homepage' => _('Redirects the user to the environment homepage.'), | ||
136 | + 'user_profile_page' => _('Redirects the user to his profile page.'), | ||
137 | + 'user_homepage' => _('Redirects the user to his homepage.'), | ||
138 | + 'user_control_panel' => _('Redirects the user to his control panel.') | ||
139 | + } | ||
140 | + end | ||
141 | + validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true | ||
142 | + | ||
130 | # ################################################# | 143 | # ################################################# |
131 | # Relationships and applied behaviour | 144 | # Relationships and applied behaviour |
132 | # ################################################# | 145 | # ################################################# |
@@ -530,6 +543,31 @@ class Environment < ActiveRecord::Base | @@ -530,6 +543,31 @@ class Environment < ActiveRecord::Base | ||
530 | signup_fields | 543 | signup_fields |
531 | end | 544 | end |
532 | 545 | ||
546 | + serialize :signup_welcome_text, Hash | ||
547 | + def signup_welcome_text | ||
548 | + self[:signup_welcome_text] ||= {} | ||
549 | + end | ||
550 | + | ||
551 | + def signup_welcome_text_subject | ||
552 | + self.signup_welcome_text[:subject] | ||
553 | + end | ||
554 | + | ||
555 | + def signup_welcome_text_subject=(subject) | ||
556 | + self.signup_welcome_text[:subject] = subject | ||
557 | + end | ||
558 | + | ||
559 | + def signup_welcome_text_body | ||
560 | + self.signup_welcome_text[:body] | ||
561 | + end | ||
562 | + | ||
563 | + def signup_welcome_text_body=(body) | ||
564 | + self.signup_welcome_text[:body] = body | ||
565 | + end | ||
566 | + | ||
567 | + def has_signup_welcome_text? | ||
568 | + signup_welcome_text && !signup_welcome_text_body.blank? | ||
569 | + end | ||
570 | + | ||
533 | # ################################################# | 571 | # ################################################# |
534 | # Validations | 572 | # Validations |
535 | # ################################################# | 573 | # ################################################# |
@@ -591,8 +629,8 @@ class Environment < ActiveRecord::Base | @@ -591,8 +629,8 @@ class Environment < ActiveRecord::Base | ||
591 | end | 629 | end |
592 | 630 | ||
593 | has_many :articles, :through => :profiles | 631 | has_many :articles, :through => :profiles |
594 | - def recent_documents(limit = 10) | ||
595 | - self.articles.recent(limit) | 632 | + def recent_documents(limit = 10, options = {}, pagination = true) |
633 | + self.articles.recent(limit, options, pagination) | ||
596 | end | 634 | end |
597 | 635 | ||
598 | has_many :events, :through => :profiles, :source => :articles, :class_name => 'Event' | 636 | has_many :events, :through => :profiles, :source => :articles, :class_name => 'Event' |
@@ -766,4 +804,53 @@ class Environment < ActiveRecord::Base | @@ -766,4 +804,53 @@ class Environment < ActiveRecord::Base | ||
766 | def image_galleries | 804 | def image_galleries |
767 | portal_community ? portal_community.image_galleries : [] | 805 | portal_community ? portal_community.image_galleries : [] |
768 | end | 806 | end |
807 | + | ||
808 | + serialize :languages | ||
809 | + | ||
810 | + before_validation do |environment| | ||
811 | + environment.default_language = nil if environment.default_language.blank? | ||
812 | + end | ||
813 | + | ||
814 | + validate :default_language_available | ||
815 | + validate :languages_available | ||
816 | + | ||
817 | + def locales | ||
818 | + if languages.present? | ||
819 | + languages.inject({}) {|r, l| r.merge({l => Noosfero.locales[l]})} | ||
820 | + else | ||
821 | + Noosfero.locales | ||
822 | + end | ||
823 | + end | ||
824 | + | ||
825 | + def default_locale | ||
826 | + default_language || Noosfero.default_locale | ||
827 | + end | ||
828 | + | ||
829 | + def available_locales | ||
830 | + locales_list = locales.keys | ||
831 | + # move English to the beginning | ||
832 | + if locales_list.include?('en') | ||
833 | + locales_list = ['en'] + (locales_list - ['en']).sort | ||
834 | + end | ||
835 | + locales_list | ||
836 | + end | ||
837 | + | ||
838 | + private | ||
839 | + | ||
840 | + def default_language_available | ||
841 | + if default_language.present? && !available_locales.include?(default_language) | ||
842 | + errors.add(:default_language, _('is not available.')) | ||
843 | + end | ||
844 | + end | ||
845 | + | ||
846 | + def languages_available | ||
847 | + if languages.present? | ||
848 | + languages.each do |language| | ||
849 | + if !Noosfero.available_locales.include?(language) | ||
850 | + errors.add(:languages, _('have unsupported languages.')) | ||
851 | + break | ||
852 | + end | ||
853 | + end | ||
854 | + end | ||
855 | + end | ||
769 | end | 856 | end |
app/models/external_feed.rb
@@ -19,9 +19,15 @@ class ExternalFeed < ActiveRecord::Base | @@ -19,9 +19,15 @@ class ExternalFeed < ActiveRecord::Base | ||
19 | article.valid? | 19 | article.valid? |
20 | end | 20 | end |
21 | 21 | ||
22 | + def address=(new_address) | ||
23 | + self.fetched_at = nil unless address == new_address | ||
24 | + super(new_address) | ||
25 | + end | ||
26 | + | ||
22 | def clear | 27 | def clear |
23 | # do nothing | 28 | # do nothing |
24 | end | 29 | end |
30 | + | ||
25 | def finish_fetch | 31 | def finish_fetch |
26 | if self.only_once && self.update_errors.zero? | 32 | if self.only_once && self.update_errors.zero? |
27 | self.enabled = false | 33 | self.enabled = false |
app/models/person.rb
@@ -71,10 +71,7 @@ class Person < Profile | @@ -71,10 +71,7 @@ class Person < Profile | ||
71 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } | 71 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } |
72 | end | 72 | end |
73 | 73 | ||
74 | - after_destroy :destroy_user | ||
75 | - def destroy_user | ||
76 | - self.user.destroy if self.user | ||
77 | - end | 74 | + belongs_to :user, :dependent => :delete |
78 | 75 | ||
79 | def can_control_scrap?(scrap) | 76 | def can_control_scrap?(scrap) |
80 | begin | 77 | begin |
@@ -183,7 +180,8 @@ class Person < Profile | @@ -183,7 +180,8 @@ class Person < Profile | ||
183 | include MaybeAddHttp | 180 | include MaybeAddHttp |
184 | 181 | ||
185 | def active_fields | 182 | def active_fields |
186 | - environment ? environment.active_person_fields : [] | 183 | + fields = environment ? environment.active_person_fields : [] |
184 | + fields << 'email' | ||
187 | end | 185 | end |
188 | 186 | ||
189 | def required_fields | 187 | def required_fields |
@@ -253,7 +251,7 @@ class Person < Profile | @@ -253,7 +251,7 @@ class Person < Profile | ||
253 | 251 | ||
254 | def is_admin?(environment = nil) | 252 | def is_admin?(environment = nil) |
255 | environment ||= self.environment | 253 | environment ||= self.environment |
256 | - role_assignments.select { |ra| ra.resource == environment }.map{|ra|ra.role.permissions}.any? do |ps| | 254 | + role_assignments.includes([:role, :resource]).select { |ra| ra.resource == environment }.map{|ra|ra.role.permissions}.any? do |ps| |
257 | ps.any? do |p| | 255 | ps.any? do |p| |
258 | ActiveRecord::Base::PERMISSIONS['Environment'].keys.include?(p) | 256 | ActiveRecord::Base::PERMISSIONS['Environment'].keys.include?(p) |
259 | end | 257 | end |
@@ -461,6 +459,10 @@ class Person < Profile | @@ -461,6 +459,10 @@ class Person < Profile | ||
461 | Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' ORDER BY updated_at DESC") | 459 | Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' ORDER BY updated_at DESC") |
462 | end | 460 | end |
463 | 461 | ||
462 | + def public_fields | ||
463 | + self.fields_privacy.nil? ? self.active_fields : self.fields_privacy.reject{ |k, v| v != 'public' }.keys.map(&:to_s) | ||
464 | + end | ||
465 | + | ||
464 | protected | 466 | protected |
465 | 467 | ||
466 | def followed_by?(profile) | 468 | def followed_by?(profile) |
app/models/profile.rb
@@ -57,6 +57,7 @@ class Profile < ActiveRecord::Base | @@ -57,6 +57,7 @@ class Profile < ActiveRecord::Base | ||
57 | 'view_private_content' => N_('View private content'), | 57 | 'view_private_content' => N_('View private content'), |
58 | 'publish_content' => N_('Publish content'), | 58 | 'publish_content' => N_('Publish content'), |
59 | 'invite_members' => N_('Invite members'), | 59 | 'invite_members' => N_('Invite members'), |
60 | + 'send_mail_to_members' => N_('Send e-Mail to members'), | ||
60 | } | 61 | } |
61 | 62 | ||
62 | acts_as_accessible | 63 | acts_as_accessible |
@@ -147,6 +148,7 @@ class Profile < ActiveRecord::Base | @@ -147,6 +148,7 @@ class Profile < ActiveRecord::Base | ||
147 | settings_items :redirect_l10n, :type => :boolean, :default => false | 148 | settings_items :redirect_l10n, :type => :boolean, :default => false |
148 | settings_items :public_content, :type => :boolean, :default => true | 149 | settings_items :public_content, :type => :boolean, :default => true |
149 | settings_items :description | 150 | settings_items :description |
151 | + settings_items :fields_privacy, :type => :hash, :default => {} | ||
150 | 152 | ||
151 | validates_length_of :description, :maximum => 550, :allow_nil => true | 153 | validates_length_of :description, :maximum => 550, :allow_nil => true |
152 | 154 | ||
@@ -402,8 +404,8 @@ class Profile < ActiveRecord::Base | @@ -402,8 +404,8 @@ class Profile < ActiveRecord::Base | ||
402 | # | 404 | # |
403 | # +limit+ is the maximum number of documents to be returned. It defaults to | 405 | # +limit+ is the maximum number of documents to be returned. It defaults to |
404 | # 10. | 406 | # 10. |
405 | - def recent_documents(limit = 10, options = {}) | ||
406 | - self.articles.recent(limit, options) | 407 | + def recent_documents(limit = 10, options = {}, pagination = true) |
408 | + self.articles.recent(limit, options, pagination) | ||
407 | end | 409 | end |
408 | 410 | ||
409 | def last_articles(limit = 10, options = {}) | 411 | def last_articles(limit = 10, options = {}) |
@@ -879,6 +881,15 @@ private :generate_url, :url_options | @@ -879,6 +881,15 @@ private :generate_url, :url_options | ||
879 | [] | 881 | [] |
880 | end | 882 | end |
881 | 883 | ||
884 | + # field => privacy (e.g.: "address" => "public") | ||
885 | + def fields_privacy | ||
886 | + self.data[:fields_privacy] | ||
887 | + end | ||
888 | + | ||
889 | + def public_fields | ||
890 | + self.active_fields | ||
891 | + end | ||
892 | + | ||
882 | private | 893 | private |
883 | def self.f_categories_label_proc(environment) | 894 | def self.f_categories_label_proc(environment) |
884 | ids = environment.top_level_category_as_facet_ids | 895 | ids = environment.top_level_category_as_facet_ids |
@@ -975,4 +986,8 @@ private :generate_url, :url_options | @@ -975,4 +986,8 @@ private :generate_url, :url_options | ||
975 | end | 986 | end |
976 | end | 987 | end |
977 | 988 | ||
989 | + validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true | ||
990 | + def preferred_login_redirection | ||
991 | + redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login | ||
992 | + end | ||
978 | end | 993 | end |
app/models/profile_list_block.rb
@@ -14,12 +14,13 @@ class ProfileListBlock < Block | @@ -14,12 +14,13 @@ class ProfileListBlock < Block | ||
14 | 14 | ||
15 | def profile_list | 15 | def profile_list |
16 | result = nil | 16 | result = nil |
17 | + visible_profiles = profiles.visible.includes([:image,:domains,:preferred_domain,:environment]) | ||
17 | if !prioritize_profiles_with_image | 18 | if !prioritize_profiles_with_image |
18 | - result = profiles.visible.all(:limit => limit, :order => 'updated_at DESC').sort_by{ rand } | ||
19 | - elsif profiles.visible.with_image.count >= limit | ||
20 | - result = profiles.visible.with_image.all(:limit => limit * 5, :order => 'updated_at DESC').sort_by{ rand } | 19 | + result = visible_profiles.all(:limit => limit, :order => 'updated_at DESC').sort_by{ rand } |
20 | + elsif visible_profiles.with_image.count >= limit | ||
21 | + result = visible_profiles.with_image.all(:limit => limit * 5, :order => 'updated_at DESC').sort_by{ rand } | ||
21 | else | 22 | else |
22 | - result = profiles.visible.with_image.sort_by{ rand } + profiles.visible.without_image.all(:limit => limit * 5, :order => 'updated_at DESC').sort_by{ rand } | 23 | + result = visible_profiles.with_image.sort_by{ rand } + visible_profiles.without_image.all(:limit => limit * 5, :order => 'updated_at DESC').sort_by{ rand } |
23 | end | 24 | end |
24 | result.slice(0..limit-1) | 25 | result.slice(0..limit-1) |
25 | end | 26 | end |
app/models/recent_documents_block.rb
@@ -16,11 +16,9 @@ class RecentDocumentsBlock < Block | @@ -16,11 +16,9 @@ class RecentDocumentsBlock < Block | ||
16 | 16 | ||
17 | include ActionController::UrlWriter | 17 | include ActionController::UrlWriter |
18 | def content(args={}) | 18 | def content(args={}) |
19 | - docs = self.limit.nil? ? owner.recent_documents : owner.recent_documents(self.limit) | ||
20 | - | 19 | + docs = self.limit.nil? ? owner.recent_documents(nil, {}, false) : owner.recent_documents(self.limit, {}, false) |
21 | block_title(title) + | 20 | block_title(title) + |
22 | content_tag('ul', docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n")) | 21 | content_tag('ul', docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n")) |
23 | - | ||
24 | end | 22 | end |
25 | 23 | ||
26 | def footer | 24 | def footer |
app/models/task.rb
@@ -31,7 +31,7 @@ class Task < ActiveRecord::Base | @@ -31,7 +31,7 @@ class Task < ActiveRecord::Base | ||
31 | end | 31 | end |
32 | end | 32 | end |
33 | 33 | ||
34 | - belongs_to :requestor, :class_name => 'Person', :foreign_key => :requestor_id | 34 | + belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id |
35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true | 35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true |
36 | 36 | ||
37 | validates_uniqueness_of :code, :on => :create | 37 | validates_uniqueness_of :code, :on => :create |
app/models/user.rb
@@ -30,7 +30,7 @@ class User < ActiveRecord::Base | @@ -30,7 +30,7 @@ class User < ActiveRecord::Base | ||
30 | 30 | ||
31 | after_create do |user| | 31 | after_create do |user| |
32 | user.person ||= Person.new | 32 | user.person ||= Person.new |
33 | - user.person.attributes = user.person_data.merge(:identifier => user.login, :user_id => user.id, :environment_id => user.environment_id) | 33 | + user.person.attributes = user.person_data.merge(:identifier => user.login, :user => user, :environment_id => user.environment_id) |
34 | user.person.name ||= user.login | 34 | user.person.name ||= user.login |
35 | user.person.visible = false unless user.activated? | 35 | user.person.visible = false unless user.activated? |
36 | user.person.save! | 36 | user.person.save! |
@@ -73,6 +73,18 @@ class User < ActiveRecord::Base | @@ -73,6 +73,18 @@ class User < ActiveRecord::Base | ||
73 | :environment => user.environment.name, | 73 | :environment => user.environment.name, |
74 | :url => user.environment.top_url | 74 | :url => user.environment.top_url |
75 | end | 75 | end |
76 | + | ||
77 | + def signup_welcome_email(user) | ||
78 | + email_body = user.environment.signup_welcome_text_body.gsub('{user_name}', user.name) | ||
79 | + email_subject = user.environment.signup_welcome_text_subject | ||
80 | + | ||
81 | + content_type 'text/html' | ||
82 | + recipients user.email | ||
83 | + | ||
84 | + from "#{user.environment.name} <#{user.environment.contact_email}>" | ||
85 | + subject email_subject.blank? ? _("Welcome to environment %s") % [user.environment.name] : email_subject | ||
86 | + body email_body | ||
87 | + end | ||
76 | end | 88 | end |
77 | 89 | ||
78 | def signup! | 90 | def signup! |
@@ -88,13 +100,13 @@ class User < ActiveRecord::Base | @@ -88,13 +100,13 @@ class User < ActiveRecord::Base | ||
88 | attr_protected :activated_at | 100 | attr_protected :activated_at |
89 | 101 | ||
90 | # Virtual attribute for the unencrypted password | 102 | # Virtual attribute for the unencrypted password |
91 | - attr_accessor :password | 103 | + attr_accessor :password, :name |
92 | 104 | ||
93 | validates_presence_of :login, :email | 105 | validates_presence_of :login, :email |
94 | validates_format_of :login, :with => Profile::IDENTIFIER_FORMAT, :if => (lambda {|user| !user.login.blank?}) | 106 | validates_format_of :login, :with => Profile::IDENTIFIER_FORMAT, :if => (lambda {|user| !user.login.blank?}) |
95 | validates_presence_of :password, :if => :password_required? | 107 | validates_presence_of :password, :if => :password_required? |
96 | - validates_presence_of :password_confirmation, :if => :password_required?, :if => (lambda {|user| !user.password.blank?}) | ||
97 | - validates_length_of :password, :within => 4..40, :if => :password_required?, :if => (lambda {|user| !user.password.blank?}) | 108 | + validates_presence_of :password_confirmation, :if => :password_required? |
109 | + validates_length_of :password, :within => 4..40, :if => :password_required? | ||
98 | validates_confirmation_of :password, :if => :password_required? | 110 | validates_confirmation_of :password, :if => :password_required? |
99 | validates_length_of :login, :within => 2..40, :if => (lambda {|user| !user.login.blank?}) | 111 | validates_length_of :login, :within => 2..40, :if => (lambda {|user| !user.login.blank?}) |
100 | validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?}) | 112 | validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?}) |
@@ -117,7 +129,17 @@ class User < ActiveRecord::Base | @@ -117,7 +129,17 @@ class User < ActiveRecord::Base | ||
117 | self.activated_at = Time.now.utc | 129 | self.activated_at = Time.now.utc |
118 | self.activation_code = nil | 130 | self.activation_code = nil |
119 | self.person.visible = true | 131 | self.person.visible = true |
120 | - self.person.save! && self.save! | 132 | + begin |
133 | + self.person.save! && self.save! | ||
134 | + rescue Exception => exception | ||
135 | + logger.error(exception.to_s) | ||
136 | + false | ||
137 | + else | ||
138 | + if environment.enabled?('send_welcome_email_to_new_users') && environment.has_signup_welcome_text? | ||
139 | + User::Mailer.delay.deliver_signup_welcome_email(self) | ||
140 | + end | ||
141 | + true | ||
142 | + end | ||
121 | end | 143 | end |
122 | 144 | ||
123 | def activated? | 145 | def activated? |
@@ -228,7 +250,12 @@ class User < ActiveRecord::Base | @@ -228,7 +250,12 @@ class User < ActiveRecord::Base | ||
228 | end | 250 | end |
229 | 251 | ||
230 | def name | 252 | def name |
231 | - person ? person.name : login | 253 | + name = (self[:name] || login) |
254 | + person.nil? ? name : (person.name || name) | ||
255 | + end | ||
256 | + | ||
257 | + def name= name | ||
258 | + self[:name] = name | ||
232 | end | 259 | end |
233 | 260 | ||
234 | def enable_email! | 261 | def enable_email! |
@@ -274,6 +301,11 @@ class User < ActiveRecord::Base | @@ -274,6 +301,11 @@ class User < ActiveRecord::Base | ||
274 | 15 # in minutes | 301 | 15 # in minutes |
275 | end | 302 | end |
276 | 303 | ||
304 | + | ||
305 | + def not_require_password! | ||
306 | + @is_password_required = false | ||
307 | + end | ||
308 | + | ||
277 | protected | 309 | protected |
278 | # before filter | 310 | # before filter |
279 | def encrypt_password | 311 | def encrypt_password |
@@ -282,9 +314,13 @@ class User < ActiveRecord::Base | @@ -282,9 +314,13 @@ class User < ActiveRecord::Base | ||
282 | self.password_type ||= User.system_encryption_method.to_s | 314 | self.password_type ||= User.system_encryption_method.to_s |
283 | self.crypted_password = encrypt(password) | 315 | self.crypted_password = encrypt(password) |
284 | end | 316 | end |
285 | - | 317 | + |
286 | def password_required? | 318 | def password_required? |
287 | - crypted_password.blank? || !password.blank? | 319 | + (crypted_password.blank? || !password.blank?) && is_password_required? |
320 | + end | ||
321 | + | ||
322 | + def is_password_required? | ||
323 | + @is_password_required.nil? ? true : @is_password_required | ||
288 | end | 324 | end |
289 | 325 | ||
290 | def make_activation_code | 326 | def make_activation_code |
app/sweepers/article_sweeper.rb
@@ -10,17 +10,24 @@ class ArticleSweeper < ActiveRecord::Observer | @@ -10,17 +10,24 @@ class ArticleSweeper < ActiveRecord::Observer | ||
10 | expire_caches(article) | 10 | expire_caches(article) |
11 | end | 11 | end |
12 | 12 | ||
13 | + def before_update(article) | ||
14 | + if article.parent_id_change | ||
15 | + Article.find(article.parent_id_was).touch if article.parent_id_was | ||
16 | + end | ||
17 | + end | ||
18 | + | ||
13 | protected | 19 | protected |
14 | 20 | ||
15 | def expire_caches(article) | 21 | def expire_caches(article) |
16 | - article.hierarchy.each { |a| a.touch if a != article } | 22 | + return if !article.environment |
23 | + article.hierarchy(true).each { |a| a.touch if a != article } | ||
17 | blocks = article.profile.blocks | 24 | blocks = article.profile.blocks |
18 | blocks += article.profile.environment.blocks if article.profile.environment | 25 | blocks += article.profile.environment.blocks if article.profile.environment |
19 | blocks = blocks.select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}} | 26 | blocks = blocks.select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}} |
20 | BlockSweeper.expire_blocks(blocks) | 27 | BlockSweeper.expire_blocks(blocks) |
21 | env = article.profile.environment | 28 | env = article.profile.environment |
22 | if env && (env.portal_community == article.profile) | 29 | if env && (env.portal_community == article.profile) |
23 | - Noosfero.locales.keys.each do |locale| | 30 | + article.environment.locales.keys.each do |locale| |
24 | expire_fragment(env.portal_news_cache_key(locale)) | 31 | expire_fragment(env.portal_news_cache_key(locale)) |
25 | end | 32 | end |
26 | end | 33 | end |
app/sweepers/block_sweeper.rb
@@ -7,10 +7,11 @@ class BlockSweeper < ActiveRecord::Observer | @@ -7,10 +7,11 @@ class BlockSweeper < ActiveRecord::Observer | ||
7 | 7 | ||
8 | # Expire block's all languages cache | 8 | # Expire block's all languages cache |
9 | def expire_block(block) | 9 | def expire_block(block) |
10 | + return if !block.environment | ||
10 | regex = '-[a-z]*$' | 11 | regex = '-[a-z]*$' |
11 | clean_ck = block.cache_key.gsub(/#{regex}/,'') | 12 | clean_ck = block.cache_key.gsub(/#{regex}/,'') |
12 | 13 | ||
13 | - Noosfero.locales.keys.each do |locale| | 14 | + block.environment.locales.keys.each do |locale| |
14 | expire_timeout_fragment("#{clean_ck}-#{locale}") | 15 | expire_timeout_fragment("#{clean_ck}-#{locale}") |
15 | end | 16 | end |
16 | end | 17 | end |
app/views/account/forgot_password.rhtml
1 | <h1><%= _('Forgot your password?') %></h1> | 1 | <h1><%= _('Forgot your password?') %></h1> |
2 | 2 | ||
3 | -<%= error_messages_for :change_password %> | 3 | +<%= error_messages_for :change_password, :header_message => _('Instructions to password recovery could not be sent'), :message => nil %> |
4 | 4 | ||
5 | <% labelled_form_for :change_password, @change_password, :url => { :action => 'forgot_password' } do |f| %> | 5 | <% labelled_form_for :change_password, @change_password, :url => { :action => 'forgot_password' } do |f| %> |
6 | 6 |
app/views/account/login.rhtml
@@ -13,6 +13,8 @@ | @@ -13,6 +13,8 @@ | ||
13 | 13 | ||
14 | <%= f.password_field :password %> | 14 | <%= f.password_field :password %> |
15 | 15 | ||
16 | + <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }.join("") %> | ||
17 | + | ||
16 | <% button_bar do %> | 18 | <% button_bar do %> |
17 | <%= submit_button( 'login', _('Log in') )%> | 19 | <%= submit_button( 'login', _('Log in') )%> |
18 | <% if is_thickbox %> | 20 | <% if is_thickbox %> |
@@ -23,8 +25,13 @@ | @@ -23,8 +25,13 @@ | ||
23 | <% end %> | 25 | <% end %> |
24 | 26 | ||
25 | <% button_bar do %> | 27 | <% button_bar do %> |
26 | - <%= button :add, _("New user"), :controller => 'account', :action => 'signup' %> | ||
27 | - <%= button :help, _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %> | 28 | + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> |
29 | + <%= button :add, _("New user"), :controller => 'account', :action => 'signup' %> | ||
30 | + <% end %> | ||
31 | + | ||
32 | + <% unless @plugins.dispatch(:allow_password_recovery).include?(false) %> | ||
33 | + <%= button :help, _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %> | ||
34 | + <% end %> | ||
28 | <% end %> | 35 | <% end %> |
29 | 36 | ||
30 | </div><!-- end class="login-box" --> | 37 | </div><!-- end class="login-box" --> |
app/views/account/login_block.rhtml
@@ -9,25 +9,30 @@ | @@ -9,25 +9,30 @@ | ||
9 | @user ||= User.new | 9 | @user ||= User.new |
10 | %> | 10 | %> |
11 | 11 | ||
12 | - <% labelled_form_for :user, @user, | ||
13 | - :url => login_url do |f| %> | 12 | + <% labelled_form_for :user, @user, :url => login_url do |f| %> |
14 | 13 | ||
15 | - <%= f.text_field :login, :onchange => 'this.value = convToValidLogin( this.value )' %> | 14 | + <%= f.text_field :login, :onchange => 'this.value = convToValidLogin( this.value )' %> |
16 | 15 | ||
17 | - <%= f.password_field :password %> | 16 | + <%= f.password_field :password %> |
17 | + | ||
18 | + <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }.join("") %> | ||
18 | 19 | ||
19 | <% button_bar do %> | 20 | <% button_bar do %> |
20 | <%= submit_button( 'login', _('Log in') )%> | 21 | <%= submit_button( 'login', _('Log in') )%> |
21 | - <%= link_to content_tag( 'span', _('New user') ), | ||
22 | - { :controller => 'account', :action => 'signup' }, | ||
23 | - :class => 'button with-text icon-add' %> | 22 | + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> |
23 | + <%= link_to content_tag( 'span', _('New user') ), | ||
24 | + { :controller => 'account', :action => 'signup' }, | ||
25 | + :class => 'button with-text icon-add' %> | ||
26 | + <% end %> | ||
24 | <% end %> | 27 | <% end %> |
25 | 28 | ||
26 | <% end %> | 29 | <% end %> |
27 | 30 | ||
28 | - <p class="forgot-passwd"> | ||
29 | - <%= link_to _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %> | ||
30 | - </p> | 31 | + <% unless @plugins.dispatch(:allow_password_recovery).include?(false) %> |
32 | + <p class="forgot-passwd"> | ||
33 | + <%= link_to _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %> | ||
34 | + </p> | ||
35 | + <% end %> | ||
31 | 36 | ||
32 | </div> | 37 | </div> |
33 | 38 |
@@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
1 | +<div class='description'> | ||
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}') %> | ||
4 | +</div> | ||
5 | + | ||
6 | +<%= labelled_form_field(_('Subject'), text_field(:environment, :signup_welcome_text_subject, :style => 'width:100%')) %> | ||
7 | +<%= labelled_form_field(_('Body'), text_area(:environment, :signup_welcome_text_body, :cols => 40, :style => 'width: 100%', :class => 'mceEditor')) %> |
app/views/admin_panel/_site_info.rhtml
1 | <%= required labelled_form_field(_('Site name'), text_field(:environment, :name)) %> | 1 | <%= required labelled_form_field(_('Site name'), text_field(:environment, :name)) %> |
2 | +<%= labelled_form_field(_('Contact email'), text_field(:environment, :contact_email)) %> | ||
3 | +<% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %> | ||
4 | +<%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %> | ||
2 | <%= required f.text_field(:reports_lower_bound, :size => 3) %> | 5 | <%= required f.text_field(:reports_lower_bound, :size => 3) %> |
6 | +<%= labelled_form_field(_('Default language'), select(:environment, :default_language, environment.locales.invert, { :selected => environment.default_locale, :include_blank => true })) %> | ||
7 | +<%= label_tag :languages, _('Available languages') %> | ||
8 | +<br /> | ||
9 | + | ||
10 | +<% | ||
11 | + fields = Noosfero.locales.map do |value, name| | ||
12 | + labelled_check_box(name, "environment[languages][#{value}]", true, environment.available_locales.include?(value)) | ||
13 | + end | ||
14 | +%> | ||
15 | +<%= balanced_table(fields)%> | ||
16 | + | ||
17 | +<br /> | ||
3 | <%= labelled_form_field _('Homepage content'), text_area(:environment, :description, :cols => 40, :style => 'width: 90%', :class => 'mceEditor') %> | 18 | <%= labelled_form_field _('Homepage content'), text_area(:environment, :description, :cols => 40, :style => 'width: 90%', :class => 'mceEditor') %> |
app/views/admin_panel/site_info.rhtml
@@ -10,6 +10,8 @@ | @@ -10,6 +10,8 @@ | ||
10 | :content => (render :partial => 'site_info', :locals => {:f => f})} %> | 10 | :content => (render :partial => 'site_info', :locals => {:f => f})} %> |
11 | <% tabs << {:title => _('Terms of use'), :id => 'terms-of-use', | 11 | <% tabs << {:title => _('Terms of use'), :id => 'terms-of-use', |
12 | :content => (render :partial => 'terms_of_use', :locals => {:f => f})} %> | 12 | :content => (render :partial => 'terms_of_use', :locals => {:f => f})} %> |
13 | + <% tabs << {:title => _('Signup welcome text'), :id => 'signup-welcome-text', | ||
14 | + :content => (render :partial => 'signup_welcome_text', :locals => {:f => f})} %> | ||
13 | <%= render_tabs(tabs) %> | 15 | <%= render_tabs(tabs) %> |
14 | <% button_bar do %> | 16 | <% button_bar do %> |
15 | <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> | 17 | <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> |
app/views/blocks/profile_info_actions/community.rhtml
@@ -32,7 +32,7 @@ | @@ -32,7 +32,7 @@ | ||
32 | { :profile => profile.identifier, | 32 | { :profile => profile.identifier, |
33 | :controller => 'contact', | 33 | :controller => 'contact', |
34 | :action => 'new' }, | 34 | :action => 'new' }, |
35 | - :class => 'button with-text icon-menu-mail' %> | 35 | + {:class => 'button with-text icon-menu-mail', :title => _('Send an e-mail to the administrators')} %> |
36 | </li> | 36 | </li> |
37 | <% end %> | 37 | <% end %> |
38 | 38 |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<% block_types.in_groups_of(2) do |block1, block2| %> | ||
2 | + <div style='float: left; width: 48%; padding-top: 2px;'> | ||
3 | + <%= labelled_radio_button(block1.description, :type, block1.name) %> | ||
4 | + </div> | ||
5 | + <% if block2 %> | ||
6 | + <div style='float: left; width: 48%; padding-top: 2px;'> | ||
7 | + <%= labelled_radio_button(block2.description, :type, block2.name) %> | ||
8 | + </div> | ||
9 | + <% end %> | ||
10 | +<% end %> |
app/views/box_organizer/_highlights_block.rhtml
1 | <strong><%= _('Highlights') %></strong> | 1 | <strong><%= _('Highlights') %></strong> |
2 | -<div id='edit-highlights-block'> | 2 | +<div id='edit-highlights-block' style='width:450px'> |
3 | <table id='highlights' class='noborder'> | 3 | <table id='highlights' class='noborder'> |
4 | <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr> | 4 | <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr> |
5 | <% for image in @block.images do %> | 5 | <% for image in @block.images do %> |
app/views/box_organizer/_link_list_block.rhtml
1 | <strong><%= _('Links') %></strong> | 1 | <strong><%= _('Links') %></strong> |
2 | -<div id='edit-link-list-block'> | 2 | +<div id='edit-link-list-block' style='width:450px'> |
3 | <table id='links' class='noborder'> | 3 | <table id='links' class='noborder'> |
4 | <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th></tr> | 4 | <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th></tr> |
5 | <% for link in @block.links do %> | 5 | <% for link in @block.links do %> |
app/views/box_organizer/_raw_html_block.rhtml
app/views/box_organizer/add_block.rhtml
1 | -<% form_tag do %> | ||
2 | - | ||
3 | - <p><%= _('In what area do you want to put your new block?') %></p> | ||
4 | - | ||
5 | - <%# FIXME hardcoded stuff %> | ||
6 | - <%= select_tag('box_id', options_for_select(@boxes.select { |item| item.position != 1 }.map {|item| [ _("Area %d") % item.position, item.id]})) %> | ||
7 | - | ||
8 | - <p><%= _('Select the type of block you want to add to your page.') %></p> | ||
9 | - | ||
10 | - <% @block_types.in_groups_of(2) do |block1, block2| %> | ||
11 | - <div style='float: left; width: 48%; padding-top: 2px;'> | ||
12 | - <%= radio_button_tag('type', block1.name) %> | ||
13 | - <%= label_tag "type_#{block1.name.downcase}", block1.description %> | 1 | +<div style='height:350px'> |
2 | + <% form_tag do %> | ||
3 | + | ||
4 | + <p><%= _('In what area do you want to put your new block?') %></p> | ||
5 | + | ||
6 | + <% @boxes.each do |box| %> | ||
7 | + <%= labelled_radio_button(_("Area %d") % box.position, :box_id, box.id, box.central?, { :class => 'box-position', 'data-position' => box.position }) %> | ||
8 | + <% end %> | ||
9 | + | ||
10 | + <script type="text/javascript"> | ||
11 | + (function ($) { | ||
12 | + $(document).ready(function () { | ||
13 | + $(".box-position").live('change', function () { | ||
14 | + if ($(this).attr('data-position') == '1') { | ||
15 | + $('#center-block-types').show(); | ||
16 | + $('#side-block-types').hide(); | ||
17 | + } else { | ||
18 | + $('#center-block-types').hide(); | ||
19 | + $('#side-block-types').show(); | ||
20 | + }; | ||
21 | + }); | ||
22 | + })})(jQuery); | ||
23 | + </script> | ||
24 | + | ||
25 | + <p><%= _('Select the type of block you want to add to your page.') %></p> | ||
26 | + | ||
27 | + <div id='center-block-types'> | ||
28 | + <%= render :partial => 'block_types', :locals => { :block_types => @center_block_types } %> | ||
14 | </div> | 29 | </div> |
15 | - <% if block2 %> | ||
16 | - <div style='float: left; width: 48%; padding-top: 2px;'> | ||
17 | - <%= radio_button_tag('type', block2.name) %> | ||
18 | - <%= label_tag "type_#{block2.name.downcase}", block2.description %> | ||
19 | - </div> | 30 | + |
31 | + <div id='side-block-types' style='display:none'> | ||
32 | + <%= render :partial => 'block_types', :locals => { :block_types => @side_block_types } %> | ||
33 | + </div> | ||
34 | + | ||
35 | + <br style='clear: both'/> | ||
36 | + | ||
37 | + <% button_bar do %> | ||
38 | + <%= submit_button(:add, _("Add")) %> | ||
39 | + <%= colorbox_close_button(_('Close')) %> | ||
20 | <% end %> | 40 | <% end %> |
21 | - <% end %> | ||
22 | - <br style='clear: both'/> | ||
23 | - | ||
24 | - <% button_bar do %> | ||
25 | - <%= submit_button(:add, _("Add")) %> | ||
26 | - <%= lightbox_close_button(_('Close')) %> | ||
27 | - <% end %> | ||
28 | 41 | ||
29 | -<% end %> | 42 | + <% end %> |
43 | +</div> |
app/views/box_organizer/edit.rhtml
1 | -<h2><%= _('Editing block') %></h2> | 1 | +<div style='width: 500px;'> |
2 | + <h2><%= _('Editing block') %></h2> | ||
2 | 3 | ||
3 | -<% form_tag(:action => 'save', :id => @block.id) do %> | 4 | + <% form_tag(:action => 'save', :id => @block.id) do %> |
4 | 5 | ||
5 | - <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %> | 6 | + <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %> |
6 | 7 | ||
7 | - <%= render :partial => partial_for_class(@block.class) %> | 8 | + <%= render :partial => partial_for_class(@block.class) %> |
8 | 9 | ||
9 | - <%= labelled_form_field _('Display this block:'), '' %> | ||
10 | - <div style='margin-left: 10px'> | ||
11 | - <%= radio_button(:block, :display, 'always') %> | ||
12 | - <%= label_tag('block_display_always', _('In all pages')) %> | ||
13 | - <br/> | ||
14 | - <%= radio_button(:block, :display, 'home_page_only') %> | ||
15 | - <%= label_tag('block_display_home_page_only', _('Only in the homepage')) %> | ||
16 | - <br/> | ||
17 | - <%= radio_button(:block, :display, 'except_home_page') %> | ||
18 | - <%= label_tag('block_display_except_home_page', _('In all pages, except in the homepage')) %> | ||
19 | - <br/> | ||
20 | - <%= radio_button(:block, :display, 'never') %> | ||
21 | - <%= label_tag('block_display_never', _("Don't display")) %> | ||
22 | - </div> | 10 | + <%= labelled_form_field _('Display this block:'), '' %> |
11 | + <div style='margin-left: 10px'> | ||
12 | + <%= radio_button(:block, :display, 'always') %> | ||
13 | + <%= label_tag('block_display_always', _('In all pages')) %> | ||
14 | + <br/> | ||
15 | + <%= radio_button(:block, :display, 'home_page_only') %> | ||
16 | + <%= label_tag('block_display_home_page_only', _('Only in the homepage')) %> | ||
17 | + <br/> | ||
18 | + <%= radio_button(:block, :display, 'except_home_page') %> | ||
19 | + <%= label_tag('block_display_except_home_page', _('In all pages, except in the homepage')) %> | ||
20 | + <br/> | ||
21 | + <%= radio_button(:block, :display, 'never') %> | ||
22 | + <%= label_tag('block_display_never', _("Don't display")) %> | ||
23 | + </div> | ||
23 | 24 | ||
24 | - <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + Noosfero.locales.map {|key, value| [value, key]} )) %> | 25 | + <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %> |
25 | 26 | ||
26 | - <% button_bar do %> | ||
27 | - <%= submit_button(:save, _('Save')) %> | ||
28 | - <%= lightbox_close_button(_('Cancel')) %> | ||
29 | - <% end %> | 27 | + <% button_bar do %> |
28 | + <%= submit_button(:save, _('Save')) %> | ||
29 | + <%= colorbox_close_button(_('Cancel')) %> | ||
30 | + <% end %> | ||
30 | 31 | ||
31 | -<% end %> | 32 | + <% end %> |
33 | +</div> |
app/views/box_organizer/index.rhtml
1 | <h1><%= _('Editing sideboxes')%></h1> | 1 | <h1><%= _('Editing sideboxes')%></h1> |
2 | 2 | ||
3 | <% button_bar do %> | 3 | <% button_bar do %> |
4 | - <%= lightbox_button('add', _('Add a block'), { :action => 'add_block' }) %> | 4 | + <%= colorbox_button('add', _('Add a block'), { :action => 'add_block' }) %> |
5 | <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> | 5 | <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> |
6 | <% end %> | 6 | <% end %> |
app/views/catalog/index.rhtml
@@ -30,6 +30,9 @@ | @@ -30,6 +30,9 @@ | ||
30 | <li class="product <%= status.join(' ') %>"> | 30 | <li class="product <%= status.join(' ') %>"> |
31 | <ul> | 31 | <ul> |
32 | <li class="product-image-link"> | 32 | <li class="product-image-link"> |
33 | + <% if product.highlighted? %> | ||
34 | + <%= link_to image_tag(themed_path('/images/star.png'), :class => 'star', :alt => _('Highlighted product')), product_path(product) %> | ||
35 | + <% end %> | ||
33 | <% if product.image %> | 36 | <% if product.image %> |
34 | <div class="zoomable-image"> | 37 | <div class="zoomable-image"> |
35 | <%= link_to_product product, :class => 'product-big', :style => "background-image: url(#{product.default_image(:big)})" %> | 38 | <%= link_to_product product, :class => 'product-big', :style => "background-image: url(#{product.default_image(:big)})" %> |
app/views/cms/_blog.rhtml
@@ -62,7 +62,7 @@ | @@ -62,7 +62,7 @@ | ||
62 | 62 | ||
63 | <% f.fields_for 'feed', @article.feed do |feed| %> | 63 | <% f.fields_for 'feed', @article.feed do |feed| %> |
64 | <%= labelled_form_field(_('Limit of posts in RSS Feed'), feed.select(:limit, [5, 10, 20, 50])) %> | 64 | <%= labelled_form_field(_('Limit of posts in RSS Feed'), feed.select(:limit, [5, 10, 20, 50])) %> |
65 | - <%= labelled_form_field(_('Include in RSS Feed only posts from language:'), feed.select(:language, [[_('All'), nil ]] + Noosfero.locales.map { |k,v| [v, k]})) %> | 65 | + <%= labelled_form_field(_('Include in RSS Feed only posts from language:'), feed.select(:language, [[_('All'), nil ]] + environment.locales.map { |k,v| [v, k]})) %> |
66 | <% end %> | 66 | <% end %> |
67 | 67 | ||
68 | <% f.fields_for 'external_feed_builder', @article.external_feed do |efeed| %> | 68 | <% f.fields_for 'external_feed_builder', @article.external_feed do |efeed| %> |
app/views/cms/_general_fields.html.erb
1 | +<%= select_profile_folder(_('Parent folder:'), 'article[parent_id]', profile, @article.parent_id) %> | ||
1 | <%= labelled_form_field(_('License'), select(:article, :license_id, options_for_select_with_title([[_('None'), nil]] + profile.environment.licenses.map {|license| [license.name, license.id]}, @article.license ? @article.license.id : nil))) %> | 2 | <%= labelled_form_field(_('License'), select(:article, :license_id, options_for_select_with_title([[_('None'), nil]] + profile.environment.licenses.map {|license| [license.name, license.id]}, @article.license ? @article.license.id : nil))) %> |
app/views/cms/_rss_feed.rhtml
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | 6 | ||
7 | <%= required labelled_form_field(_('Limit of articles'), text_field(:article, :limit)) %> | 7 | <%= required labelled_form_field(_('Limit of articles'), text_field(:article, :limit)) %> |
8 | 8 | ||
9 | -<%= labelled_form_field(_('Include in RSS Feed only posts from language:'), f.select(:language, [[_('All'), nil ]] + Noosfero.locales.map { |k,v| [v, k]})) %> | 9 | +<%= labelled_form_field(_('Include in RSS Feed only posts from language:'), f.select(:language, [[_('All'), nil ]] + environment.locales.map { |k,v| [v, k]})) %> |
10 | 10 | ||
11 | <%= labelled_form_field(_('Use as item description:'), select(:article, :feed_item_description, [ [ _('Article abstract'), 'abstract'], [ _('Article body'), 'body']])) %> | 11 | <%= labelled_form_field(_('Use as item description:'), select(:article, :feed_item_description, [ [ _('Article abstract'), 'abstract'], [ _('Article body'), 'body']])) %> |
12 | 12 |
app/views/cms/_text_editor_sidebar.rhtml
@@ -9,8 +9,7 @@ | @@ -9,8 +9,7 @@ | ||
9 | <div id='media-upload-form'> | 9 | <div id='media-upload-form'> |
10 | <% form_tag({ :action => 'media_upload' }, :multipart => true) do %> | 10 | <% form_tag({ :action => 'media_upload' }, :multipart => true) do %> |
11 | <div class='formfield'> | 11 | <div class='formfield'> |
12 | - <%# TODO duplicated from partial upload_file_form %> | ||
13 | - <%= labelled_form_field(_('Choose folder to upload files:'), select_tag('parent_id', options_for_select([[profile.identifier, '']] + profile.folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] }))) %> | 12 | + <%= select_profile_folder(_('Choose folder to upload files:'), :parent_id, profile) %> |
14 | </div> | 13 | </div> |
15 | <p><%= file_field_tag('file1') %></p> | 14 | <p><%= file_field_tag('file1') %></p> |
16 | <p><%= file_field_tag('file2') %></p> | 15 | <p><%= file_field_tag('file2') %></p> |
app/views/cms/_upload_file_form.rhtml
1 | <% if @parent %> | 1 | <% if @parent %> |
2 | <%= hidden_field_tag('parent_id', @parent.id) %> | 2 | <%= hidden_field_tag('parent_id', @parent.id) %> |
3 | <% else %> | 3 | <% else %> |
4 | - <%= labelled_form_field(_('Choose folder to upload files:'), select_tag('parent_id', options_for_select([[profile.identifier, '']] + @folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] }))) %> | 4 | + <%= select_profile_folder(_('Choose folder to upload files:'), :parent_id, profile) %> |
5 | <% end %> | 5 | <% end %> |
6 | 6 | ||
7 | <div id='uploaded_files'> | 7 | <div id='uploaded_files'> |
app/views/cms/_uploaded_file.rhtml
1 | <%= labelled_form_field(_('Title'), text_field(:article, :title, :maxlength => 60)) %> | 1 | <%= labelled_form_field(_('Title'), text_field(:article, :title, :maxlength => 60)) %> |
2 | + | ||
3 | +<%= render :partial => 'general_fields' %> | ||
4 | + | ||
2 | <%= labelled_form_field(_('Description'), text_area(:article, :abstract, :rows => 3, :cols => 64)) %> | 5 | <%= labelled_form_field(_('Description'), text_area(:article, :abstract, :rows => 3, :cols => 64)) %> |
3 | <% if @article.image? %> | 6 | <% if @article.image? %> |
4 | <%= f.text_field(:external_link, :size => 64) %> | 7 | <%= f.text_field(:external_link, :size => 64) %> |
app/views/contact/new.rhtml
1 | -<h1><%= _('Send an e-mail to %s') % profile.name %></h1> | 1 | +<% if profile.person? %> |
2 | + <h1><%= _('Send an e-mail to %s') % profile.name %></h1> | ||
3 | +<% else %> | ||
4 | + <h1><%= _('Send an e-mail to administrators') %></h1> | ||
2 | 5 | ||
3 | -<%= error_messages_for 'contact' %> | 6 | + <div class='tooltip'><%= _("The e-mail will be sent to the administrators of '%s'") % profile.name %></div> |
7 | +<% end %> | ||
4 | 8 | ||
9 | +<%= error_messages_for 'contact' %> | ||
5 | 10 | ||
6 | <% labelled_form_for :contact, @contact do |f| %> | 11 | <% labelled_form_for :contact, @contact do |f| %> |
7 | <%= hidden_field_tag(:confirm, 'false') %> | 12 | <%= hidden_field_tag(:confirm, 'false') %> |
app/views/features/index.rhtml
@@ -26,17 +26,12 @@ Check all the features you want to enable for your environment, uncheck all the | @@ -26,17 +26,12 @@ Check all the features you want to enable for your environment, uncheck all the | ||
26 | 26 | ||
27 | <h2><%= _('Configure features') %></h2> | 27 | <h2><%= _('Configure features') %></h2> |
28 | 28 | ||
29 | -<table> | ||
30 | - <tr> | ||
31 | - <th><%= _('Option') %></th> | ||
32 | - <th><%= _('Choice') %></th> | ||
33 | - </tr> | ||
34 | - <tr> | ||
35 | - <td><%= _('Organization Approval Method') %></td> | ||
36 | - <td><%= select_organization_approval_method('environment', 'organization_approval_method') %></td> | ||
37 | - </tr> | ||
38 | -</table> | ||
39 | - | 29 | +<h3><%= _('Page to redirect after login') %></h3> |
30 | + <%= select 'environment', 'redirection_after_login', Environment.login_redirection_options.map{|key,value|[value,key]} %> | ||
31 | +<hr/> | ||
32 | +<h3><%= _('Organization Approval Method') %></h3> | ||
33 | + <%= select_organization_approval_method('environment', 'organization_approval_method') %> | ||
34 | +<hr/> | ||
40 | 35 | ||
41 | <div> | 36 | <div> |
42 | <% button_bar do %> | 37 | <% button_bar do %> |
app/views/layouts/_javascript.rhtml
@@ -2,7 +2,8 @@ | @@ -2,7 +2,8 @@ | ||
2 | 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox', | 2 | 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox', |
3 | 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate', | 3 | 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate', |
4 | 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', | 4 | 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', |
5 | -'add-and-join', 'report-abuse', 'catalog', 'manage-products', :cache => 'cache-general' %> | 5 | +'add-and-join', 'report-abuse', 'catalog', 'manage-products', |
6 | +'jquery-ui-timepicker-addon', :cache => 'cache-general' %> | ||
6 | 7 | ||
7 | <% language = FastGettext.locale %> | 8 | <% language = FastGettext.locale %> |
8 | <% %w{messages methods}.each do |type| %> | 9 | <% %w{messages methods}.each do |type| %> |
app/views/layouts/application-ng.rhtml
@@ -56,10 +56,18 @@ | @@ -56,10 +56,18 @@ | ||
56 | <%= usermenu_logged_in %> | 56 | <%= usermenu_logged_in %> |
57 | </span> | 57 | </span> |
58 | <span class='not-logged-in' style='display: none'> | 58 | <span class='not-logged-in' style='display: none'> |
59 | - <%= _("<span class='login'>%s</span> <span class='or'>or</span> <span class='signup'>%s</span>") % [thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login'), link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup') ] %> | 59 | + |
60 | + <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %> | ||
61 | + <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_eval(&content) }.join("") %> | ||
62 | + | ||
60 | <div id='inlineLoginBox' style='display: none;'> | 63 | <div id='inlineLoginBox' style='display: none;'> |
61 | <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> | 64 | <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> |
62 | </div> | 65 | </div> |
66 | + | ||
67 | + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> | ||
68 | + <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%> | ||
69 | + <% end %> | ||
70 | + | ||
63 | </span> | 71 | </span> |
64 | <form action="/search" class="search_form" method="get" class="clean"> | 72 | <form action="/search" class="search_form" method="get" class="clean"> |
65 | <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> | 73 | <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> |
app/views/layouts/application.rhtml
@@ -80,7 +80,7 @@ | @@ -80,7 +80,7 @@ | ||
80 | </div><!-- id='navigation_bar' --> | 80 | </div><!-- id='navigation_bar' --> |
81 | 81 | ||
82 | <div id="language-selector"> | 82 | <div id="language-selector"> |
83 | - <%= language_chooser(:element => 'dropdown') %> | 83 | + <%= language_chooser(environment, :element => 'dropdown') %> |
84 | </div> | 84 | </div> |
85 | 85 | ||
86 | <div id="user_box"> | 86 | <div id="user_box"> |
app/views/profile/_common.rhtml
1 | - | ||
2 | -<script type="text/javascript"> | ||
3 | - jQuery( function() { | ||
4 | - var parent_selector = '.profile-wall-description, .profile-activity-description, .profile-network-description'; | ||
5 | - var child_selector = '.icon-delete, .icon-reply'; | ||
6 | - jQuery(parent_selector).live('mouseover', function () { jQuery(this).find(child_selector).css('visibility', 'visible'); }); | ||
7 | - jQuery(parent_selector).live('mouseout', function () { jQuery(this).find(child_selector).css('visibility', 'hidden'); }); | ||
8 | - }); | ||
9 | -</script> | ||
10 | - | ||
11 | <% unless @action %> | 1 | <% unless @action %> |
12 | <% cache_timeout(profile.cache_key + '-profile-general-info', 4.hours) do %> | 2 | <% cache_timeout(profile.cache_key + '-profile-general-info', 4.hours) do %> |
13 | <tr> | 3 | <tr> |
app/views/profile/_person_profile.rhtml
@@ -13,31 +13,16 @@ | @@ -13,31 +13,16 @@ | ||
13 | <td><%= show_date(profile.created_at) %></td> | 13 | <td><%= show_date(profile.created_at) %></td> |
14 | </tr> | 14 | </tr> |
15 | 15 | ||
16 | - <% if profile == user || profile.friends.include?(user) %> | ||
17 | - <tr> | ||
18 | - <th colspan='2'><%= _('Contact')%></th> | ||
19 | - </tr> | ||
20 | - <%= display_field(_('Address:'), profile, :address) %> | ||
21 | - <%= display_field(_('ZIP code:'), profile, :zip_code) %> | ||
22 | - <%= display_field(_('Contact phone:'), profile, :contact_phone) %> | ||
23 | - <%= display_field(_('e-Mail:'), profile, :email, true) { |email| link_to_email(email) } %> | ||
24 | - <% end %> | 16 | + <%= display_contact profile %> |
25 | 17 | ||
26 | <% cache_timeout(profile.relationships_cache_key, 4.hours) do %> | 18 | <% cache_timeout(profile.relationships_cache_key, 4.hours) do %> |
27 | - <% if !(profile.organization.blank? && profile.organization_website.blank?) && (profile.active_fields.include?('organization') || profile.active_fields.include?('organization_website')) %> | ||
28 | - <tr> | ||
29 | - <th colspan='2'><%= _('Work')%></th> | ||
30 | - </tr> | ||
31 | - <% end %> | ||
32 | - <%= display_field(_('Organization:'), profile, :organization) %> | ||
33 | - <%= display_field(_('Organization website:'), profile, :organization_website) { |url| link_to(url, url) }%> | ||
34 | - | 19 | + <%= display_work_info profile %> |
35 | 20 | ||
36 | <% if !environment.enabled?('disable_asset_enterprises') && !profile.enterprises.empty? %> | 21 | <% if !environment.enabled?('disable_asset_enterprises') && !profile.enterprises.empty? %> |
37 | <tr> | 22 | <tr> |
38 | <th colspan='2'><%= __('Enterprises') %></th> | 23 | <th colspan='2'><%= __('Enterprises') %></th> |
39 | </tr> | 24 | </tr> |
40 | - <% profile.enterprises.each do |item| %> | 25 | + <% profile.enterprises.includes(:environment,:domains, :preferred_domain).each do |item| %> |
41 | <tr> | 26 | <tr> |
42 | <td></td> | 27 | <td></td> |
43 | <td><%= button 'menu-enterprise', item.name, item.url %></td> | 28 | <td><%= button 'menu-enterprise', item.name, item.url %></td> |
@@ -59,6 +44,6 @@ | @@ -59,6 +44,6 @@ | ||
59 | 44 | ||
60 | <%= render :partial => 'common' %> | 45 | <%= render :partial => 'common' %> |
61 | 46 | ||
62 | - </table> | ||
63 | -<% end %> | 47 | + <% end %> |
48 | +</table> | ||
64 | 49 |
app/views/profile/members.rhtml
@@ -16,8 +16,13 @@ | @@ -16,8 +16,13 @@ | ||
16 | 16 | ||
17 | <% button_bar do %> | 17 | <% button_bar do %> |
18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> | 18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> |
19 | - <% if profile.community? and user and user.has_permission?(:invite_members, profile) %> | ||
20 | - <%= button :search, _('Invite your friends to join %s') % profile.name, :controller => 'invite', :action => 'select_address_book' %> | 19 | + <% if profile.community? and user %> |
20 | + <% if user.has_permission?(:invite_members, profile) %> | ||
21 | + <%= button :search, _('Invite your friends to join %s') % profile.name, :controller => 'invite', :action => 'select_address_book' %> | ||
22 | + <% end %> | ||
23 | + <% if user.has_permission?(:send_mail_to_members, profile) %> | ||
24 | + <%= button :send, _('Send e-mail to members'), :controller => 'profile', :action => 'send_mail' %> | ||
25 | + <% end %> | ||
21 | <% end %> | 26 | <% end %> |
22 | <% end %> | 27 | <% end %> |
23 | 28 |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +<h1><%= h profile.short_name(50) %></h1> | ||
2 | + | ||
3 | +<h2><%= _('Send e-mail to members') %></h2> | ||
4 | + | ||
5 | +<%= error_messages_for :mailing %> | ||
6 | + | ||
7 | +<%= render :file => 'shared/tiny_mce' %> | ||
8 | + | ||
9 | +<% form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %> | ||
10 | + <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> | ||
11 | + <%= labelled_form_field(_('Body:'), f.text_area(:body, :class => 'mceEditor')) %> | ||
12 | + <%= submit_button(:send, _('Send')) %> | ||
13 | + <%= button :cancel, _('Cancel e-mail'), :back %> | ||
14 | +<% end %> |
app/views/profile_editor/_person.rhtml
@@ -2,9 +2,19 @@ | @@ -2,9 +2,19 @@ | ||
2 | 2 | ||
3 | <%= required_fields_message %> | 3 | <%= required_fields_message %> |
4 | 4 | ||
5 | - <%= required f.text_field(:name) %> | 5 | + <div class="field-with-privacy-selector"> |
6 | + <%= required f.text_field(:name) %> | ||
7 | + <div class="field-privacy-selector"> | ||
8 | + <%= unchangeable_privacy_field @profile %> | ||
9 | + </div> | ||
10 | + </div> | ||
6 | 11 | ||
7 | - <%= required f.text_field(:email) %> | 12 | + <div class="field-with-privacy-selector"> |
13 | + <%= required f.text_field(:email) %> | ||
14 | + <div class="field-privacy-selector"> | ||
15 | + <%= profile_field_privacy_selector @profile, 'email' %> | ||
16 | + </div> | ||
17 | + </div> | ||
8 | 18 | ||
9 | <%= @plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_eval(&content) }.join("") %> | 19 | <%= @plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_eval(&content) }.join("") %> |
10 | 20 |
app/views/profile_editor/_person_form.rhtml
@@ -61,11 +61,3 @@ | @@ -61,11 +61,3 @@ | ||
61 | <%= optional_field(@person, 'professional_activity', f.text_field(:professional_activity, :rel => _('Professional activity'))) %> | 61 | <%= optional_field(@person, 'professional_activity', f.text_field(:professional_activity, :rel => _('Professional activity'))) %> |
62 | <%= optional_field(@person, 'organization', f.text_field(:organization, :rel => _('Organization'))) %> | 62 | <%= optional_field(@person, 'organization', f.text_field(:organization, :rel => _('Organization'))) %> |
63 | <%= optional_field(@person, 'organization_website', f.text_field(:organization_website, :rel => _('Organization website'))) %> | 63 | <%= optional_field(@person, 'organization_website', f.text_field(:organization_website, :rel => _('Organization website'))) %> |
64 | - | ||
65 | -<% optional_field(@person, 'image') do %> | ||
66 | - <div id="profile_choose_picture"> | ||
67 | - <% f.fields_for :image_builder, @person.image do |i| %> | ||
68 | - <%= file_field_or_thumbnail(_('Image:'), @person.image, i) %><span class="person_image_maxsize"><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %></span> | ||
69 | - <% end %> | ||
70 | - </div> | ||
71 | -<% end %> |
app/views/profile_editor/edit.rhtml
@@ -12,73 +12,37 @@ | @@ -12,73 +12,37 @@ | ||
12 | 12 | ||
13 | <%= render :partial => partial_for_class(@profile.class), :locals => { :f => f } %> | 13 | <%= render :partial => partial_for_class(@profile.class), :locals => { :f => f } %> |
14 | 14 | ||
15 | - <% unless @profile.person? && @environment.active_person_fields.include?('image') %> | ||
16 | - <div id="profile_change_picture"> | 15 | + <div id="profile_change_picture_title"> |
17 | <h2><%= _('Change picture') %></h2> | 16 | <h2><%= _('Change picture') %></h2> |
17 | + <span><%= unchangeable_privacy_field @profile %></span> | ||
18 | + </div> | ||
19 | + <div id="profile_change_picture"> | ||
18 | <% f.fields_for :image_builder, @profile.image do |i| %> | 20 | <% f.fields_for :image_builder, @profile.image do |i| %> |
19 | <%= 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)")% Image.max_size.to_humanreadable %> |
20 | <% end %> | 22 | <% end %> |
21 | </div> | 23 | </div> |
22 | - <% end %> | ||
23 | 24 | ||
24 | <h2><%= _('Privacy options') %></h2> | 25 | <h2><%= _('Privacy options') %></h2> |
25 | 26 | ||
26 | <% if profile.person? %> | 27 | <% if profile.person? %> |
27 | - <table> | ||
28 | - <tr> | ||
29 | - <th style='text-align: right;'> | ||
30 | - <%= _('This profile is:') %> | ||
31 | - </th> | ||
32 | - <th> | ||
33 | - <%= radio_button 'profile_data', 'public_profile', 'true' %> | ||
34 | - <label for="profile_data_public_profile_true"><u><%= _('Public') %></u></label> | ||
35 | - </th> | ||
36 | - <th style='padding: 2px 10px 2px 2px;'> | ||
37 | - <%= radio_button 'profile_data', 'public_profile', 'false' %> | ||
38 | - <label for="profile_data_public_profile_false"><u><%= _('Private') %></u></label> | ||
39 | - </th> | ||
40 | - </tr> | ||
41 | - <tr> | ||
42 | - <td> <%= _('Activate Intranet access (restricted area only for me)') %> </td><td><%= _('Yes') %></td><td><%= _('Yes') %></td> | ||
43 | - </tr> | ||
44 | - <tr> | ||
45 | - <td> <%= _('Include my contact in directory of people') %> </td><td><%= _('Yes') %></td><td><%= _('Yes') %></td> | ||
46 | - </tr> | ||
47 | - <tr> | ||
48 | - <td> <%= _('Show my contents to all internet users') %> </td><td><%= _('Yes') %></td><td><%= _('No') %></td> | ||
49 | - </tr> | ||
50 | - <tr> | ||
51 | - <td> <%= _('Show my contents to my friends (person)') %> </td><td><%= _('Yes') %></td><td><%= _('Yes') %></td> | ||
52 | - </tr> | ||
53 | - </table> | 28 | + <div> |
29 | + <%= labelled_radio_button _('Public — show my contents to all internet users'), 'profile_data[public_profile]', true, @profile.public_profile? %> | ||
30 | + </div> | ||
31 | + <div> | ||
32 | + <%= labelled_radio_button _('Private — show my contents only to friends'), 'profile_data[public_profile]', false, !@profile.public_profile? %> | ||
33 | + </div> | ||
54 | <% else %> | 34 | <% else %> |
55 | - <table> | ||
56 | - <tr> | ||
57 | - <th style='text-align: right;'> | ||
58 | - <%= _('This profile is:') %> | ||
59 | - </th> | ||
60 | - <th> | ||
61 | - <%= radio_button 'profile_data', 'public_profile', 'true' %> | ||
62 | - <label for="profile_data_public_profile_true"><u><%= _('Public') %></u></label> | ||
63 | - </th> | ||
64 | - <th style='padding: 2px 10px 2px 2px;'> | ||
65 | - <%= radio_button 'profile_data', 'public_profile', 'false' %> | ||
66 | - <label for="profile_data_public_profile_false"><u><%= _('Private') %></u></label> | ||
67 | - </th> | ||
68 | - </tr> | ||
69 | - <tr> | ||
70 | - <td> <%= _('Activate Intranet access (restricted area only for members)') %> </td><td><%= _('Yes') %></td><td><%= _('Yes') %></td> | ||
71 | - </tr> | ||
72 | - <tr> | ||
73 | - <td> <%= _('Include this group directory of groups') %> </td><td><%= _('Yes') %></td><td><%= _('Yes') %></td> | ||
74 | - </tr> | ||
75 | - <tr> | ||
76 | - <td> <%= _('Show content of this group to all internet users') %> </td><td><%= _('Yes') %></td><td><%= _('No') %></td> | ||
77 | - </tr> | ||
78 | - <tr> | ||
79 | - <td> <%= _('Show content of this group to members') %> </td><td><%= _('Yes') %></td><td><%= _('Yes') %></td> | ||
80 | - </tr> | ||
81 | - </table> | 35 | + <div> |
36 | + <%= labelled_radio_button _('Public — show content of this group to all internet users'), 'profile_data[public_profile]', true, @profile.public_profile? %> | ||
37 | + </div> | ||
38 | + <div> | ||
39 | + <%= labelled_radio_button _('Private — show content of this group only to members'), 'profile_data[public_profile]', false, !@profile.public_profile? %> | ||
40 | + </div> | ||
41 | + <% end %> | ||
42 | + | ||
43 | + <% if environment.enabled?('allow_change_of_redirection_after_login') %> | ||
44 | + <h2><%= _('Page to redirect after login') %></h2> | ||
45 | + <%= select 'profile_data', 'redirection_after_login', Environment.login_redirection_options.map{|key,value|[value,key]}, { :selected => @profile.preferred_login_redirection} %> | ||
82 | <% end %> | 46 | <% end %> |
83 | 47 | ||
84 | <h2><%= _('Translations') %></h2> | 48 | <h2><%= _('Translations') %></h2> |
app/views/profile_members/_index_buttons.rhtml
@@ -4,7 +4,9 @@ | @@ -4,7 +4,9 @@ | ||
4 | <% if profile.community? and user.has_permission?(:invite_members, profile) %> | 4 | <% if profile.community? and user.has_permission?(:invite_members, profile) %> |
5 | <%= button :search, _('Invite your friends to join %s') % profile.short_name, :controller => 'invite', :action => 'select_address_book' %> | 5 | <%= button :search, _('Invite your friends to join %s') % profile.short_name, :controller => 'invite', :action => 'select_address_book' %> |
6 | <% end %> | 6 | <% end %> |
7 | - <%= button :send, _('Send e-mail to members'), :action => 'send_mail' %> | 7 | + <% if profile.community? and user.has_permission?(:send_mail_to_members, profile) %> |
8 | + <%= button :send, _('Send e-mail to members'), :controller => 'profile', :action => 'send_mail' %> | ||
9 | + <% end %> | ||
8 | <% @plugins.dispatch(:manage_members_extra_buttons).each do |plugin_button| %> | 10 | <% @plugins.dispatch(:manage_members_extra_buttons).each do |plugin_button| %> |
9 | <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url] %> | 11 | <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url] %> |
10 | <% end %> | 12 | <% end %> |
app/views/profile_members/send_mail.rhtml
@@ -1,14 +0,0 @@ | @@ -1,14 +0,0 @@ | ||
1 | -<h1><%= h profile.short_name(50) %></h1> | ||
2 | - | ||
3 | -<h2><%= _('Send e-mail to members') %></h2> | ||
4 | - | ||
5 | -<%= error_messages_for :mailing %> | ||
6 | - | ||
7 | -<%= render :file => 'shared/tiny_mce' %> | ||
8 | - | ||
9 | -<% form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %> | ||
10 | - <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> | ||
11 | - <%= labelled_form_field(_('Body:'), f.text_area(:body, :class => 'mceEditor')) %> | ||
12 | - <%= submit_button(:send, _('Send')) %> | ||
13 | - <%= button :cancel, _('Cancel e-mail'), :action => 'index' %> | ||
14 | -<% end %> |
app/views/search/_product.rhtml
1 | <% extra_content = @plugins.dispatch(:asset_product_extras, product, product.enterprise).collect { |content| instance_eval(&content) } %> | 1 | <% extra_content = @plugins.dispatch(:asset_product_extras, product, product.enterprise).collect { |content| instance_eval(&content) } %> |
2 | <% extra_properties = @plugins.dispatch(:asset_product_properties, product)%> | 2 | <% extra_properties = @plugins.dispatch(:asset_product_properties, product)%> |
3 | 3 | ||
4 | -<li class="search-product-item"> | 4 | +<li class="search-product-item <%= 'highlighted' if product.highlighted? %>"> |
5 | 5 | ||
6 | <div class="search-product-item-first-column"> | 6 | <div class="search-product-item-first-column"> |
7 | <%= render :partial => 'search/image', :object => product %> | 7 | <%= render :partial => 'search/image', :object => product %> |
app/views/tasks/_approve_article_accept_details.rhtml
1 | <%= render :file => 'shared/tiny_mce' %> | 1 | <%= render :file => 'shared/tiny_mce' %> |
2 | 2 | ||
3 | <%= labelled_form_field(_('Name for publishing'), f.text_field(:name)) %> | 3 | <%= labelled_form_field(_('Name for publishing'), f.text_field(:name)) %> |
4 | -<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task]", 'article_parent_id', task.target) %> | 4 | +<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article_parent_id]", task.target) %> |
5 | <%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %> | 5 | <%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %> |
6 | 6 | ||
7 | <% tiny = task.article && task.article.tiny_mce? ? {:tiny_mce => true} : {} %> | 7 | <% tiny = task.article && task.article.tiny_mce? ? {:tiny_mce => true} : {} %> |
app/views/tasks/_suggest_article_accept_details.rhtml
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | <%= labelled_form_field(_('Source'), f.text_field(:source_name)) %> | 6 | <%= labelled_form_field(_('Source'), f.text_field(:source_name)) %> |
7 | <%= labelled_form_field(_("Source URL"), f.text_field(:source)) %> | 7 | <%= labelled_form_field(_("Source URL"), f.text_field(:source)) %> |
8 | 8 | ||
9 | -<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task]", 'article_parent_id', task.target) %> | 9 | +<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article_parent_id]", task.target) %> |
10 | <%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %> | 10 | <%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %> |
11 | 11 | ||
12 | <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => f, :abstract_method => 'article_abstract', :body_method => 'article_body', :lead_id => task.id} %> | 12 | <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => f, :abstract_method => 'article_abstract', :body_method => 'article_body', :lead_id => task.id} %> |
app/views/tasks/_task.rhtml
@@ -50,13 +50,13 @@ | @@ -50,13 +50,13 @@ | ||
50 | <% fields_for "tasks[#{task.id}][task]", task do |f| %> | 50 | <% fields_for "tasks[#{task.id}][task]", task do |f| %> |
51 | <% if task.accept_details %> | 51 | <% if task.accept_details %> |
52 | <div id="on-accept-information-<%=task.id%>" style="display: none"> | 52 | <div id="on-accept-information-<%=task.id%>" style="display: none"> |
53 | - <%= render :partial => partial_for_task_class(task.class, :accept_details), :locals => {:task => task, :f => f} %> | 53 | + <%= render :partial => partial_for_class(task.class, :accept_details), :locals => {:task => task, :f => f} %> |
54 | </div> | 54 | </div> |
55 | <% end %> | 55 | <% end %> |
56 | 56 | ||
57 | <% if task.reject_details %> | 57 | <% if task.reject_details %> |
58 | <div id="on-reject-information-<%=task.id%>" style="display: none"> | 58 | <div id="on-reject-information-<%=task.id%>" style="display: none"> |
59 | - <%= render :partial => partial_for_task_class(task.class, :reject_details), :locals => {:task => task, :f => f} %> | 59 | + <%= render :partial => partial_for_class(task.class, :reject_details), :locals => {:task => task, :f => f} %> |
60 | </div> | 60 | </div> |
61 | <% end %> | 61 | <% end %> |
62 | <% end %> | 62 | <% end %> |
config/routes.rb
@@ -19,16 +19,17 @@ ActionController::Routing::Routes.draw do |map| | @@ -19,16 +19,17 @@ ActionController::Routing::Routes.draw do |map| | ||
19 | 19 | ||
20 | # -- just remember to delete public/index.html. | 20 | # -- just remember to delete public/index.html. |
21 | # You can have the root of your site routed by hooking up '' | 21 | # You can have the root of your site routed by hooking up '' |
22 | + map.root :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | ||
22 | map.connect '', :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | 23 | map.connect '', :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } |
23 | map.home 'site/:action', :controller => 'home' | 24 | map.home 'site/:action', :controller => 'home' |
24 | 25 | ||
25 | - map.connect 'images/*stuff', :controller => 'not_found', :action => 'index' | ||
26 | - map.connect 'stylesheets/*stuff', :controller => 'not_found', :action => 'index' | ||
27 | - map.connect 'designs/*stuff', :controller => 'not_found', :action => 'index' | ||
28 | - map.connect 'articles/*stuff', :controller => 'not_found', :action => 'index' | ||
29 | - map.connect 'javascripts/*stuff', :controller => 'not_found', :action => 'index' | ||
30 | - map.connect 'thumbnails/*stuff', :controller => 'not_found', :action => 'index' | ||
31 | - map.connect 'user_themes/*stuff', :controller => 'not_found', :action => 'index' | 26 | + map.connect 'images/*stuff', :controller => 'not_found', :action => 'nothing' |
27 | + map.connect 'stylesheets/*stuff', :controller => 'not_found', :action => 'nothing' | ||
28 | + map.connect 'designs/*stuff', :controller => 'not_found', :action => 'nothing' | ||
29 | + map.connect 'articles/*stuff', :controller => 'not_found', :action => 'nothing' | ||
30 | + map.connect 'javascripts/*stuff', :controller => 'not_found', :action => 'nothing' | ||
31 | + map.connect 'thumbnails/*stuff', :controller => 'not_found', :action => 'nothing' | ||
32 | + map.connect 'user_themes/*stuff', :controller => 'not_found', :action => 'nothing' | ||
32 | 33 | ||
33 | # online documentation | 34 | # online documentation |
34 | map.doc 'doc', :controller => 'doc', :action => 'index' | 35 | map.doc 'doc', :controller => 'doc', :action => 'index' |
db/migrate/20120823215007_add_languages_and_default_language_to_environment.rb
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +class AddLanguagesAndDefaultLanguageToEnvironment < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + add_column :environments, :languages, :string | ||
4 | + add_column :environments, :default_language, :string | ||
5 | + end | ||
6 | + | ||
7 | + def self.down | ||
8 | + remove_column :environments, :languages | ||
9 | + remove_column :environments, :default_language | ||
10 | + end | ||
11 | +end |
db/migrate/20120824165019_add_permission_for_send_mail_to_members_to_admin_and_moderator_roles.rb
0 → 100644
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +class AddPermissionForSendMailToMembersToAdminAndModeratorRoles < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + Environment.all.map(&:id).each do |id| | ||
4 | + role = Profile::Roles.admin(id) | ||
5 | + role.permissions += ['send_mail_to_members'] | ||
6 | + role.save! | ||
7 | + role = Profile::Roles.moderator(id) | ||
8 | + role.permissions += ['send_mail_to_members'] | ||
9 | + role.save! | ||
10 | + end | ||
11 | + end | ||
12 | + | ||
13 | + def self.down | ||
14 | + Environment.all.map(&:id).each do |id| | ||
15 | + role = Profile::Roles.admin(id) | ||
16 | + role.permissions -= ['send_mail_to_members'] | ||
17 | + role.save! | ||
18 | + role = Profile::Roles.moderator(id) | ||
19 | + role.permissions -= ['send_mail_to_members'] | ||
20 | + role.save! | ||
21 | + end | ||
22 | + end | ||
23 | +end |
db/migrate/20120824183534_add_redirection_after_login_to_environment.rb
0 → 100644
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +class AddRedirectionAfterLoginToEnvironment < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + add_column :environments, :redirection_after_login, :string, :default => 'keep_on_same_page' | ||
4 | + end | ||
5 | + | ||
6 | + def self.down | ||
7 | + remove_column :environments, :redirection_after_login | ||
8 | + end | ||
9 | +end |
db/migrate/20120824184046_add_redirection_after_login_to_profiles.rb
0 → 100644
db/schema.rb
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | # | 9 | # |
10 | # It's strongly recommended to check this file into your version control system. | 10 | # It's strongly recommended to check this file into your version control system. |
11 | 11 | ||
12 | -ActiveRecord::Schema.define(:version => 20120825185219) do | 12 | +ActiveRecord::Schema.define(:version => 20121008185303) do |
13 | 13 | ||
14 | create_table "abuse_reports", :force => true do |t| | 14 | create_table "abuse_reports", :force => true do |t| |
15 | t.integer "reporter_id" | 15 | t.integer "reporter_id" |
@@ -261,6 +261,10 @@ ActiveRecord::Schema.define(:version => 20120825185219) do | @@ -261,6 +261,10 @@ ActiveRecord::Schema.define(:version => 20120825185219) do | ||
261 | t.datetime "created_at" | 261 | t.datetime "created_at" |
262 | t.datetime "updated_at" | 262 | t.datetime "updated_at" |
263 | t.integer "reports_lower_bound", :default => 0, :null => false | 263 | t.integer "reports_lower_bound", :default => 0, :null => false |
264 | + t.string "redirection_after_login", :default => "keep_on_same_page" | ||
265 | + t.text "signup_welcome_text" | ||
266 | + t.string "languages" | ||
267 | + t.string "default_language" | ||
264 | end | 268 | end |
265 | 269 | ||
266 | create_table "external_feeds", :force => true do |t| | 270 | create_table "external_feeds", :force => true do |t| |
@@ -438,6 +442,7 @@ ActiveRecord::Schema.define(:version => 20120825185219) do | @@ -438,6 +442,7 @@ ActiveRecord::Schema.define(:version => 20120825185219) do | ||
438 | t.string "national_region_code" | 442 | t.string "national_region_code" |
439 | t.boolean "is_template", :default => false | 443 | t.boolean "is_template", :default => false |
440 | t.integer "template_id" | 444 | t.integer "template_id" |
445 | + t.string "redirection_after_login" | ||
441 | end | 446 | end |
442 | 447 | ||
443 | add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" | 448 | add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" |
debian/changelog
@@ -4,6 +4,12 @@ noosfero (0.39.0~1) UNRELEASED; urgency=low | @@ -4,6 +4,12 @@ noosfero (0.39.0~1) UNRELEASED; urgency=low | ||
4 | 4 | ||
5 | -- Antonio Terceiro <terceiro@debian.org> Thu, 30 Aug 2012 14:55:10 -0300 | 5 | -- Antonio Terceiro <terceiro@debian.org> Thu, 30 Aug 2012 14:55:10 -0300 |
6 | 6 | ||
7 | +noosfero (0.38.3) unstable; urgency=low | ||
8 | + | ||
9 | + * Bugfixes release | ||
10 | + | ||
11 | + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Wed, 07 Nov 2012 20:25:51 -0200 | ||
12 | + | ||
7 | noosfero (0.38.2) unstable; urgency=low | 13 | noosfero (0.38.2) unstable; urgency=low |
8 | 14 | ||
9 | * Bugfixes release | 15 | * Bugfixes release |
features/login.feature
@@ -9,7 +9,8 @@ Feature: login | @@ -9,7 +9,8 @@ Feature: login | ||
9 | | joaosilva | Joao Silva | | 9 | | joaosilva | Joao Silva | |
10 | 10 | ||
11 | Scenario: login from portal homepage | 11 | Scenario: login from portal homepage |
12 | - Given I am not logged in | 12 | + Given feature "allow_change_of_redirection_after_login" is disabled on environment |
13 | + And I am not logged in | ||
13 | And I go to the homepage | 14 | And I go to the homepage |
14 | And I fill in the following: | 15 | And I fill in the following: |
15 | | Username | joaosilva | | 16 | | Username | joaosilva | |
@@ -19,7 +20,8 @@ Feature: login | @@ -19,7 +20,8 @@ Feature: login | ||
19 | And I should be logged in as "joaosilva" | 20 | And I should be logged in as "joaosilva" |
20 | 21 | ||
21 | Scenario: login from some profile page | 22 | Scenario: login from some profile page |
22 | - Given I am not logged in | 23 | + Given feature "allow_change_of_redirection_after_login" is disabled on environment |
24 | + And I am not logged in | ||
23 | And the following users | 25 | And the following users |
24 | | login | name | | 26 | | login | name | |
25 | | mariasilva | Maria Silva | | 27 | | mariasilva | Maria Silva | |
@@ -35,7 +37,8 @@ Feature: login | @@ -35,7 +37,8 @@ Feature: login | ||
35 | Then I should be on Maria Silva's homepage | 37 | Then I should be on Maria Silva's homepage |
36 | 38 | ||
37 | Scenario: view my control panel | 39 | Scenario: view my control panel |
38 | - Given I am not logged in | 40 | + Given feature "allow_change_of_redirection_after_login" is disabled on environment |
41 | + And I am not logged in | ||
39 | And I go to Joao Silva's control panel | 42 | And I go to Joao Silva's control panel |
40 | And I should be on login page | 43 | And I should be on login page |
41 | And I fill in the following: | 44 | And I fill in the following: |
@@ -48,3 +51,146 @@ Feature: login | @@ -48,3 +51,146 @@ Feature: login | ||
48 | Given I am logged in as "joaosilva" | 51 | Given I am logged in as "joaosilva" |
49 | And I go to login page | 52 | And I go to login page |
50 | Then I should be on Joao Silva's control panel | 53 | Then I should be on Joao Silva's control panel |
54 | + | ||
55 | + Scenario: stay on the same page after login if this is the environment default | ||
56 | + Given feature "allow_change_of_redirection_after_login" is enabled on environment | ||
57 | + And I am not logged in | ||
58 | + And the environment is configured to stay on the same page after login | ||
59 | + And the following users | ||
60 | + | login | name | | ||
61 | + | mariasilva | Maria Silva | | ||
62 | + And the following articles | ||
63 | + | owner | name | homepage | | ||
64 | + | mariasilva | my home page | true | | ||
65 | + And I go to Maria Silva's homepage | ||
66 | + And I follow "Login" | ||
67 | + And I fill in the following: | ||
68 | + | Username | joaosilva | | ||
69 | + | Password | 123456 | | ||
70 | + When I press "Log in" | ||
71 | + Then I should be on Maria Silva's homepage | ||
72 | + | ||
73 | + Scenario: go to site homepage if this is the environment default | ||
74 | + Given feature "allow_change_of_redirection_after_login" is enabled on environment | ||
75 | + And I am not logged in | ||
76 | + And the environment is configured to redirect to site homepage after login | ||
77 | + And I go to Joao Silva's homepage | ||
78 | + And I follow "Login" | ||
79 | + And I fill in the following: | ||
80 | + | Username | joaosilva | | ||
81 | + | Password | 123456 | | ||
82 | + When I press "Log in" | ||
83 | + Then I should be on the homepage | ||
84 | + | ||
85 | + Scenario: go to user profile after login if this is the environment default | ||
86 | + Given feature "allow_change_of_redirection_after_login" is enabled on environment | ||
87 | + And I am not logged in | ||
88 | + And the environment is configured to redirect to user profile page after login | ||
89 | + And I go to the homepage | ||
90 | + And I follow "Login" | ||
91 | + And I fill in the following: | ||
92 | + | Username | joaosilva | | ||
93 | + | Password | 123456 | | ||
94 | + When I press "Log in" | ||
95 | + Then I should be on Joao Silva's profile | ||
96 | + | ||
97 | + Scenario: go to profile homepage after login if this is the environment default | ||
98 | + Given the following articles | ||
99 | + | owner | name | body | homepage | | ||
100 | + | joaosilva | Sample Article | This is an article | true | | ||
101 | + And feature "allow_change_of_redirection_after_login" is enabled on environment | ||
102 | + And I am not logged in | ||
103 | + And the environment is configured to redirect to profile homepage after login | ||
104 | + And I go to the homepage | ||
105 | + And I follow "Login" | ||
106 | + And I fill in the following: | ||
107 | + | Username | joaosilva | | ||
108 | + | Password | 123456 | | ||
109 | + When I press "Log in" | ||
110 | + Then I should be on Joao Silva's homepage | ||
111 | + | ||
112 | + Scenario: go to profile control panel after login if this is the environment default | ||
113 | + Given feature "allow_change_of_redirection_after_login" is enabled on environment | ||
114 | + And I am not logged in | ||
115 | + And the environment is configured to redirect to profile control panel after login | ||
116 | + And I go to the homepage | ||
117 | + And I follow "Login" | ||
118 | + And I fill in the following: | ||
119 | + | Username | joaosilva | | ||
120 | + | Password | 123456 | | ||
121 | + When I press "Log in" | ||
122 | + Then I should be on Joao Silva's control panel | ||
123 | + | ||
124 | + Scenario: stay on the same page after login if this is the profile default | ||
125 | + Given feature "allow_change_of_redirection_after_login" is enabled on environment | ||
126 | + And I am not logged in | ||
127 | + And the environment is configured to redirect to site homepage after login | ||
128 | + And the profile joaosilva is configured to stay on the same page after login | ||
129 | + And the following users | ||
130 | + | login | name | | ||
131 | + | mariasilva | Maria Silva | | ||
132 | + And the following articles | ||
133 | + | owner | name | homepage | | ||
134 | + | mariasilva | my home page | true | | ||
135 | + And I go to Maria Silva's homepage | ||
136 | + And I follow "Login" | ||
137 | + And I fill in the following: | ||
138 | + | Username | joaosilva | | ||
139 | + | Password | 123456 | | ||
140 | + When I press "Log in" | ||
141 | + Then I should be on Maria Silva's homepage | ||
142 | + | ||
143 | + Scenario: go to site homepage if this is the profile default | ||
144 | + Given feature "allow_change_of_redirection_after_login" is enabled on environment | ||
145 | + And I am not logged in | ||
146 | + And the environment is configured to stay on the same page after login | ||
147 | + And the profile joaosilva is configured to redirect to site homepage after login | ||
148 | + And I go to Joao Silva's homepage | ||
149 | + And I follow "Login" | ||
150 | + And I fill in the following: | ||
151 | + | Username | joaosilva | | ||
152 | + | Password | 123456 | | ||
153 | + When I press "Log in" | ||
154 | + Then I should be on the homepage | ||
155 | + | ||
156 | + Scenario: go to user profile after login if this is the profile default | ||
157 | + Given feature "allow_change_of_redirection_after_login" is enabled on environment | ||
158 | + And I am not logged in | ||
159 | + And the environment is configured to stay on the same page after login | ||
160 | + And the profile joaosilva is configured to redirect to user profile page after login | ||
161 | + And I go to the homepage | ||
162 | + And I follow "Login" | ||
163 | + And I fill in the following: | ||
164 | + | Username | joaosilva | | ||
165 | + | Password | 123456 | | ||
166 | + When I press "Log in" | ||
167 | + Then I should be on Joao Silva's profile | ||
168 | + | ||
169 | + Scenario: go to profile homepage after login if this is the profile default | ||
170 | + Given the following articles | ||
171 | + | owner | name | body | homepage | | ||
172 | + | joaosilva | Sample Article | This is an article | true | | ||
173 | + And feature "allow_change_of_redirection_after_login" is enabled on environment | ||
174 | + And I am not logged in | ||
175 | + And the environment is configured to stay on the same page after login | ||
176 | + And the profile joaosilva is configured to redirect to profile homepage after login | ||
177 | + And I go to the homepage | ||
178 | + And I follow "Login" | ||
179 | + And I fill in the following: | ||
180 | + | Username | joaosilva | | ||
181 | + | Password | 123456 | | ||
182 | + When I press "Log in" | ||
183 | + Then I should be on Joao Silva's homepage | ||
184 | + | ||
185 | + Scenario: go to profile control panel after login if this is the profile default | ||
186 | + Given feature "allow_change_of_redirection_after_login" is enabled on environment | ||
187 | + And I am not logged in | ||
188 | + And the environment is configured to stay on the same page after login | ||
189 | + And the profile joaosilva is configured to redirect to profile control panel after login | ||
190 | + And I go to the homepage | ||
191 | + And I follow "Login" | ||
192 | + And I fill in the following: | ||
193 | + | Username | joaosilva | | ||
194 | + | Password | 123456 | | ||
195 | + When I press "Log in" | ||
196 | + Then I should be on Joao Silva's control panel |
features/send_email_to_organization_members.feature
1 | Feature: send emails to organization members | 1 | Feature: send emails to organization members |
2 | - As a organization administrator | 2 | + As a organization administrator or moderator |
3 | I want to send email to all members | 3 | I want to send email to all members |
4 | 4 | ||
5 | Background: | 5 | Background: |
6 | Given the following users | 6 | Given the following users |
7 | | login | name | | 7 | | login | name | |
8 | | joaosilva | Joao Silva | | 8 | | joaosilva | Joao Silva | |
9 | + | jose | Jose Silva | | ||
10 | + | manoel | Manoel Silva | | ||
9 | And the following communities | 11 | And the following communities |
10 | | identifier | name | | 12 | | identifier | name | |
11 | | sample-community | Sample Community | | 13 | | sample-community | Sample Community | |
12 | And "Joao Silva" is admin of "Sample Community" | 14 | And "Joao Silva" is admin of "Sample Community" |
15 | + And "Jose Silva" is moderator of "Sample Community" | ||
16 | + And "Manoel Silva" is a member of "Sample Community" | ||
13 | 17 | ||
14 | Scenario: Cant access if not logged in | 18 | Scenario: Cant access if not logged in |
15 | Given I am not logged in | 19 | Given I am not logged in |
16 | - When I go to /myprofile/sample-community/profile_members/send_mail | 20 | + When I go to /profile/sample-community/send_mail |
17 | Then I should be on login page | 21 | Then I should be on login page |
18 | 22 | ||
19 | Scenario: Cant access as normal user | 23 | Scenario: Cant access as normal user |
@@ -21,7 +25,7 @@ Feature: send emails to organization members | @@ -21,7 +25,7 @@ Feature: send emails to organization members | ||
21 | | login | | 25 | | login | |
22 | | josesilva | | 26 | | josesilva | |
23 | And I am logged in as "josesilva" | 27 | And I am logged in as "josesilva" |
24 | - When I go to /myprofile/sample-community/profile_members/send_mail | 28 | + When I go to /profile/sample-community/send_mail |
25 | Then I should see "Access denied" | 29 | Then I should see "Access denied" |
26 | 30 | ||
27 | Scenario: Send e-mail to members | 31 | Scenario: Send e-mail to members |
@@ -39,7 +43,7 @@ Feature: send emails to organization members | @@ -39,7 +43,7 @@ Feature: send emails to organization members | ||
39 | And I follow "Send e-mail to members" | 43 | And I follow "Send e-mail to members" |
40 | And I fill in "body" with "We have some news" | 44 | And I fill in "body" with "We have some news" |
41 | When I press "Send" | 45 | When I press "Send" |
42 | - Then I should be on /myprofile/sample-community/profile_members/send_mail | 46 | + Then I should be on /profile/sample-community/send_mail |
43 | 47 | ||
44 | Scenario: Not send e-mail to members if body is blank | 48 | Scenario: Not send e-mail to members if body is blank |
45 | Given I am logged in as "joaosilva" | 49 | Given I am logged in as "joaosilva" |
@@ -47,7 +51,7 @@ Feature: send emails to organization members | @@ -47,7 +51,7 @@ Feature: send emails to organization members | ||
47 | And I follow "Send e-mail to members" | 51 | And I follow "Send e-mail to members" |
48 | And I fill in "Subject" with "Hello, user!" | 52 | And I fill in "Subject" with "Hello, user!" |
49 | When I press "Send" | 53 | When I press "Send" |
50 | - Then I should be on /myprofile/sample-community/profile_members/send_mail | 54 | + Then I should be on /profile/sample-community/send_mail |
51 | 55 | ||
52 | Scenario: Cancel creation of mailing | 56 | Scenario: Cancel creation of mailing |
53 | Given I am logged in as "joaosilva" | 57 | Given I am logged in as "joaosilva" |
@@ -55,3 +59,34 @@ Feature: send emails to organization members | @@ -55,3 +59,34 @@ Feature: send emails to organization members | ||
55 | And I follow "Send e-mail to members" | 59 | And I follow "Send e-mail to members" |
56 | When I follow "Cancel e-mail" | 60 | When I follow "Cancel e-mail" |
57 | Then I should be on Sample Community's members management | 61 | Then I should be on Sample Community's members management |
62 | + | ||
63 | + Scenario: Cant access if has no send_mail_to_members permission | ||
64 | + Given I am logged in as "manoel" | ||
65 | + When I go to /profile/sample-community/send_mail | ||
66 | + Then I should see "Access denied" | ||
67 | + | ||
68 | + Scenario: Show button "Send e-Mail to members" of community to an moderator | ||
69 | + Given I am logged in as "jose" | ||
70 | + When I go to Sample Community's members page | ||
71 | + Then I should see "Send e-mail to members" link | ||
72 | + | ||
73 | + Scenario: Not show button "Send e-Mail to members" if user has no right permission | ||
74 | + Given I am logged in as "manoel" | ||
75 | + When I go to Sample Community's members page | ||
76 | + Then I should not see "Send e-mail to members" link | ||
77 | + | ||
78 | + Scenario: Redirect back to profile members page after send mail | ||
79 | + Given I am logged in as "jose" | ||
80 | + When I go to Sample Community's members page | ||
81 | + And I follow "Send e-mail to members" | ||
82 | + And I fill in "Subject" with "Hello, member!" | ||
83 | + And I fill in "body" with "We have some news" | ||
84 | + When I press "Send" | ||
85 | + Then I should be on Sample Community's members page | ||
86 | + | ||
87 | + Scenario: Back to profile members page after cancel creation of mailing | ||
88 | + Given I am logged in as "jose" | ||
89 | + And I go to Sample Community's members page | ||
90 | + And I follow "Send e-mail to members" | ||
91 | + When I follow "Cancel e-mail" | ||
92 | + Then I should be on Sample Community's members page |
features/step_definitions/noosfero_steps.rb
@@ -355,6 +355,12 @@ Given /^"(.+)" is admin of "(.+)"$/ do |person, organization| | @@ -355,6 +355,12 @@ Given /^"(.+)" is admin of "(.+)"$/ do |person, organization| | ||
355 | org.add_admin(user) | 355 | org.add_admin(user) |
356 | end | 356 | end |
357 | 357 | ||
358 | +Given /^"(.+)" is moderator of "(.+)"$/ do |person, organization| | ||
359 | + org = Profile.find_by_name(organization) | ||
360 | + user = Profile.find_by_name(person) | ||
361 | + org.add_moderator(user) | ||
362 | +end | ||
363 | + | ||
358 | Then /^"(.+)" should be admin of "(.+)"$/ do |person, organization| | 364 | Then /^"(.+)" should be admin of "(.+)"$/ do |person, organization| |
359 | org = Organization.find_by_name(organization) | 365 | org = Organization.find_by_name(organization) |
360 | user = Person.find_by_name(person) | 366 | user = Person.find_by_name(person) |
@@ -706,3 +712,39 @@ When /^I make a AJAX request to (.*)$/ do |page| | @@ -706,3 +712,39 @@ When /^I make a AJAX request to (.*)$/ do |page| | ||
706 | header 'X-Requested-With', 'XMLHttpRequest' | 712 | header 'X-Requested-With', 'XMLHttpRequest' |
707 | visit(path_to(page)) | 713 | visit(path_to(page)) |
708 | end | 714 | end |
715 | + | ||
716 | +Given /^the environment is configured to (.*) after login$/ do |option| | ||
717 | + redirection = case option | ||
718 | + when 'stay on the same page' | ||
719 | + 'keep_on_same_page' | ||
720 | + when 'redirect to site homepage' | ||
721 | + 'site_homepage' | ||
722 | + when 'redirect to user profile page' | ||
723 | + 'user_profile_page' | ||
724 | + when 'redirect to profile homepage' | ||
725 | + 'user_homepage' | ||
726 | + when 'redirect to profile control panel' | ||
727 | + 'user_control_panel' | ||
728 | + end | ||
729 | + environment = Environment.default | ||
730 | + environment.redirection_after_login = redirection | ||
731 | + environment.save | ||
732 | +end | ||
733 | + | ||
734 | +Given /^the profile (.*) is configured to (.*) after login$/ do |profile, option| | ||
735 | + redirection = case option | ||
736 | + when 'stay on the same page' | ||
737 | + 'keep_on_same_page' | ||
738 | + when 'redirect to site homepage' | ||
739 | + 'site_homepage' | ||
740 | + when 'redirect to user profile page' | ||
741 | + 'user_profile_page' | ||
742 | + when 'redirect to profile homepage' | ||
743 | + 'user_homepage' | ||
744 | + when 'redirect to profile control panel' | ||
745 | + 'user_control_panel' | ||
746 | + end | ||
747 | + profile = Profile.find_by_identifier(profile) | ||
748 | + profile.redirection_after_login = redirection | ||
749 | + profile.save | ||
750 | +end |
features/support/paths.rb
@@ -108,6 +108,9 @@ module NavigationHelpers | @@ -108,6 +108,9 @@ module NavigationHelpers | ||
108 | when /the user data path/ | 108 | when /the user data path/ |
109 | '/account/user_data' | 109 | '/account/user_data' |
110 | 110 | ||
111 | + when /^(.+)'s members page/ | ||
112 | + '/profile/%s/members' % Profile.find_by_name($1).identifier | ||
113 | + | ||
111 | # Add more mappings here. | 114 | # Add more mappings here. |
112 | # Here is a more fancy example: | 115 | # Here is a more fancy example: |
113 | # | 116 | # |
lib/acts_as_having_boxes.rb
@@ -18,7 +18,7 @@ module ActsAsHavingBoxes | @@ -18,7 +18,7 @@ module ActsAsHavingBoxes | ||
18 | @blocks = nil | 18 | @blocks = nil |
19 | end | 19 | end |
20 | if @blocks.nil? | 20 | if @blocks.nil? |
21 | - @blocks = boxes.inject([]) do |acc,obj| | 21 | + @blocks = boxes.includes(:blocks).inject([]) do |acc,obj| |
22 | acc.concat(obj.blocks) | 22 | acc.concat(obj.blocks) |
23 | end | 23 | end |
24 | @blocks.send(:extend, BlockArray) | 24 | @blocks.send(:extend, BlockArray) |
lib/noosfero/plugin.rb
@@ -320,6 +320,37 @@ class Noosfero::Plugin | @@ -320,6 +320,37 @@ class Noosfero::Plugin | ||
320 | nil | 320 | nil |
321 | end | 321 | end |
322 | 322 | ||
323 | + # -> Add an alternative authentication method. | ||
324 | + # Your plugin have to make the access control and return the logged user. | ||
325 | + # returns = User | ||
326 | + def alternative_authentication | ||
327 | + nil | ||
328 | + end | ||
329 | + | ||
330 | + # -> Adds adicional link to make the user authentication | ||
331 | + # returns = lambda block that creates html code | ||
332 | + def alternative_authentication_link | ||
333 | + nil | ||
334 | + end | ||
335 | + | ||
336 | + # -> Allow or not user registration | ||
337 | + # returns = boolean | ||
338 | + def allow_user_registration | ||
339 | + true | ||
340 | + end | ||
341 | + | ||
342 | + # -> Allow or not password recovery by users | ||
343 | + # returns = boolean | ||
344 | + def allow_password_recovery | ||
345 | + true | ||
346 | + end | ||
347 | + | ||
348 | + # -> Adds fields to the login form | ||
349 | + # returns = lambda block that creates html code | ||
350 | + def login_extra_contents | ||
351 | + nil | ||
352 | + end | ||
353 | + | ||
323 | def method_missing(method, *args, &block) | 354 | def method_missing(method, *args, &block) |
324 | # This is a generic hotspot for all controllers on Noosfero. | 355 | # This is a generic hotspot for all controllers on Noosfero. |
325 | # If any plugin wants to define filters to run on any controller, the name of | 356 | # If any plugin wants to define filters to run on any controller, the name of |
plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb
0 → 100644
@@ -0,0 +1,147 @@ | @@ -0,0 +1,147 @@ | ||
1 | +class CustomFormsPluginMyprofileController < MyProfileController | ||
2 | + | ||
3 | + protect 'post_content', :profile | ||
4 | + def index | ||
5 | + @forms = CustomFormsPlugin::Form.from(profile) | ||
6 | + end | ||
7 | + | ||
8 | + def create | ||
9 | + @form = CustomFormsPlugin::Form.new(:profile => profile) | ||
10 | + @fields = [] | ||
11 | + @empty_field = CustomFormsPlugin::Field.new | ||
12 | + if request.post? | ||
13 | + begin | ||
14 | + @form.update_attributes!(params[:form]) | ||
15 | + params[:fields] = format_kind(params[:fields]) | ||
16 | + params[:fields] = format_choices(params[:fields]) | ||
17 | + params[:fields] = set_form_id(params[:fields], @form.id) | ||
18 | + create_fields(new_fields(params)) | ||
19 | + session['notice'] = _('Form created') | ||
20 | + redirect_to :action => 'index' | ||
21 | + rescue Exception => exception | ||
22 | + logger.error(exception.to_s) | ||
23 | + session['notice'] = _('Form could not be created') | ||
24 | + end | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + def edit | ||
29 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
30 | + @fields = @form.fields | ||
31 | + @empty_field = CustomFormsPlugin::TextField.new | ||
32 | + if request.post? | ||
33 | + begin | ||
34 | + @form.update_attributes!(params[:form]) | ||
35 | + params[:fields] = format_kind(params[:fields]) | ||
36 | + params[:fields] = format_choices(params[:fields]) | ||
37 | + remove_fields(params, @form) | ||
38 | + create_fields(new_fields(params)) | ||
39 | + update_fields(edited_fields(params)) | ||
40 | + session['notice'] = _('Form updated') | ||
41 | + redirect_to :action => 'index' | ||
42 | + rescue Exception => exception | ||
43 | + logger.error(exception.to_s) | ||
44 | + session['notice'] = _('Form could not be updated') | ||
45 | + end | ||
46 | + end | ||
47 | + end | ||
48 | + | ||
49 | + def remove | ||
50 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
51 | + begin | ||
52 | + @form.destroy | ||
53 | + session[:notice] = _('Form removed') | ||
54 | + rescue | ||
55 | + session[:notice] = _('Form could not be removed') | ||
56 | + end | ||
57 | + redirect_to :action => 'index' | ||
58 | + end | ||
59 | + | ||
60 | + def submissions | ||
61 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
62 | + @submissions = @form.submissions | ||
63 | + end | ||
64 | + | ||
65 | + def show_submission | ||
66 | + @submission = CustomFormsPlugin::Submission.find(params[:id]) | ||
67 | + @form = @submission.form | ||
68 | + end | ||
69 | + | ||
70 | + private | ||
71 | + | ||
72 | + def new_fields(params) | ||
73 | + result = params[:fields].map {|id, hash| hash.has_key?(:real_id) ? nil : hash}.compact | ||
74 | + result.delete_if {|field| field[:name].blank?} | ||
75 | + result | ||
76 | + end | ||
77 | + | ||
78 | + def edited_fields(params) | ||
79 | + params[:fields].map {|id, hash| hash.has_key?(:real_id) ? hash : nil}.compact | ||
80 | + end | ||
81 | + | ||
82 | + def create_fields(fields) | ||
83 | + fields.each do |field| | ||
84 | + case field[:type] | ||
85 | + when 'text_field' | ||
86 | + CustomFormsPlugin::TextField.create!(field) | ||
87 | + when 'select_field' | ||
88 | + CustomFormsPlugin::SelectField.create!(field) | ||
89 | + else | ||
90 | + CustomFormsPlugin::Field.create!(field) | ||
91 | + end | ||
92 | + end | ||
93 | + end | ||
94 | + | ||
95 | + def update_fields(fields) | ||
96 | + fields.each do |field_attrs| | ||
97 | + field = CustomFormsPlugin::Field.find(field_attrs.delete(:real_id)) | ||
98 | + field.attributes = field_attrs | ||
99 | + field.save! if field.changed? | ||
100 | + end | ||
101 | + end | ||
102 | + | ||
103 | + def format_kind(fields) | ||
104 | + fields.each do |id, field| | ||
105 | + next if field[:kind].blank? | ||
106 | + kind = field.delete(:kind) | ||
107 | + case kind | ||
108 | + when 'radio' | ||
109 | + field[:list] = false | ||
110 | + field[:multiple] = false | ||
111 | + when 'check_box' | ||
112 | + field[:list] = false | ||
113 | + field[:multiple] = true | ||
114 | + when 'select' | ||
115 | + field[:list] = true | ||
116 | + field[:multiple] = false | ||
117 | + when 'multiple_select' | ||
118 | + field[:list] = true | ||
119 | + field[:multiple] = true | ||
120 | + end | ||
121 | + end | ||
122 | + fields | ||
123 | + end | ||
124 | + | ||
125 | + def format_choices(fields) | ||
126 | + fields.each do |id, field| | ||
127 | + next if !field.has_key?(:choices) | ||
128 | + field[:choices] = field[:choices].map {|key, value| value}.inject({}) do |result, choice| | ||
129 | + hash = (choice[:name].blank? || choice[:value].blank?) ? {} : {choice[:name] => choice[:value]} | ||
130 | + result.merge!(hash) | ||
131 | + end | ||
132 | + end | ||
133 | + fields | ||
134 | + end | ||
135 | + | ||
136 | + def remove_fields(params, form) | ||
137 | + present_fields = params[:fields].map{|id, value| value}.collect {|field| field[:real_id]}.compact | ||
138 | + form.fields.each {|field| field.destroy if !present_fields.include?(field.id.to_s) } | ||
139 | + end | ||
140 | + | ||
141 | + def set_form_id(fields, form_id) | ||
142 | + fields.each do |id, field| | ||
143 | + field[:form_id] = form_id | ||
144 | + end | ||
145 | + fields | ||
146 | + end | ||
147 | +end |
plugins/custom_forms/controllers/custom_forms_plugin_profile_controller.rb
0 → 100644
@@ -0,0 +1,45 @@ | @@ -0,0 +1,45 @@ | ||
1 | +class CustomFormsPluginProfileController < ProfileController | ||
2 | + | ||
3 | + before_filter :has_access, :show | ||
4 | + | ||
5 | + def show | ||
6 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
7 | + if user | ||
8 | + @submission ||= CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id) | ||
9 | + @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id, :profile_id => user.id) | ||
10 | + else | ||
11 | + @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id) | ||
12 | + end | ||
13 | + if request.post? | ||
14 | + begin | ||
15 | + extend(CustomFormsPlugin::Helper) | ||
16 | + answers = build_answers(params[:submission], @form) | ||
17 | + failed_answers = answers.select {|answer| !answer.valid? } | ||
18 | + if failed_answers.empty? | ||
19 | + if !user | ||
20 | + @submission.author_name = params[:author_name] | ||
21 | + @submission.author_email = params[:author_email] | ||
22 | + end | ||
23 | + @submission.save! | ||
24 | + answers.map {|answer| answer.submission = @submission; answer.save!} | ||
25 | + else | ||
26 | + @submission.valid? | ||
27 | + failed_answers.each do |answer| | ||
28 | + @submission.errors.add(answer.field.name.to_sym, answer.errors[answer.field.slug.to_sym]) | ||
29 | + end | ||
30 | + end | ||
31 | + session[:notice] = _('Submission saved') | ||
32 | + redirect_to :action => 'show' | ||
33 | + rescue | ||
34 | + session[:notice] = _('Submission could not be saved') | ||
35 | + end | ||
36 | + end | ||
37 | + end | ||
38 | + | ||
39 | + private | ||
40 | + | ||
41 | + def has_access | ||
42 | + form = CustomFormsPlugin::Form.find(params[:id]) | ||
43 | + render_access_denied if !form.accessible_to(user) | ||
44 | + end | ||
45 | +end |
plugins/custom_forms/db/migrate/20120727162444_create_custom_forms_plugin_forms.rb
0 → 100644
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +class CreateCustomFormsPluginForms < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_forms do |t| | ||
4 | + t.string :name | ||
5 | + t.string :slug | ||
6 | + t.text :description | ||
7 | + t.references :profile | ||
8 | + t.datetime :begining | ||
9 | + t.datetime :ending | ||
10 | + t.boolean :report_submissions, :default => false | ||
11 | + t.boolean :on_membership, :default => false | ||
12 | + t.string :access | ||
13 | + t.timestamps | ||
14 | + end | ||
15 | + end | ||
16 | + | ||
17 | + def self.down | ||
18 | + drop_table :custom_forms_plugin_forms | ||
19 | + end | ||
20 | +end |
plugins/custom_forms/db/migrate/20120727174506_create_custom_forms_plugin_fields.rb
0 → 100644
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +class CreateCustomFormsPluginFields < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_fields do |t| | ||
4 | + t.string :name | ||
5 | + t.string :slug | ||
6 | + t.string :type | ||
7 | + t.string :default_value | ||
8 | + t.string :choices | ||
9 | + t.float :minimum | ||
10 | + t.float :maximum | ||
11 | + t.references :form | ||
12 | + t.boolean :mandatory, :default => false | ||
13 | + t.boolean :multiple | ||
14 | + t.boolean :list | ||
15 | + end | ||
16 | + end | ||
17 | + | ||
18 | + def self.down | ||
19 | + drop_table :custom_forms_plugin_fields | ||
20 | + end | ||
21 | +end |
plugins/custom_forms/db/migrate/20120727175250_create_custom_forms_plugin_answers.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class CreateCustomFormsPluginAnswers < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_answers do |t| | ||
4 | + t.text :value | ||
5 | + t.references :field | ||
6 | + t.references :submission | ||
7 | + end | ||
8 | + end | ||
9 | + | ||
10 | + def self.down | ||
11 | + drop_table :custom_forms_plugin_answers | ||
12 | + end | ||
13 | +end |
plugins/custom_forms/db/migrate/20120727180512_create_custom_forms_plugin_submissions.rb
0 → 100644
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +class CreateCustomFormsPluginSubmissions < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_submissions do |t| | ||
4 | + t.string :author_name | ||
5 | + t.string :author_email | ||
6 | + t.references :profile | ||
7 | + t.references :form | ||
8 | + t.timestamps | ||
9 | + end | ||
10 | + end | ||
11 | + | ||
12 | + def self.down | ||
13 | + drop_table :custom_forms_plugin_submissions | ||
14 | + end | ||
15 | +end |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +require 'ext/role_assignment_trigger' | ||
2 | + | ||
3 | +class CustomFormsPlugin < Noosfero::Plugin | ||
4 | + | ||
5 | + def self.plugin_name | ||
6 | + "Custom Forms" | ||
7 | + end | ||
8 | + | ||
9 | + def self.plugin_description | ||
10 | + _("Enables the creation of forms.") | ||
11 | + end | ||
12 | + | ||
13 | + def stylesheet? | ||
14 | + true | ||
15 | + end | ||
16 | + | ||
17 | + def control_panel_buttons | ||
18 | + {:title => _('Manage Forms'), :icon => 'custom-forms', :url => {:controller => 'custom_forms_plugin_myprofile'}} | ||
19 | + end | ||
20 | + | ||
21 | +end |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +class CustomFormsPlugin::Answer < Noosfero::Plugin::ActiveRecord | ||
2 | + belongs_to :field, :class_name => 'CustomFormsPlugin::Field' | ||
3 | + belongs_to :submission, :class_name => 'CustomFormsPlugin::Submission' | ||
4 | + | ||
5 | + validates_presence_of :field | ||
6 | + validate :value_mandatory, :if => 'field.present?' | ||
7 | + | ||
8 | + def value_mandatory | ||
9 | + if field.mandatory && value.blank? | ||
10 | + errors.add(field.slug.to_sym, _("is mandatory.").fix_i18n) | ||
11 | + end | ||
12 | + end | ||
13 | +end | ||
14 | + |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +class CustomFormsPlugin::Field < ActiveRecord::Base | ||
2 | + set_table_name :custom_forms_plugin_fields | ||
3 | + | ||
4 | + validates_presence_of :form, :name | ||
5 | + validates_uniqueness_of :slug, :scope => :form_id | ||
6 | + | ||
7 | + belongs_to :form, :class_name => 'CustomFormsPlugin::Form', :dependent => :destroy | ||
8 | + has_many :answers, :class_name => 'CustomFormsPlugin::Answer' | ||
9 | + | ||
10 | + serialize :choices, Hash | ||
11 | + | ||
12 | + before_validation do |field| | ||
13 | + field.slug = field.name.to_slug if field.name.present? | ||
14 | + end | ||
15 | +end | ||
16 | + |