Commit abab0c3ec3d841ecedc57e59ade08193cd6e6067
Exists in
staging
and in
42 other branches
Merge branch 'plugins-routes' of git://gitorious.org/~diguliu/noosfero/digulius-…
…noosfero into refactoring_controllers
Showing
286 changed files
with
8733 additions
and
1124 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 286 files displayed.
INSTALL.varnish
| ... | ... | @@ -15,6 +15,10 @@ Noosfero was tested with Varnish 2.x. If you are using a Debian Lenny (and you |
| 15 | 15 | should, unless Debian already released Squeeze by now), make sure you install |
| 16 | 16 | varnish from the lenny-backports suite. |
| 17 | 17 | |
| 18 | +Install the RPAF apache module (or skip this step if not using apache): | |
| 19 | + | |
| 20 | + # apt-get install libapache2-mod-rpaf | |
| 21 | + | |
| 18 | 22 | 3) Enable varnish logging: |
| 19 | 23 | |
| 20 | 24 | 3a) Edit /etc/default/varnishncsa and uncomment the line that contains: | ... | ... |
app/controllers/admin/users_controller.rb
| ... | ... | @@ -7,11 +7,12 @@ class UsersController < AdminController |
| 7 | 7 | format.html |
| 8 | 8 | format.xml do |
| 9 | 9 | @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person]) |
| 10 | - render :xml => @users.to_xml( | |
| 11 | - :skip_types => true, | |
| 12 | - :only => %w[email login created_at updated_at], | |
| 13 | - :include => { :person => {:only => %w[name updated_at created_at address birth_date contact_phone identifier lat lng] } } | |
| 14 | - ) | |
| 10 | + send_data @users.to_xml( | |
| 11 | + :skip_types => true, | |
| 12 | + :only => %w[email login created_at updated_at], | |
| 13 | + :include => { :person => {:only => %w[name updated_at created_at address birth_date contact_phone identifier lat lng] } }), | |
| 14 | + :type => 'text/xml', | |
| 15 | + :disposition => "attachment; filename=users.xml" | |
| 15 | 16 | end |
| 16 | 17 | format.csv do |
| 17 | 18 | @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person]) | ... | ... |
app/controllers/application_controller.rb
| ... | ... | @@ -101,9 +101,10 @@ class ApplicationController < ActionController::Base |
| 101 | 101 | end |
| 102 | 102 | end |
| 103 | 103 | |
| 104 | + include Noosfero::Plugin::HotSpot | |
| 105 | + | |
| 104 | 106 | def init_noosfero_plugins |
| 105 | - @plugins = Noosfero::Plugin::Manager.new(self) | |
| 106 | - @plugins.each do |plugin| | |
| 107 | + plugins.each do |plugin| | |
| 107 | 108 | prepend_view_path(plugin.class.view_path) |
| 108 | 109 | end |
| 109 | 110 | init_noosfero_plugins_controller_filters |
| ... | ... | @@ -112,8 +113,10 @@ class ApplicationController < ActionController::Base |
| 112 | 113 | # This is a generic method that initialize any possible filter defined by a |
| 113 | 114 | # plugin to the current controller being initialized. |
| 114 | 115 | def init_noosfero_plugins_controller_filters |
| 115 | - @plugins.each do |plugin| | |
| 116 | - plugin.send(self.class.name.underscore + '_filters').each do |plugin_filter| | |
| 116 | + plugins.each do |plugin| | |
| 117 | + filters = plugin.send(self.class.name.underscore + '_filters') | |
| 118 | + filters = [filters] if !filters.kind_of?(Array) | |
| 119 | + filters.each do |plugin_filter| | |
| 117 | 120 | self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {})) |
| 118 | 121 | self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block]) |
| 119 | 122 | end | ... | ... |
app/controllers/box_organizer_controller.rb
| ... | ... | @@ -68,7 +68,8 @@ class BoxOrganizerController < ApplicationController |
| 68 | 68 | raise ArgumentError.new("Type %s is not allowed. Go away." % type) |
| 69 | 69 | end |
| 70 | 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 | 73 | @boxes = boxes_holder.boxes |
| 73 | 74 | render :action => 'add_block', :layout => false |
| 74 | 75 | end | ... | ... |
app/controllers/my_profile/profile_design_controller.rb
| ... | ... | @@ -5,7 +5,7 @@ class ProfileDesignController < BoxOrganizerController |
| 5 | 5 | protect 'edit_profile_design', :profile |
| 6 | 6 | |
| 7 | 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 | 10 | # blocks exclusive for organizations |
| 11 | 11 | if profile.has_members? | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
| ... | ... | @@ -156,18 +156,4 @@ class ProfileMembersController < MyProfileController |
| 156 | 156 | end |
| 157 | 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 | 159 | end | ... | ... |
| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | +class SpamController < MyProfileController | |
| 2 | + | |
| 3 | + protect :moderate_comments, :profile | |
| 4 | + | |
| 5 | + def index | |
| 6 | + if request.post? | |
| 7 | + begin | |
| 8 | + # FIXME duplicated logic | |
| 9 | + # | |
| 10 | + # This logic more or less replicates what is already in | |
| 11 | + # ContentViewerController#view_page, | |
| 12 | + # ContentViewerController#remove_comment and | |
| 13 | + # ContentViewerController#mark_comment_as_spam | |
| 14 | + if params[:remove_comment] | |
| 15 | + profile.comments_received.find(params[:remove_comment]).destroy | |
| 16 | + end | |
| 17 | + if params[:mark_comment_as_ham] | |
| 18 | + profile.comments_received.find(params[:mark_comment_as_ham]).ham! | |
| 19 | + end | |
| 20 | + if request.xhr? | |
| 21 | + json_response(true) | |
| 22 | + else | |
| 23 | + redirect_to :action => :index | |
| 24 | + end | |
| 25 | + rescue | |
| 26 | + json_response(false) | |
| 27 | + end | |
| 28 | + return | |
| 29 | + end | |
| 30 | + | |
| 31 | + @spam = profile.comments_received.spam.paginate({:page => params[:page]}) | |
| 32 | + end | |
| 33 | + | |
| 34 | + protected | |
| 35 | + | |
| 36 | + def json_response(status) | |
| 37 | + render :text => {'ok' => status }.to_json, :content_type => 'application/json' | |
| 38 | + end | |
| 39 | + | |
| 40 | +end | ... | ... |
app/controllers/public/account_controller.rb
| ... | ... | @@ -25,11 +25,13 @@ class AccountController < ApplicationController |
| 25 | 25 | |
| 26 | 26 | # action to perform login to the application |
| 27 | 27 | def login |
| 28 | - @user = User.new | |
| 29 | - @person = @user.build_person | |
| 30 | 28 | store_location(request.referer) unless session[:return_to] |
| 31 | 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 | 35 | if logged_in? |
| 34 | 36 | if params[:remember_me] == "1" |
| 35 | 37 | self.current_user.remember_me |
| ... | ... | @@ -41,7 +43,6 @@ class AccountController < ApplicationController |
| 41 | 43 | end |
| 42 | 44 | else |
| 43 | 45 | session[:notice] = _('Incorrect username or password') if redirect? |
| 44 | - redirect_to :back if redirect? | |
| 45 | 46 | end |
| 46 | 47 | end |
| 47 | 48 | |
| ... | ... | @@ -56,6 +57,11 @@ class AccountController < ApplicationController |
| 56 | 57 | |
| 57 | 58 | # action to register an user to the application |
| 58 | 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 | 65 | @invitation_code = params[:invitation_code] |
| 60 | 66 | begin |
| 61 | 67 | if params[:user] |
| ... | ... | @@ -125,6 +131,10 @@ class AccountController < ApplicationController |
| 125 | 131 | # |
| 126 | 132 | # Posts back. |
| 127 | 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 | 138 | @change_password = ChangePassword.new(params[:change_password]) |
| 129 | 139 | |
| 130 | 140 | if request.post? |
| ... | ... | @@ -303,10 +313,27 @@ class AccountController < ApplicationController |
| 303 | 313 | end |
| 304 | 314 | |
| 305 | 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 | 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 | 337 | end |
| 311 | 338 | end |
| 312 | 339 | |
| ... | ... | @@ -316,4 +343,13 @@ class AccountController < ApplicationController |
| 316 | 343 | end |
| 317 | 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 | 355 | end | ... | ... |
app/controllers/public/content_viewer_controller.rb
| ... | ... | @@ -2,6 +2,8 @@ class ContentViewerController < ApplicationController |
| 2 | 2 | |
| 3 | 3 | needs_profile |
| 4 | 4 | |
| 5 | + before_filter :comment_author, :only => :edit_comment | |
| 6 | + | |
| 5 | 7 | helper ProfileHelper |
| 6 | 8 | helper TagsHelper |
| 7 | 9 | |
| ... | ... | @@ -19,7 +21,7 @@ class ContentViewerController < ApplicationController |
| 19 | 21 | unless @page |
| 20 | 22 | page_from_old_path = profile.articles.find_by_old_path(path) |
| 21 | 23 | if page_from_old_path |
| 22 | - redirect_to :profile => profile.identifier, :page => page_from_old_path.explode_path | |
| 24 | + redirect_to profile.url.merge(:page => page_from_old_path.explode_path) | |
| 23 | 25 | return |
| 24 | 26 | end |
| 25 | 27 | end |
| ... | ... | @@ -75,8 +77,14 @@ class ContentViewerController < ApplicationController |
| 75 | 77 | @comment = Comment.new |
| 76 | 78 | end |
| 77 | 79 | |
| 78 | - if request.post? && params[:remove_comment] | |
| 79 | - remove_comment | |
| 80 | + if request.post? | |
| 81 | + if params[:remove_comment] | |
| 82 | + remove_comment | |
| 83 | + return | |
| 84 | + elsif params[:mark_comment_as_spam] | |
| 85 | + mark_comment_as_spam | |
| 86 | + return | |
| 87 | + end | |
| 80 | 88 | end |
| 81 | 89 | |
| 82 | 90 | if @page.has_posts? |
| ... | ... | @@ -107,23 +115,46 @@ class ContentViewerController < ApplicationController |
| 107 | 115 | end |
| 108 | 116 | end |
| 109 | 117 | |
| 110 | - @comments = @page.comments(true).as_thread | |
| 111 | - @comments_count = @page.comments.count | |
| 118 | + comments = @page.comments.without_spam | |
| 119 | + @comments = comments.as_thread | |
| 120 | + @comments_count = comments.count | |
| 112 | 121 | if params[:slideshow] |
| 113 | 122 | render :action => 'slideshow', :layout => 'slideshow' |
| 114 | 123 | end |
| 115 | 124 | end |
| 116 | 125 | |
| 126 | + def edit_comment | |
| 127 | + path = params[:page].join('/') | |
| 128 | + @page = profile.articles.find_by_path(path) | |
| 129 | + @form_div = 'opened' | |
| 130 | + @comment = @page.comments.find_by_id(params[:id]) | |
| 131 | + if @comment | |
| 132 | + if request.post? | |
| 133 | + begin | |
| 134 | + @comment.update_attributes(params[:comment]) | |
| 135 | + session[:notice] = _('Comment succesfully updated') | |
| 136 | + redirect_to :action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path | |
| 137 | + rescue | |
| 138 | + session[:notice] = _('Comment could not be updated') | |
| 139 | + end | |
| 140 | + end | |
| 141 | + else | |
| 142 | + redirect_to @page.view_url | |
| 143 | + session[:notice] = _('Could not find the comment in the article') | |
| 144 | + end | |
| 145 | + end | |
| 146 | + | |
| 117 | 147 | protected |
| 118 | 148 | |
| 119 | 149 | def add_comment |
| 120 | 150 | @comment.author = user if logged_in? |
| 121 | 151 | @comment.article = @page |
| 122 | 152 | @comment.ip_address = request.remote_ip |
| 153 | + @comment.user_agent = request.user_agent | |
| 154 | + @comment.referrer = request.referrer | |
| 123 | 155 | plugins_filter_comment(@comment) |
| 124 | 156 | return if @comment.rejected? |
| 125 | 157 | if (pass_without_comment_captcha? || verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) && @comment.save |
| 126 | - plugins_comment_saved(@comment) | |
| 127 | 158 | @page.touch |
| 128 | 159 | @comment = nil # clear the comment form |
| 129 | 160 | redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] |
| ... | ... | @@ -138,12 +169,6 @@ class ContentViewerController < ApplicationController |
| 138 | 169 | end |
| 139 | 170 | end |
| 140 | 171 | |
| 141 | - def plugins_comment_saved(comment) | |
| 142 | - @plugins.each do |plugin| | |
| 143 | - plugin.comment_saved(comment) | |
| 144 | - end | |
| 145 | - end | |
| 146 | - | |
| 147 | 172 | def pass_without_comment_captcha? |
| 148 | 173 | logged_in? && !environment.enabled?('captcha_for_logged_users') |
| 149 | 174 | end |
| ... | ... | @@ -153,9 +178,24 @@ class ContentViewerController < ApplicationController |
| 153 | 178 | @comment = @page.comments.find(params[:remove_comment]) |
| 154 | 179 | if (user == @comment.author || user == @page.profile || user.has_permission?(:moderate_comments, @page.profile)) |
| 155 | 180 | @comment.destroy |
| 156 | - session[:notice] = _('Comment succesfully deleted') | |
| 157 | 181 | end |
| 158 | - redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] | |
| 182 | + finish_comment_handling | |
| 183 | + end | |
| 184 | + | |
| 185 | + def mark_comment_as_spam | |
| 186 | + @comment = @page.comments.find(params[:mark_comment_as_spam]) | |
| 187 | + if logged_in? && (user == @page.profile || user.has_permission?(:moderate_comments, @page.profile)) | |
| 188 | + @comment.spam! | |
| 189 | + end | |
| 190 | + finish_comment_handling | |
| 191 | + end | |
| 192 | + | |
| 193 | + def finish_comment_handling | |
| 194 | + if request.xhr? | |
| 195 | + render :text => {'ok' => true}.to_json, :content_type => 'application/json' | |
| 196 | + else | |
| 197 | + redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] | |
| 198 | + end | |
| 159 | 199 | end |
| 160 | 200 | |
| 161 | 201 | def per_page |
| ... | ... | @@ -181,4 +221,13 @@ class ContentViewerController < ApplicationController |
| 181 | 221 | end |
| 182 | 222 | end |
| 183 | 223 | |
| 224 | + def comment_author | |
| 225 | + comment = Comment.find_by_id(params[:id]) | |
| 226 | + if comment | |
| 227 | + render_access_denied if comment.author.blank? || comment.author != user | |
| 228 | + else | |
| 229 | + render_not_found | |
| 230 | + end | |
| 231 | + end | |
| 232 | + | |
| 184 | 233 | end | ... | ... |
app/controllers/public/not_found_controller.rb
app/controllers/public/profile_controller.rb
| ... | ... | @@ -2,11 +2,13 @@ class ProfileController < PublicController |
| 2 | 2 | |
| 3 | 3 | needs_profile |
| 4 | 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 | 8 | helper TagsHelper |
| 9 | 9 | |
| 10 | + protect 'send_mail_to_members', :profile, :only => [:send_mail] | |
| 11 | + | |
| 10 | 12 | def index |
| 11 | 13 | @network_activities = !@profile.is_a?(Person) ? @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) : [] |
| 12 | 14 | if logged_in? && current_person.follows?(@profile) |
| ... | ... | @@ -49,36 +51,36 @@ class ProfileController < PublicController |
| 49 | 51 | |
| 50 | 52 | def communities |
| 51 | 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 | 55 | end |
| 54 | 56 | end |
| 55 | 57 | |
| 56 | 58 | def enterprises |
| 57 | - @enterprises = profile.enterprises | |
| 59 | + @enterprises = profile.enterprises.includes(relations_to_include) | |
| 58 | 60 | end |
| 59 | 61 | |
| 60 | 62 | def friends |
| 61 | 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 | 65 | end |
| 64 | 66 | end |
| 65 | 67 | |
| 66 | 68 | def members |
| 67 | 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 | 71 | end |
| 70 | 72 | end |
| 71 | 73 | |
| 72 | 74 | def fans |
| 73 | - @fans = profile.fans | |
| 75 | + @fans = profile.fans.includes(relations_to_include) | |
| 74 | 76 | end |
| 75 | 77 | |
| 76 | 78 | def favorite_enterprises |
| 77 | - @favorite_enterprises = profile.favorite_enterprises | |
| 79 | + @favorite_enterprises = profile.favorite_enterprises.includes(relations_to_include) | |
| 78 | 80 | end |
| 79 | 81 | |
| 80 | 82 | def sitemap |
| 81 | - @articles = profile.top_level_articles | |
| 83 | + @articles = profile.top_level_articles.includes([:profile, :parent]) | |
| 82 | 84 | end |
| 83 | 85 | |
| 84 | 86 | def join |
| ... | ... | @@ -212,9 +214,9 @@ class ProfileController < PublicController |
| 212 | 214 | begin |
| 213 | 215 | scrap = current_user.person.scraps(params[:scrap_id]) |
| 214 | 216 | scrap.destroy |
| 215 | - render :text => _('Scrap successfully removed.') | |
| 217 | + finish_successful_removal 'Scrap successfully removed.' | |
| 216 | 218 | rescue |
| 217 | - render :text => _('You could not remove this scrap') | |
| 219 | + finish_unsuccessful_removal 'You could not remove this scrap.' | |
| 218 | 220 | end |
| 219 | 221 | end |
| 220 | 222 | |
| ... | ... | @@ -227,9 +229,9 @@ class ProfileController < PublicController |
| 227 | 229 | else |
| 228 | 230 | activity.destroy |
| 229 | 231 | end |
| 230 | - render :text => _('Activity successfully removed.') | |
| 232 | + finish_successful_removal 'Activity successfully removed.' | |
| 231 | 233 | rescue |
| 232 | - render :text => _('You could not remove this activity') | |
| 234 | + finish_unsuccessful_removal 'You could not remove this activity.' | |
| 233 | 235 | end |
| 234 | 236 | end |
| 235 | 237 | |
| ... | ... | @@ -244,6 +246,24 @@ class ProfileController < PublicController |
| 244 | 246 | end |
| 245 | 247 | end |
| 246 | 248 | |
| 249 | + def finish_successful_removal(msg) | |
| 250 | + if request.xhr? | |
| 251 | + render :text => {'ok' => true}.to_json, :content_type => 'application/json' | |
| 252 | + else | |
| 253 | + session[:notice] = _(msg) | |
| 254 | + redirect_to :action => :index | |
| 255 | + end | |
| 256 | + end | |
| 257 | + | |
| 258 | + def finish_unsuccessful_removal(msg) | |
| 259 | + session[:notice] = _(msg) | |
| 260 | + if request.xhr? | |
| 261 | + render :text => {'redirect' => url_for(:action => :index)}.to_json, :content_type => 'application/json' | |
| 262 | + else | |
| 263 | + redirect_to :action => :index | |
| 264 | + end | |
| 265 | + end | |
| 266 | + | |
| 247 | 267 | def profile_info |
| 248 | 268 | begin |
| 249 | 269 | @block = profile.blocks.find(params[:block_id]) |
| ... | ... | @@ -303,9 +323,24 @@ class ProfileController < PublicController |
| 303 | 323 | @comment = Comment.find(params[:comment_id]) |
| 304 | 324 | if (user == @comment.author || user == profile || user.has_permission?(:moderate_comments, profile)) |
| 305 | 325 | @comment.destroy |
| 306 | - session[:notice] = _('Comment successfully deleted') | |
| 326 | + finish_successful_removal 'Comment successfully removed.' | |
| 327 | + else | |
| 328 | + finish_unsuccessful_removal 'You could not remove this comment.' | |
| 329 | + end | |
| 330 | + end | |
| 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 | |
| 307 | 343 | end |
| 308 | - redirect_to :action => :index | |
| 309 | 344 | end |
| 310 | 345 | |
| 311 | 346 | protected |
| ... | ... | @@ -359,4 +394,8 @@ class ProfileController < PublicController |
| 359 | 394 | @can_edit_profile ||= user && user.has_permission?('edit_profile', profile) |
| 360 | 395 | end |
| 361 | 396 | helper_method :can_edit_profile |
| 397 | + | |
| 398 | + def relations_to_include | |
| 399 | + [:image, :domains, :preferred_domain, :environment] | |
| 400 | + end | |
| 362 | 401 | end | ... | ... |
app/controllers/public/search_controller.rb
| ... | ... | @@ -4,10 +4,17 @@ class SearchController < PublicController |
| 4 | 4 | include SearchHelper |
| 5 | 5 | include ActionView::Helpers::NumberHelper |
| 6 | 6 | |
| 7 | + before_filter :redirect_asset_param, :except => [:facets_browse, :assets] | |
| 7 | 8 | before_filter :load_category |
| 8 | 9 | before_filter :load_search_assets |
| 9 | 10 | before_filter :load_query |
| 10 | 11 | |
| 12 | + # Backwards compatibility with old URLs | |
| 13 | + def redirect_asset_param | |
| 14 | + return unless params.has_key?(:asset) | |
| 15 | + redirect_to params.merge(:action => params.delete(:asset)) | |
| 16 | + end | |
| 17 | + | |
| 11 | 18 | no_design_blocks |
| 12 | 19 | |
| 13 | 20 | def facets_browse |
| ... | ... | @@ -39,7 +46,7 @@ class SearchController < PublicController |
| 39 | 46 | if !@empty_query |
| 40 | 47 | full_text_search ['public:true'] |
| 41 | 48 | else |
| 42 | - @results[@asset] = @environment.people.visible.send(@filter).paginate(paginate_options) | |
| 49 | + @results[@asset] = visible_profiles(Person).send(@filter).paginate(paginate_options) | |
| 43 | 50 | end |
| 44 | 51 | end |
| 45 | 52 | |
| ... | ... | @@ -69,7 +76,7 @@ class SearchController < PublicController |
| 69 | 76 | full_text_search ['public:true'] |
| 70 | 77 | else |
| 71 | 78 | @filter_title = _('Enterprises from network') |
| 72 | - @results[@asset] = @environment.enterprises.visible.paginate(paginate_options) | |
| 79 | + @results[@asset] = visible_profiles(Enterprise, [{:products => :product_category}]).paginate(paginate_options) | |
| 73 | 80 | end |
| 74 | 81 | end |
| 75 | 82 | |
| ... | ... | @@ -77,7 +84,7 @@ class SearchController < PublicController |
| 77 | 84 | if !@empty_query |
| 78 | 85 | full_text_search ['public:true'] |
| 79 | 86 | else |
| 80 | - @results[@asset] = @environment.communities.visible.send(@filter).paginate(paginate_options) | |
| 87 | + @results[@asset] = visible_profiles(Community).send(@filter).paginate(paginate_options) | |
| 81 | 88 | end |
| 82 | 89 | end |
| 83 | 90 | |
| ... | ... | @@ -250,10 +257,9 @@ class SearchController < PublicController |
| 250 | 257 | end |
| 251 | 258 | |
| 252 | 259 | def limit |
| 253 | - searching = @searching.values.select{ |v| v } | |
| 254 | - if params[:display] == 'map' | |
| 260 | + if map_search? | |
| 255 | 261 | MAP_SEARCH_LIMIT |
| 256 | - elsif searching.size <= 1 | |
| 262 | + elsif !multiple_search? | |
| 257 | 263 | if [:people, :communities].include? @asset |
| 258 | 264 | BLOCKS_SEARCH_LIMIT |
| 259 | 265 | elsif @asset == :enterprises and @empty_query |
| ... | ... | @@ -267,31 +273,34 @@ class SearchController < PublicController |
| 267 | 273 | end |
| 268 | 274 | |
| 269 | 275 | def paginate_options(page = params[:page]) |
| 276 | + page = 1 if multiple_search? or params[:display] == 'map' | |
| 270 | 277 | { :per_page => limit, :page => page } |
| 271 | 278 | end |
| 272 | 279 | |
| 273 | 280 | def full_text_search(filters = [], options = {}) |
| 274 | 281 | paginate_options = paginate_options(params[:page]) |
| 275 | 282 | asset_class = asset_class(@asset) |
| 276 | - | |
| 277 | 283 | solr_options = options |
| 278 | - if !@results_only and asset_class.respond_to? :facets | |
| 279 | - solr_options.merge! asset_class.facets_find_options(params[:facet]) | |
| 280 | - solr_options[:all_facets] = true | |
| 281 | - solr_options[:limit] = 0 if @facets_only | |
| 282 | - end | |
| 283 | - solr_options[:filter_queries] ||= [] | |
| 284 | - solr_options[:filter_queries] += filters | |
| 285 | - solr_options[:filter_queries] << "environment_id:#{environment.id}" | |
| 286 | - solr_options[:filter_queries] << asset_class.facet_category_query.call(@category) if @category | |
| 287 | - | |
| 288 | - solr_options[:boost_functions] ||= [] | |
| 289 | - params[:order_by] = nil if params[:order_by] == 'none' | |
| 290 | - if params[:order_by] | |
| 291 | - order = SortOptions[@asset][params[:order_by].to_sym] | |
| 292 | - raise "Unknown order by" if order.nil? | |
| 293 | - order[:solr_opts].each do |opt, value| | |
| 294 | - solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value | |
| 284 | + pg_options = paginate_options(params[:page]) | |
| 285 | + | |
| 286 | + if !multiple_search? | |
| 287 | + if !@results_only and asset_class.respond_to? :facets | |
| 288 | + solr_options.merge! asset_class.facets_find_options(params[:facet]) | |
| 289 | + solr_options[:all_facets] = true | |
| 290 | + end | |
| 291 | + solr_options[:filter_queries] ||= [] | |
| 292 | + solr_options[:filter_queries] += filters | |
| 293 | + solr_options[:filter_queries] << "environment_id:#{environment.id}" | |
| 294 | + solr_options[:filter_queries] << asset_class.facet_category_query.call(@category) if @category | |
| 295 | + | |
| 296 | + solr_options[:boost_functions] ||= [] | |
| 297 | + params[:order_by] = nil if params[:order_by] == 'none' | |
| 298 | + if params[:order_by] | |
| 299 | + order = SortOptions[@asset][params[:order_by].to_sym] | |
| 300 | + raise "Unknown order by" if order.nil? | |
| 301 | + order[:solr_opts].each do |opt, value| | |
| 302 | + solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value | |
| 303 | + end | |
| 295 | 304 | end |
| 296 | 305 | end |
| 297 | 306 | |
| ... | ... | @@ -301,4 +310,12 @@ class SearchController < PublicController |
| 301 | 310 | @all_facets = ret[:all_facets] |
| 302 | 311 | end |
| 303 | 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 | + | |
| 304 | 321 | end | ... | ... |
app/helpers/application_helper.rb
| ... | ... | @@ -265,9 +265,9 @@ module ApplicationHelper |
| 265 | 265 | |
| 266 | 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 | 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 | 272 | search_name = String.new(name) |
| 273 | 273 | if search_name.include?("/") |
| ... | ... | @@ -282,31 +282,20 @@ module ApplicationHelper |
| 282 | 282 | return name if File.exists?(File.join(path)) |
| 283 | 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 | 286 | end |
| 287 | 287 | |
| 288 | - def partial_for_class(klass) | |
| 288 | + def partial_for_class(klass, suffix=nil) | |
| 289 | 289 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? |
| 290 | 290 | name = klass.name.underscore |
| 291 | 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 | 293 | return partial if partial |
| 294 | 294 | end |
| 295 | 295 | |
| 296 | 296 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' |
| 297 | 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 | 299 | def view_for_profile_actions(klass) |
| 311 | 300 | raise ArgumentError, 'No profile actions view for this class.' if klass.nil? |
| 312 | 301 | |
| ... | ... | @@ -1336,6 +1325,19 @@ module ApplicationHelper |
| 1336 | 1325 | end |
| 1337 | 1326 | end |
| 1338 | 1327 | |
| 1328 | + def expirable_link_to(expired, content, url, options = {}) | |
| 1329 | + if expired | |
| 1330 | + options[:class] = (options[:class] || '') + ' disabled' | |
| 1331 | + content_tag('a', ' '+content_tag('span', content), options) | |
| 1332 | + else | |
| 1333 | + link_to content, url, options | |
| 1334 | + end | |
| 1335 | + end | |
| 1336 | + | |
| 1337 | + def remove_content_button(action) | |
| 1338 | + @plugins.dispatch("content_remove_#{action.to_s}", @page).include?(true) | |
| 1339 | + end | |
| 1340 | + | |
| 1339 | 1341 | def template_options(klass, field_name) |
| 1340 | 1342 | return '' if klass.templates.count == 0 |
| 1341 | 1343 | return hidden_field_tag("#{field_name}[template_id]", klass.templates.first.id) if klass.templates.count == 1 |
| ... | ... | @@ -1401,4 +1403,19 @@ module ApplicationHelper |
| 1401 | 1403 | result |
| 1402 | 1404 | end |
| 1403 | 1405 | |
| 1406 | + def expirable_content_reference(content, action, text, url, options = {}) | |
| 1407 | + reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first | |
| 1408 | + options[:title] = reason | |
| 1409 | + expirable_link_to reason.present?, text, url, options | |
| 1410 | + end | |
| 1411 | + | |
| 1412 | + def expirable_button(content, action, text, url, options = {}) | |
| 1413 | + options[:class] = "button with-text icon-#{action.to_s}" | |
| 1414 | + expirable_content_reference content, action, text, url, options | |
| 1415 | + end | |
| 1416 | + | |
| 1417 | + def expirable_comment_link(content, action, text, url, options = {}) | |
| 1418 | + options[:class] = "comment-footer comment-footer-link comment-footer-hide" | |
| 1419 | + expirable_content_reference content, action, text, url, options | |
| 1420 | + end | |
| 1404 | 1421 | end | ... | ... |
app/helpers/article_helper.rb
| ... | ... | @@ -2,14 +2,19 @@ module ArticleHelper |
| 2 | 2 | |
| 3 | 3 | def custom_options_for_article(article) |
| 4 | 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 | 16 | content_tag('h4', _('Options')) + |
| 6 | 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 | 18 | (article.profile.has_members? ? |
| 14 | 19 | content_tag( |
| 15 | 20 | 'div', | ... | ... |
app/helpers/boxes_helper.rb
| ... | ... | @@ -66,7 +66,7 @@ module BoxesHelper |
| 66 | 66 | |
| 67 | 67 | def display_box_content(box, main_content) |
| 68 | 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 | 70 | end |
| 71 | 71 | |
| 72 | 72 | def select_blocks(arr, context) |
| ... | ... | @@ -162,9 +162,6 @@ module BoxesHelper |
| 162 | 162 | # |
| 163 | 163 | # +box+ is always needed |
| 164 | 164 | def block_target(box, block = nil) |
| 165 | - # FIXME hardcoded | |
| 166 | - return '' if box.position == 1 | |
| 167 | - | |
| 168 | 165 | id = |
| 169 | 166 | if block.nil? |
| 170 | 167 | "end-of-box-#{box.id}" |
| ... | ... | @@ -172,14 +169,11 @@ module BoxesHelper |
| 172 | 169 | "before-block-#{block.id}" |
| 173 | 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 | 173 | end |
| 177 | 174 | |
| 178 | 175 | # makes the given block draggable so it can be moved away. |
| 179 | 176 | def block_handle(block) |
| 180 | - # FIXME hardcoded | |
| 181 | - return '' if block.box.position == 1 | |
| 182 | - | |
| 183 | 177 | draggable_element("block-#{block.id}", :revert => true) |
| 184 | 178 | end |
| 185 | 179 | |
| ... | ... | @@ -211,7 +205,7 @@ module BoxesHelper |
| 211 | 205 | end |
| 212 | 206 | |
| 213 | 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 | 209 | end |
| 216 | 210 | |
| 217 | 211 | if !block.main? | ... | ... |
app/helpers/cms_helper.rb
| ... | ... | @@ -42,13 +42,25 @@ module CmsHelper |
| 42 | 42 | |
| 43 | 43 | def display_spread_button(profile, article) |
| 44 | 44 | if profile.person? |
| 45 | - button_without_text :spread, _('Spread this'), :action => 'publish', :id => article.id | |
| 45 | + expirable_button article, :spread, _('Spread this'), :action => 'publish', :id => article.id | |
| 46 | 46 | elsif profile.community? && environment.portal_community |
| 47 | - button_without_text :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id | |
| 47 | + expirable_button article, :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id | |
| 48 | 48 | end |
| 49 | 49 | end |
| 50 | 50 | |
| 51 | 51 | def display_delete_button(article) |
| 52 | - button_without_text :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article) | |
| 52 | + expirable_button article, :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article) | |
| 53 | + end | |
| 54 | + | |
| 55 | + def expirable_button(content, action, title, url, options = {}) | |
| 56 | + reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first | |
| 57 | + if reason.present? | |
| 58 | + options[:class] = (options[:class] || '') + ' disabled' | |
| 59 | + options[:disabled] = 'disabled' | |
| 60 | + options.delete(:confirm) | |
| 61 | + options.delete(:method) | |
| 62 | + title = reason | |
| 63 | + end | |
| 64 | + button_without_text action.to_sym, title, url, options | |
| 53 | 65 | end |
| 54 | 66 | end | ... | ... |
app/helpers/colorbox_helper.rb
| ... | ... | @@ -8,6 +8,10 @@ module ColorboxHelper |
| 8 | 8 | button(type, label, url, colorbox_options(options)) |
| 9 | 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 | 15 | # options must be an HTML options hash as passed to link_to etc. |
| 12 | 16 | # |
| 13 | 17 | # returns a new hash with colorbox class added. Keeps existing classes. | ... | ... |
app/helpers/content_viewer_helper.rb
| ... | ... | @@ -4,11 +4,11 @@ module ContentViewerHelper |
| 4 | 4 | include ForumHelper |
| 5 | 5 | |
| 6 | 6 | def number_of_comments(article) |
| 7 | - n = article.comments.size | |
| 7 | + n = article.comments.without_spam.count | |
| 8 | 8 | if n == 0 |
| 9 | 9 | _('No comments yet') |
| 10 | 10 | else |
| 11 | - n_('One comment', '%{comments} comments', n) % { :comments => n } | |
| 11 | + n_('One comment', '<span class="comment-count">%{comments}</span> comments', n) % { :comments => n } | |
| 12 | 12 | end |
| 13 | 13 | end |
| 14 | 14 | ... | ... |
app/helpers/folder_helper.rb
| ... | ... | @@ -58,18 +58,18 @@ module FolderHelper |
| 58 | 58 | |
| 59 | 59 | def custom_options_for_article(article) |
| 60 | 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 | 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 | 73 | hidden_field_tag('article[accept_comments]', 0) |
| 74 | 74 | ) |
| 75 | 75 | end | ... | ... |
app/helpers/forms_helper.rb
| ... | ... | @@ -123,6 +123,119 @@ module FormsHelper |
| 123 | 123 | options_for_select.join("\n") |
| 124 | 124 | end |
| 125 | 125 | |
| 126 | + def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) | |
| 127 | + datepicker_options[:disabled] ||= false | |
| 128 | + datepicker_options[:alt_field] ||= '' | |
| 129 | + datepicker_options[:alt_format] ||= '' | |
| 130 | + datepicker_options[:append_text] ||= '' | |
| 131 | + datepicker_options[:auto_size] ||= false | |
| 132 | + datepicker_options[:button_image] ||= '' | |
| 133 | + datepicker_options[:button_image_only] ||= false | |
| 134 | + datepicker_options[:button_text] ||= '...' | |
| 135 | + datepicker_options[:calculate_week] ||= 'jQuery.datepicker.iso8601Week' | |
| 136 | + datepicker_options[:change_month] ||= false | |
| 137 | + datepicker_options[:change_year] ||= false | |
| 138 | + datepicker_options[:close_text] ||= _('Done') | |
| 139 | + datepicker_options[:constrain_input] ||= true | |
| 140 | + datepicker_options[:current_text] ||= _('Today') | |
| 141 | + datepicker_options[:date_format] ||= 'mm/dd/yy' | |
| 142 | + datepicker_options[:day_names] ||= [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')] | |
| 143 | + datepicker_options[:day_names_min] ||= [_('Su'), _('Mo'), _('Tu'), _('We'), _('Th'), _('Fr'), _('Sa')] | |
| 144 | + datepicker_options[:day_names_short] ||= [_('Sun'), _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat')] | |
| 145 | + datepicker_options[:default_date] ||= nil | |
| 146 | + datepicker_options[:duration] ||= 'normal' | |
| 147 | + datepicker_options[:first_day] ||= 0 | |
| 148 | + datepicker_options[:goto_current] ||= false | |
| 149 | + datepicker_options[:hide_if_no_prev_next] ||= false | |
| 150 | + datepicker_options[:is_rtl] ||= false | |
| 151 | + datepicker_options[:max_date] ||= nil | |
| 152 | + datepicker_options[:min_date] ||= nil | |
| 153 | + datepicker_options[:month_names] ||= [_('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July'), _('August'), _('September'), _('October'), _('November'), _('December')] | |
| 154 | + datepicker_options[:month_names_short] ||= [_('Jan'), _('Feb'), _('Mar'), _('Apr'), _('May'), _('Jun'), _('Jul'), _('Aug'), _('Sep'), _('Oct'), _('Nov'), _('Dec')] | |
| 155 | + datepicker_options[:navigation_as_date_format] ||= false | |
| 156 | + datepicker_options[:next_text] ||= _('Next') | |
| 157 | + datepicker_options[:number_of_months] ||= 1 | |
| 158 | + datepicker_options[:prev_text] ||= _('Prev') | |
| 159 | + datepicker_options[:select_other_months] ||= false | |
| 160 | + datepicker_options[:short_year_cutoff] ||= '+10' | |
| 161 | + datepicker_options[:show_button_panel] ||= false | |
| 162 | + datepicker_options[:show_current_at_pos] ||= 0 | |
| 163 | + datepicker_options[:show_month_after_year] ||= false | |
| 164 | + datepicker_options[:show_on] ||= 'focus' | |
| 165 | + datepicker_options[:show_options] ||= {} | |
| 166 | + datepicker_options[:show_other_months] ||= false | |
| 167 | + datepicker_options[:show_week] ||= false | |
| 168 | + datepicker_options[:step_months] ||= 1 | |
| 169 | + datepicker_options[:week_header] ||= _('Wk') | |
| 170 | + datepicker_options[:year_range] ||= 'c-10:c+10' | |
| 171 | + datepicker_options[:year_suffix] ||= '' | |
| 172 | + | |
| 173 | + element_id = html_options[:id] || 'datepicker-date' | |
| 174 | + value = value.strftime(format) if value.present? | |
| 175 | + method = datepicker_options[:time] ? 'datetimepicker' : 'datepicker' | |
| 176 | + result = text_field_tag(name, value, html_options) | |
| 177 | + result += | |
| 178 | + " | |
| 179 | + <script type='text/javascript'> | |
| 180 | + jQuery('##{element_id}').#{method}({ | |
| 181 | + disabled: #{datepicker_options[:disabled].to_json}, | |
| 182 | + altField: #{datepicker_options[:alt_field].to_json}, | |
| 183 | + altFormat: #{datepicker_options[:alt_format].to_json}, | |
| 184 | + appendText: #{datepicker_options[:append_text].to_json}, | |
| 185 | + autoSize: #{datepicker_options[:auto_size].to_json}, | |
| 186 | + buttonImage: #{datepicker_options[:button_image].to_json}, | |
| 187 | + buttonImageOnly: #{datepicker_options[:button_image_only].to_json}, | |
| 188 | + buttonText: #{datepicker_options[:button_text].to_json}, | |
| 189 | + calculateWeek: #{datepicker_options[:calculate_week].to_json}, | |
| 190 | + changeMonth: #{datepicker_options[:change_month].to_json}, | |
| 191 | + changeYear: #{datepicker_options[:change_year].to_json}, | |
| 192 | + closeText: #{datepicker_options[:close_text].to_json}, | |
| 193 | + constrainInput: #{datepicker_options[:constrain_input].to_json}, | |
| 194 | + currentText: #{datepicker_options[:current_text].to_json}, | |
| 195 | + dateFormat: #{datepicker_options[:date_format].to_json}, | |
| 196 | + dayNames: #{datepicker_options[:day_names].to_json}, | |
| 197 | + dayNamesMin: #{datepicker_options[:day_names_min].to_json}, | |
| 198 | + dayNamesShort: #{datepicker_options[:day_names_short].to_json}, | |
| 199 | + defaultDate: #{datepicker_options[:default_date].to_json}, | |
| 200 | + duration: #{datepicker_options[:duration].to_json}, | |
| 201 | + firstDay: #{datepicker_options[:first_day].to_json}, | |
| 202 | + gotoCurrent: #{datepicker_options[:goto_current].to_json}, | |
| 203 | + hideIfNoPrevNext: #{datepicker_options[:hide_if_no_prev_next].to_json}, | |
| 204 | + isRTL: #{datepicker_options[:is_rtl].to_json}, | |
| 205 | + maxDate: #{datepicker_options[:max_date].to_json}, | |
| 206 | + minDate: #{datepicker_options[:min_date].to_json}, | |
| 207 | + monthNames: #{datepicker_options[:month_names].to_json}, | |
| 208 | + monthNamesShort: #{datepicker_options[:month_names_short].to_json}, | |
| 209 | + navigationAsDateFormat: #{datepicker_options[:navigation_as_date_format].to_json}, | |
| 210 | + nextText: #{datepicker_options[:next_text].to_json}, | |
| 211 | + numberOfMonths: #{datepicker_options[:number_of_months].to_json}, | |
| 212 | + prevText: #{datepicker_options[:prev_text].to_json}, | |
| 213 | + selectOtherMonths: #{datepicker_options[:select_other_months].to_json}, | |
| 214 | + shortYearCutoff: #{datepicker_options[:short_year_cutoff].to_json}, | |
| 215 | + showButtonPanel: #{datepicker_options[:show_button_panel].to_json}, | |
| 216 | + showCurrentAtPos: #{datepicker_options[:show_current_at_pos].to_json}, | |
| 217 | + showMonthAfterYear: #{datepicker_options[:show_month_after_year].to_json}, | |
| 218 | + showOn: #{datepicker_options[:show_on].to_json}, | |
| 219 | + showOptions: #{datepicker_options[:show_options].to_json}, | |
| 220 | + showOtherMonths: #{datepicker_options[:show_other_months].to_json}, | |
| 221 | + showWeek: #{datepicker_options[:show_week].to_json}, | |
| 222 | + stepMonths: #{datepicker_options[:step_months].to_json}, | |
| 223 | + weekHeader: #{datepicker_options[:week_header].to_json}, | |
| 224 | + yearRange: #{datepicker_options[:year_range].to_json}, | |
| 225 | + yearSuffix: #{datepicker_options[:year_suffix].to_json} | |
| 226 | + }) | |
| 227 | + </script> | |
| 228 | + " | |
| 229 | + result | |
| 230 | + end | |
| 231 | + | |
| 232 | + def date_range_field(from_name, to_name, from_value, to_value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) | |
| 233 | + from_id = html_options[:from_id] || 'datepicker-from-date' | |
| 234 | + to_id = html_options[:to_id] || 'datepicker-to-date' | |
| 235 | + return _('From') +' '+ date_field(from_name, from_value, format, datepicker_options, html_options.merge({:id => from_id})) + | |
| 236 | + ' ' + _('until') +' '+ date_field(to_name, to_value, format, datepicker_options, html_options.merge({:id => to_id})) | |
| 237 | + end | |
| 238 | + | |
| 126 | 239 | protected |
| 127 | 240 | def self.next_id_number |
| 128 | 241 | if defined? @@id_num | ... | ... |
app/helpers/search_helper.rb
| ... | ... | @@ -45,6 +45,14 @@ module SearchHelper |
| 45 | 45 | # FIXME remove it after search_controler refactored |
| 46 | 46 | include EventsHelper |
| 47 | 47 | |
| 48 | + def multiple_search? | |
| 49 | + ['index', 'category_index'].include?(params[:action]) or @results.size > 1 | |
| 50 | + end | |
| 51 | + | |
| 52 | + def map_search? | |
| 53 | + !@empty_query and !multiple_search? and params[:display] == 'map' | |
| 54 | + end | |
| 55 | + | |
| 48 | 56 | def search_page_title(title, category = nil) |
| 49 | 57 | title = "<h1>" + title |
| 50 | 58 | title += '<small>' + category.name + '</small>' if category |
| ... | ... | @@ -58,8 +66,8 @@ module SearchHelper |
| 58 | 66 | :align => 'center', :class => 'search-category-context') if category |
| 59 | 67 | end |
| 60 | 68 | |
| 61 | - def display_results(use_map = false) | |
| 62 | - if params[:display] == 'map' && use_map | |
| 69 | + def display_results(map_capable = false) | |
| 70 | + if map_capable and map_search? | |
| 63 | 71 | partial = 'google_maps' |
| 64 | 72 | klass = 'map' |
| 65 | 73 | else |
| ... | ... | @@ -99,7 +107,7 @@ module SearchHelper |
| 99 | 107 | @asset_class = asset_class(asset) |
| 100 | 108 | render(:partial => 'facets_unselect_menu') |
| 101 | 109 | end |
| 102 | - | |
| 110 | + | |
| 103 | 111 | def facet_javascript(input_id, facet, array) |
| 104 | 112 | array = [] if array.nil? |
| 105 | 113 | hintText = _('Type in an option') |
| ... | ... | @@ -148,6 +156,7 @@ module SearchHelper |
| 148 | 156 | params = params.dup |
| 149 | 157 | params[:facet].each do |id, value| |
| 150 | 158 | facet = klass.facet_by_id(id.to_sym) |
| 159 | + next unless facet | |
| 151 | 160 | if value.kind_of?(Hash) |
| 152 | 161 | label_hash = facet[:label].call(environment) |
| 153 | 162 | value.each do |label_id, value| | ... | ... |
app/models/article.rb
| ... | ... | @@ -179,37 +179,23 @@ class Article < ActiveRecord::Base |
| 179 | 179 | end |
| 180 | 180 | |
| 181 | 181 | 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 | |
| 182 | + named_scope :relevant_as_recent, :conditions => ["(articles.type != 'UploadedFile' and articles.type != 'RssFeed' and articles.type != 'Blog') OR articles.type is NULL"] | |
| 183 | + | |
| 184 | + def self.recent(limit = nil, extra_conditions = {}, pagination = true) | |
| 185 | + result = scoped({:conditions => extra_conditions}). | |
| 186 | + public. | |
| 187 | + relevant_as_recent. | |
| 188 | + limit(limit). | |
| 189 | + order(['articles.published_at desc', 'articles.id desc']) | |
| 190 | + | |
| 191 | + if !( scoped_methods && scoped_methods.last && | |
| 192 | + scoped_methods.last[:find] && | |
| 193 | + scoped_methods.last[:find][:joins] && | |
| 194 | + scoped_methods.last[:find][:joins].index('profiles') ) | |
| 195 | + result = result.includes(:profile) | |
| 212 | 196 | end |
| 197 | + | |
| 198 | + pagination ? result.paginate({:page => 1, :per_page => limit}) : result | |
| 213 | 199 | end |
| 214 | 200 | |
| 215 | 201 | # produces the HTML code that is to be displayed as this article's contents. | ... | ... |
app/models/box.rb
| ... | ... | @@ -2,4 +2,76 @@ class Box < ActiveRecord::Base |
| 2 | 2 | belongs_to :owner, :polymorphic => true |
| 3 | 3 | acts_as_list :scope => 'owner_id = #{owner_id} and owner_type = \'#{owner_type}\'' |
| 4 | 4 | has_many :blocks, :dependent => :destroy, :order => 'position' |
| 5 | + | |
| 6 | + def acceptable_blocks | |
| 7 | + to_css_class_name central? ? Box.acceptable_center_blocks : Box.acceptable_side_blocks | |
| 8 | + end | |
| 9 | + | |
| 10 | + def central? | |
| 11 | + position == 1 | |
| 12 | + end | |
| 13 | + | |
| 14 | + def self.acceptable_center_blocks | |
| 15 | + [ ArticleBlock, | |
| 16 | + BlogArchivesBlock, | |
| 17 | + CategoriesBlock, | |
| 18 | + CommunitiesBlock, | |
| 19 | + EnterprisesBlock, | |
| 20 | + EnvironmentStatisticsBlock, | |
| 21 | + FansBlock, | |
| 22 | + FavoriteEnterprisesBlock, | |
| 23 | + FeedReaderBlock, | |
| 24 | + FriendsBlock, | |
| 25 | + HighlightsBlock, | |
| 26 | + LinkListBlock, | |
| 27 | + LoginBlock, | |
| 28 | + MainBlock, | |
| 29 | + MembersBlock, | |
| 30 | + MyNetworkBlock, | |
| 31 | + PeopleBlock, | |
| 32 | + ProfileImageBlock, | |
| 33 | + RawHTMLBlock, | |
| 34 | + RecentDocumentsBlock, | |
| 35 | + SellersSearchBlock, | |
| 36 | + TagsBlock ] | |
| 37 | + end | |
| 38 | + | |
| 39 | + def self.acceptable_side_blocks | |
| 40 | + [ ArticleBlock, | |
| 41 | + BlogArchivesBlock, | |
| 42 | + CategoriesBlock, | |
| 43 | + CommunitiesBlock, | |
| 44 | + DisabledEnterpriseMessageBlock, | |
| 45 | + EnterprisesBlock, | |
| 46 | + EnvironmentStatisticsBlock, | |
| 47 | + FansBlock, | |
| 48 | + FavoriteEnterprisesBlock, | |
| 49 | + FeaturedProductsBlock, | |
| 50 | + FeedReaderBlock, | |
| 51 | + FriendsBlock, | |
| 52 | + HighlightsBlock, | |
| 53 | + LinkListBlock, | |
| 54 | + LocationBlock, | |
| 55 | + LoginBlock, | |
| 56 | + MembersBlock, | |
| 57 | + MyNetworkBlock, | |
| 58 | + PeopleBlock, | |
| 59 | + ProductsBlock, | |
| 60 | + ProfileImageBlock, | |
| 61 | + ProfileInfoBlock, | |
| 62 | + ProfileSearchBlock, | |
| 63 | + RawHTMLBlock, | |
| 64 | + RecentDocumentsBlock, | |
| 65 | + SellersSearchBlock, | |
| 66 | + SlideshowBlock, | |
| 67 | + TagsBlock | |
| 68 | + ] | |
| 69 | + end | |
| 70 | + | |
| 71 | + private | |
| 72 | + | |
| 73 | + def to_css_class_name(blocks) | |
| 74 | + blocks.map{ |block| block.to_s.underscore.tr('_', '-') } | |
| 75 | + end | |
| 76 | + | |
| 5 | 77 | end | ... | ... |
app/models/change_password.rb
| ... | ... | @@ -7,7 +7,7 @@ class ChangePassword < Task |
| 7 | 7 | when :login: |
| 8 | 8 | _('Username') |
| 9 | 9 | when :email |
| 10 | - _('e-Mail') | |
| 10 | + _('e-mail') | |
| 11 | 11 | when :password |
| 12 | 12 | _('Password') |
| 13 | 13 | when :password_confirmation |
| ... | ... | @@ -20,9 +20,7 @@ class ChangePassword < Task |
| 20 | 20 | ################################################### |
| 21 | 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 | 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 | 28 | unless data.login.blank? || data.email.blank? |
| 31 | 29 | user = User.find_by_login_and_environment_id(data.login, data.environment_id) |
| 32 | 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 | 32 | else |
| 35 | 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 | 35 | end |
| 38 | 36 | end |
| 39 | 37 | end | ... | ... |
app/models/comment.rb
| ... | ... | @@ -10,6 +10,9 @@ class Comment < ActiveRecord::Base |
| 10 | 10 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy |
| 11 | 11 | belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id' |
| 12 | 12 | |
| 13 | + named_scope :without_spam, :conditions => ['spam IS NULL OR spam = ?', false] | |
| 14 | + named_scope :spam, :conditions => ['spam = ?', true] | |
| 15 | + | |
| 13 | 16 | # unauthenticated authors: |
| 14 | 17 | validates_presence_of :name, :if => (lambda { |record| !record.email.blank? }) |
| 15 | 18 | validates_presence_of :email, :if => (lambda { |record| !record.name.blank? }) |
| ... | ... | @@ -25,6 +28,8 @@ class Comment < ActiveRecord::Base |
| 25 | 28 | |
| 26 | 29 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' |
| 27 | 30 | |
| 31 | + delegate :environment, :to => :source | |
| 32 | + | |
| 28 | 33 | def action_tracker_target |
| 29 | 34 | self.article.profile |
| 30 | 35 | end |
| ... | ... | @@ -85,7 +90,28 @@ class Comment < ActiveRecord::Base |
| 85 | 90 | end |
| 86 | 91 | end |
| 87 | 92 | |
| 88 | - after_create :notify_by_mail | |
| 93 | + after_create :schedule_notification | |
| 94 | + | |
| 95 | + def schedule_notification | |
| 96 | + Delayed::Job.enqueue CommentHandler.new(self.id, :verify_and_notify) | |
| 97 | + end | |
| 98 | + | |
| 99 | + delegate :environment, :to => :profile | |
| 100 | + delegate :profile, :to => :source | |
| 101 | + | |
| 102 | + include Noosfero::Plugin::HotSpot | |
| 103 | + | |
| 104 | + def verify_and_notify | |
| 105 | + check_for_spam | |
| 106 | + unless spam? | |
| 107 | + notify_by_mail | |
| 108 | + end | |
| 109 | + end | |
| 110 | + | |
| 111 | + def check_for_spam | |
| 112 | + plugins.dispatch(:check_comment_for_spam, self) | |
| 113 | + end | |
| 114 | + | |
| 89 | 115 | def notify_by_mail |
| 90 | 116 | if source.kind_of?(Article) && article.notify_comments? |
| 91 | 117 | if !article.profile.notification_emails.empty? |
| ... | ... | @@ -123,10 +149,14 @@ class Comment < ActiveRecord::Base |
| 123 | 149 | def self.as_thread |
| 124 | 150 | result = {} |
| 125 | 151 | root = [] |
| 126 | - all.each do |c| | |
| 152 | + order(:id).each do |c| | |
| 127 | 153 | c.replies = [] |
| 128 | 154 | result[c.id] ||= c |
| 129 | - c.reply_of_id.nil? ? root << c : result[c.reply_of_id].replies << c | |
| 155 | + if result[c.reply_of_id] | |
| 156 | + result[c.reply_of_id].replies << c | |
| 157 | + else | |
| 158 | + root << c | |
| 159 | + end | |
| 130 | 160 | end |
| 131 | 161 | root |
| 132 | 162 | end |
| ... | ... | @@ -183,4 +213,34 @@ class Comment < ActiveRecord::Base |
| 183 | 213 | @rejected = true |
| 184 | 214 | end |
| 185 | 215 | |
| 216 | + def spam? | |
| 217 | + !spam.nil? && spam | |
| 218 | + end | |
| 219 | + | |
| 220 | + def ham? | |
| 221 | + !spam.nil? && !spam | |
| 222 | + end | |
| 223 | + | |
| 224 | + def spam! | |
| 225 | + self.spam = true | |
| 226 | + self.save! | |
| 227 | + Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) | |
| 228 | + self | |
| 229 | + end | |
| 230 | + | |
| 231 | + def ham! | |
| 232 | + self.spam = false | |
| 233 | + self.save! | |
| 234 | + Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham)) | |
| 235 | + self | |
| 236 | + end | |
| 237 | + | |
| 238 | + def marked_as_spam | |
| 239 | + plugins.dispatch(:comment_marked_as_spam, self) | |
| 240 | + end | |
| 241 | + | |
| 242 | + def marked_as_ham | |
| 243 | + plugins.dispatch(:comment_marked_as_ham, self) | |
| 244 | + end | |
| 245 | + | |
| 186 | 246 | end | ... | ... |
app/models/community.rb
| ... | ... | @@ -88,7 +88,7 @@ class Community < Organization |
| 88 | 88 | end |
| 89 | 89 | |
| 90 | 90 | def activities |
| 91 | - 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.target_id = #{self.id} UNION SELECT at.id, at.updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} at INNER JOIN articles a ON at.target_id = a.id WHERE a.profile_id = #{self.id} AND at.target_type = 'Article' ORDER BY updated_at DESC") | |
| 91 | + 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.target_id = #{self.id} and action_tracker.verb != 'join_community' and action_tracker.verb != 'leave_scrap' UNION SELECT at.id, at.updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} at INNER JOIN articles a ON at.target_id = a.id WHERE a.profile_id = #{self.id} AND at.target_type = 'Article' ORDER BY updated_at DESC") | |
| 92 | 92 | end |
| 93 | 93 | |
| 94 | 94 | end | ... | ... |
app/models/enterprise.rb
| ... | ... | @@ -17,7 +17,7 @@ class Enterprise < Organization |
| 17 | 17 | after_save_reindex [:products], :with => :delayed_job |
| 18 | 18 | extra_data_for_index :product_categories |
| 19 | 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 | 21 | end |
| 22 | 22 | |
| 23 | 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 | 123 | 'xmpp_chat' => _('XMPP/Jabber based chat'), |
| 124 | 124 | 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'), |
| 125 | 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 | 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 | 144 | # Relationships and applied behaviour |
| 132 | 145 | # ################################################# |
| ... | ... | @@ -530,6 +543,31 @@ class Environment < ActiveRecord::Base |
| 530 | 543 | signup_fields |
| 531 | 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 | 572 | # Validations |
| 535 | 573 | # ################################################# |
| ... | ... | @@ -591,8 +629,8 @@ class Environment < ActiveRecord::Base |
| 591 | 629 | end |
| 592 | 630 | |
| 593 | 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 | 634 | end |
| 597 | 635 | |
| 598 | 636 | has_many :events, :through => :profiles, :source => :articles, :class_name => 'Event' | ... | ... |
app/models/external_feed.rb
| ... | ... | @@ -19,9 +19,15 @@ class ExternalFeed < ActiveRecord::Base |
| 19 | 19 | article.valid? |
| 20 | 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 | 27 | def clear |
| 23 | 28 | # do nothing |
| 24 | 29 | end |
| 30 | + | |
| 25 | 31 | def finish_fetch |
| 26 | 32 | if self.only_once && self.update_errors.zero? |
| 27 | 33 | self.enabled = false | ... | ... |
app/models/person.rb
| ... | ... | @@ -22,8 +22,6 @@ class Person < Profile |
| 22 | 22 | super |
| 23 | 23 | end |
| 24 | 24 | |
| 25 | - acts_as_having_hotspots | |
| 26 | - | |
| 27 | 25 | named_scope :members_of, lambda { |resources| |
| 28 | 26 | resources = [resources] if !resources.kind_of?(Array) |
| 29 | 27 | conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ') |
| ... | ... | @@ -32,7 +30,7 @@ class Person < Profile |
| 32 | 30 | |
| 33 | 31 | def has_permission_with_plugins?(permission, profile) |
| 34 | 32 | permissions = [has_permission_without_plugins?(permission, profile)] |
| 35 | - permissions += enabled_plugins.map do |plugin| | |
| 33 | + permissions += plugins.map do |plugin| | |
| 36 | 34 | plugin.has_permission?(self, permission, profile) |
| 37 | 35 | end |
| 38 | 36 | permissions.include?(true) |
| ... | ... | @@ -73,10 +71,7 @@ class Person < Profile |
| 73 | 71 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } |
| 74 | 72 | end |
| 75 | 73 | |
| 76 | - after_destroy :destroy_user | |
| 77 | - def destroy_user | |
| 78 | - self.user.destroy if self.user | |
| 79 | - end | |
| 74 | + belongs_to :user, :dependent => :delete | |
| 80 | 75 | |
| 81 | 76 | def can_control_scrap?(scrap) |
| 82 | 77 | begin |
| ... | ... | @@ -253,7 +248,7 @@ class Person < Profile |
| 253 | 248 | |
| 254 | 249 | def is_admin?(environment = nil) |
| 255 | 250 | environment ||= self.environment |
| 256 | - role_assignments.select { |ra| ra.resource == environment }.map{|ra|ra.role.permissions}.any? do |ps| | |
| 251 | + role_assignments.includes([:role, :resource]).select { |ra| ra.resource == environment }.map{|ra|ra.role.permissions}.any? do |ps| | |
| 257 | 252 | ps.any? do |p| |
| 258 | 253 | ActiveRecord::Base::PERMISSIONS['Environment'].keys.include?(p) |
| 259 | 254 | end |
| ... | ... | @@ -458,7 +453,7 @@ class Person < Profile |
| 458 | 453 | end |
| 459 | 454 | |
| 460 | 455 | def activities |
| 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} ORDER BY updated_at DESC") | |
| 456 | + 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 | 457 | end |
| 463 | 458 | |
| 464 | 459 | protected | ... | ... |
app/models/product.rb
| 1 | 1 | class Product < ActiveRecord::Base |
| 2 | + | |
| 2 | 3 | belongs_to :enterprise |
| 3 | 4 | has_one :region, :through => :enterprise |
| 4 | 5 | validates_presence_of :enterprise |
| ... | ... | @@ -163,7 +164,7 @@ class Product < ActiveRecord::Base |
| 163 | 164 | |
| 164 | 165 | def total_production_cost |
| 165 | 166 | return inputs_cost if price_details.empty? |
| 166 | - inputs_cost + price_details.map(&:price).inject { |sum,price| sum + price } | |
| 167 | + inputs_cost + price_details.map(&:price).inject(0){ |sum,price| sum + price } | |
| 167 | 168 | end |
| 168 | 169 | |
| 169 | 170 | def price_described? | ... | ... |
app/models/profile.rb
| ... | ... | @@ -57,10 +57,12 @@ class Profile < ActiveRecord::Base |
| 57 | 57 | 'view_private_content' => N_('View private content'), |
| 58 | 58 | 'publish_content' => N_('Publish content'), |
| 59 | 59 | 'invite_members' => N_('Invite members'), |
| 60 | + 'send_mail_to_members' => N_('Send e-Mail to members'), | |
| 60 | 61 | } |
| 61 | 62 | |
| 62 | 63 | acts_as_accessible |
| 63 | - acts_as_having_hotspots | |
| 64 | + | |
| 65 | + include Noosfero::Plugin::HotSpot | |
| 64 | 66 | |
| 65 | 67 | named_scope :memberships_of, lambda { |person| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id ] } } |
| 66 | 68 | #FIXME: these will work only if the subclass is already loaded |
| ... | ... | @@ -69,7 +71,7 @@ class Profile < ActiveRecord::Base |
| 69 | 71 | named_scope :templates, :conditions => {:is_template => true} |
| 70 | 72 | |
| 71 | 73 | def members |
| 72 | - scopes = dispatch_scopes(:organization_members, self) | |
| 74 | + scopes = plugins.dispatch_scopes(:organization_members, self) | |
| 73 | 75 | scopes << Person.members_of(self) |
| 74 | 76 | scopes.size == 1 ? scopes.first : Person.or_scope(scopes) |
| 75 | 77 | end |
| ... | ... | @@ -113,6 +115,8 @@ class Profile < ActiveRecord::Base |
| 113 | 115 | has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC", :dependent => :destroy |
| 114 | 116 | belongs_to :template, :class_name => 'Profile', :foreign_key => 'template_id' |
| 115 | 117 | |
| 118 | + has_many :comments_received, :class_name => 'Comment', :through => :articles, :source => :comments | |
| 119 | + | |
| 116 | 120 | # FIXME ugly workaround |
| 117 | 121 | def self.human_attribute_name(attrib) |
| 118 | 122 | _(self.superclass.human_attribute_name(attrib)) |
| ... | ... | @@ -255,7 +259,7 @@ class Profile < ActiveRecord::Base |
| 255 | 259 | self.categories(true) |
| 256 | 260 | self.solr_save |
| 257 | 261 | end |
| 258 | - self.categories(reload) | |
| 262 | + self.categories(reload) | |
| 259 | 263 | end |
| 260 | 264 | |
| 261 | 265 | def category_ids=(ids) |
| ... | ... | @@ -395,8 +399,8 @@ class Profile < ActiveRecord::Base |
| 395 | 399 | # |
| 396 | 400 | # +limit+ is the maximum number of documents to be returned. It defaults to |
| 397 | 401 | # 10. |
| 398 | - def recent_documents(limit = 10, options = {}) | |
| 399 | - self.articles.recent(limit, options) | |
| 402 | + def recent_documents(limit = 10, options = {}, pagination = true) | |
| 403 | + self.articles.recent(limit, options, pagination) | |
| 400 | 404 | end |
| 401 | 405 | |
| 402 | 406 | def last_articles(limit = 10, options = {}) |
| ... | ... | @@ -968,4 +972,8 @@ private :generate_url, :url_options |
| 968 | 972 | end |
| 969 | 973 | end |
| 970 | 974 | |
| 975 | + validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true | |
| 976 | + def preferred_login_redirection | |
| 977 | + redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login | |
| 978 | + end | |
| 971 | 979 | end | ... | ... |
app/models/profile_list_block.rb
| ... | ... | @@ -14,12 +14,13 @@ class ProfileListBlock < Block |
| 14 | 14 | |
| 15 | 15 | def profile_list |
| 16 | 16 | result = nil |
| 17 | + visible_profiles = profiles.visible.includes([:image,:domains,:preferred_domain,:environment]) | |
| 17 | 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 | 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 | 24 | end |
| 24 | 25 | result.slice(0..limit-1) |
| 25 | 26 | end | ... | ... |
app/models/recent_documents_block.rb
| ... | ... | @@ -16,11 +16,9 @@ class RecentDocumentsBlock < Block |
| 16 | 16 | |
| 17 | 17 | include ActionController::UrlWriter |
| 18 | 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 | 20 | block_title(title) + |
| 22 | 21 | content_tag('ul', docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n")) |
| 23 | - | |
| 24 | 22 | end |
| 25 | 23 | |
| 26 | 24 | def footer | ... | ... |
app/models/task.rb
| ... | ... | @@ -31,7 +31,7 @@ class Task < ActiveRecord::Base |
| 31 | 31 | end |
| 32 | 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 | 35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true |
| 36 | 36 | |
| 37 | 37 | validates_uniqueness_of :code, :on => :create | ... | ... |
app/models/uploaded_file.rb
| ... | ... | @@ -67,7 +67,7 @@ class UploadedFile < Article |
| 67 | 67 | 'upload-file' |
| 68 | 68 | end |
| 69 | 69 | end |
| 70 | - | |
| 70 | + | |
| 71 | 71 | def mime_type |
| 72 | 72 | content_type |
| 73 | 73 | end |
| ... | ... | @@ -129,6 +129,12 @@ class UploadedFile < Article |
| 129 | 129 | end |
| 130 | 130 | end |
| 131 | 131 | |
| 132 | + def extension | |
| 133 | + dotindex = self.filename.rindex('.') | |
| 134 | + return nil unless dotindex | |
| 135 | + self.filename[(dotindex+1)..-1].downcase | |
| 136 | + end | |
| 137 | + | |
| 132 | 138 | def allow_children? |
| 133 | 139 | false |
| 134 | 140 | end |
| ... | ... | @@ -144,4 +150,5 @@ class UploadedFile < Article |
| 144 | 150 | def uploaded_file? |
| 145 | 151 | true |
| 146 | 152 | end |
| 153 | + | |
| 147 | 154 | end | ... | ... |
app/models/user.rb
| ... | ... | @@ -30,7 +30,7 @@ class User < ActiveRecord::Base |
| 30 | 30 | |
| 31 | 31 | after_create do |user| |
| 32 | 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 | 34 | user.person.name ||= user.login |
| 35 | 35 | user.person.visible = false unless user.activated? |
| 36 | 36 | user.person.save! |
| ... | ... | @@ -73,6 +73,18 @@ class User < ActiveRecord::Base |
| 73 | 73 | :environment => user.environment.name, |
| 74 | 74 | :url => user.environment.top_url |
| 75 | 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 | 88 | end |
| 77 | 89 | |
| 78 | 90 | def signup! |
| ... | ... | @@ -88,13 +100,13 @@ class User < ActiveRecord::Base |
| 88 | 100 | attr_protected :activated_at |
| 89 | 101 | |
| 90 | 102 | # Virtual attribute for the unencrypted password |
| 91 | - attr_accessor :password | |
| 103 | + attr_accessor :password, :name | |
| 92 | 104 | |
| 93 | 105 | validates_presence_of :login, :email |
| 94 | 106 | validates_format_of :login, :with => Profile::IDENTIFIER_FORMAT, :if => (lambda {|user| !user.login.blank?}) |
| 95 | 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 | 110 | validates_confirmation_of :password, :if => :password_required? |
| 99 | 111 | validates_length_of :login, :within => 2..40, :if => (lambda {|user| !user.login.blank?}) |
| 100 | 112 | validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?}) |
| ... | ... | @@ -117,7 +129,17 @@ class User < ActiveRecord::Base |
| 117 | 129 | self.activated_at = Time.now.utc |
| 118 | 130 | self.activation_code = nil |
| 119 | 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 | 143 | end |
| 122 | 144 | |
| 123 | 145 | def activated? |
| ... | ... | @@ -228,7 +250,12 @@ class User < ActiveRecord::Base |
| 228 | 250 | end |
| 229 | 251 | |
| 230 | 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 | 259 | end |
| 233 | 260 | |
| 234 | 261 | def enable_email! |
| ... | ... | @@ -274,6 +301,11 @@ class User < ActiveRecord::Base |
| 274 | 301 | 15 # in minutes |
| 275 | 302 | end |
| 276 | 303 | |
| 304 | + | |
| 305 | + def not_require_password! | |
| 306 | + @is_password_required = false | |
| 307 | + end | |
| 308 | + | |
| 277 | 309 | protected |
| 278 | 310 | # before filter |
| 279 | 311 | def encrypt_password |
| ... | ... | @@ -282,9 +314,13 @@ class User < ActiveRecord::Base |
| 282 | 314 | self.password_type ||= User.system_encryption_method.to_s |
| 283 | 315 | self.crypted_password = encrypt(password) |
| 284 | 316 | end |
| 285 | - | |
| 317 | + | |
| 286 | 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 | 324 | end |
| 289 | 325 | |
| 290 | 326 | def make_activation_code |
| ... | ... | @@ -292,6 +328,7 @@ class User < ActiveRecord::Base |
| 292 | 328 | end |
| 293 | 329 | |
| 294 | 330 | def deliver_activation_code |
| 331 | + return if person.is_template? | |
| 295 | 332 | User::Mailer.deliver_activation_code(self) unless self.activation_code.blank? |
| 296 | 333 | end |
| 297 | 334 | ... | ... |
app/views/account/forgot_password.rhtml
| 1 | 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 | 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 | 13 | |
| 14 | 14 | <%= f.password_field :password %> |
| 15 | 15 | |
| 16 | + <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }.join("") %> | |
| 17 | + | |
| 16 | 18 | <% button_bar do %> |
| 17 | 19 | <%= submit_button( 'login', _('Log in') )%> |
| 18 | 20 | <% if is_thickbox %> |
| ... | ... | @@ -23,8 +25,13 @@ |
| 23 | 25 | <% end %> |
| 24 | 26 | |
| 25 | 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 | 35 | <% end %> |
| 29 | 36 | |
| 30 | 37 | </div><!-- end class="login-box" --> | ... | ... |
app/views/account/login_block.rhtml
| ... | ... | @@ -9,25 +9,30 @@ |
| 9 | 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 | 20 | <% button_bar do %> |
| 20 | 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 | 27 | <% end %> |
| 25 | 28 | |
| 26 | 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 | 37 | </div> |
| 33 | 38 | ... | ... |
| ... | ... | @@ -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/index.rhtml
| 1 | 1 | <h1><%= _('Administrator Panel') %></h1> |
| 2 | 2 | |
| 3 | -<p><%= _('You, as an environment administrator, has the following options:')%></p> | |
| 3 | +<h2><%= _('System settings') %></h2> | |
| 4 | 4 | |
| 5 | 5 | <table> |
| 6 | - <tr><td><%= link_to _('Edit environment settings'), :action => 'site_info' %></td></tr> | |
| 7 | - <tr><td><%= link_to __('Edit message for disabled enterprises'), :action => 'message_for_disabled_enterprise' %></td></tr> | |
| 8 | - <tr><td><%= link_to _('Enable/disable features'), :controller => 'features' %></td></tr> | |
| 9 | - <tr><td><%= link_to _('Enable/disable plugins'), :controller => 'plugins' %></td></tr> | |
| 10 | - <tr><td><%= link_to _('Edit sideboxes'), :controller => 'environment_design'%></td></tr> | |
| 11 | - <tr><td><%= link_to _('Manage Categories'), :controller => 'categories'%></td></tr> | |
| 12 | - <tr><td><%= link_to _('Manage User roles'), :controller => 'role' %></td></tr> | |
| 13 | - <tr><td><%= link_to _('Manage users'), :controller => 'users' %></td></tr> | |
| 14 | - <tr><td><%= link_to _('Manage Validators by region'), :controller => 'region_validators' %></td></tr> | |
| 15 | - <tr><td><%= link_to _('Edit Templates'), :controller => 'templates' %></td></tr> | |
| 16 | - <tr><td><%= link_to _('Manage Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> | |
| 17 | - <tr><td><%= link_to _('Set Portal'), :action => 'set_portal_community' %></td></tr> | |
| 18 | - <tr><td><%= link_to _('Manage Licenses'), :controller =>'licenses' %></td></tr> | |
| 19 | - <% @plugins.dispatch(:admin_panel_links).each do |link| %> | |
| 6 | + <tr><td><%= link_to _('Environment settings'), :action => 'site_info' %></td></tr> | |
| 7 | + <tr><td><%= link_to _('Features'), :controller => 'features' %></td></tr> | |
| 8 | + <tr><td><%= link_to _('Plugins'), :controller => 'plugins' %></td></tr> | |
| 9 | + <tr><td><%= link_to _('Sideboxes'), :controller => 'environment_design'%></td></tr> | |
| 10 | + <tr><td><%= link_to _('Homepage'), :action => 'set_portal_community' %></td></tr> | |
| 11 | + <tr><td><%= link_to _('Licenses'), :controller =>'licenses' %></td></tr> | |
| 12 | +</table> | |
| 13 | + | |
| 14 | +<h2><%= _('Profiles') %></h2> | |
| 15 | + | |
| 16 | +<table> | |
| 17 | + <tr><td><%= link_to _('User roles'), :controller => 'role' %></td></tr> | |
| 18 | + <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> | |
| 19 | + <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> | |
| 20 | + <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> | |
| 21 | +</table> | |
| 22 | + | |
| 23 | + | |
| 24 | +<% | |
| 25 | + plugin_links = @plugins.dispatch(:admin_panel_links) | |
| 26 | +%> | |
| 27 | +<% unless plugin_links.empty? %> | |
| 28 | + <h2><%= _('Plugins') %></h2> | |
| 29 | + <table> | |
| 30 | + <% plugin_links.each do |link| %> | |
| 20 | 31 | <tr><td><%= link_to link[:title], link[:url] %></td></tr> |
| 21 | 32 | <% end %> |
| 33 | + </table> | |
| 34 | +<% end %> | |
| 35 | + | |
| 36 | +<h2><%= _('Enterprise-related settings') %></h2> | |
| 37 | + | |
| 38 | +<table> | |
| 39 | + <tr><td><%= link_to __('Message for disabled enterprises'), :action => 'message_for_disabled_enterprise' %></td></tr> | |
| 40 | + <tr><td><%= link_to _('Validators by region'), :controller => 'region_validators' %></td></tr> | |
| 41 | + <tr><td><%= link_to _('Categories'), :controller => 'categories'%></td></tr> | |
| 22 | 42 | </table> | ... | ... |
app/views/admin_panel/site_info.rhtml
| ... | ... | @@ -10,6 +10,8 @@ |
| 10 | 10 | :content => (render :partial => 'site_info', :locals => {:f => f})} %> |
| 11 | 11 | <% tabs << {:title => _('Terms of use'), :id => 'terms-of-use', |
| 12 | 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 | 15 | <%= render_tabs(tabs) %> |
| 14 | 16 | <% button_bar do %> |
| 15 | 17 | <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> | ... | ... |
app/views/blocks/profile_info_actions/community.rhtml
| ... | ... | @@ -32,7 +32,7 @@ |
| 32 | 32 | { :profile => profile.identifier, |
| 33 | 33 | :controller => 'contact', |
| 34 | 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 | 36 | </li> |
| 37 | 37 | <% end %> |
| 38 | 38 | ... | ... |
| ... | ... | @@ -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 | 1 | <strong><%= _('Highlights') %></strong> |
| 2 | -<div id='edit-highlights-block'> | |
| 2 | +<div id='edit-highlights-block' style='width:450px'> | |
| 3 | 3 | <table id='highlights' class='noborder'> |
| 4 | 4 | <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr> |
| 5 | 5 | <% for image in @block.images do %> | ... | ... |
app/views/box_organizer/_link_list_block.rhtml
| 1 | 1 | <strong><%= _('Links') %></strong> |
| 2 | -<div id='edit-link-list-block'> | |
| 2 | +<div id='edit-link-list-block' style='width:450px'> | |
| 3 | 3 | <table id='links' class='noborder'> |
| 4 | 4 | <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th></tr> |
| 5 | 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 | 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 | 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']] + Noosfero.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 | 1 | <h1><%= _('Editing sideboxes')%></h1> |
| 2 | 2 | |
| 3 | 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 | 5 | <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> |
| 6 | 6 | <% end %> | ... | ... |
app/views/cms/view.rhtml
| ... | ... | @@ -49,13 +49,13 @@ |
| 49 | 49 | <%= article.class.short_description %> |
| 50 | 50 | </td> |
| 51 | 51 | <td class="article-controls"> |
| 52 | - <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => article.id %> | |
| 52 | + <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> | |
| 53 | 53 | <%= button_without_text :eyes, _('Public view'), article.view_url %> |
| 54 | - <%= display_spread_button(profile, article) unless article.folder? %> | |
| 55 | - <% if !environment.enabled?('cant_change_homepage') %> | |
| 56 | - <%= button_without_text :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | |
| 54 | + <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> | |
| 55 | + <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> | |
| 56 | + <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | |
| 57 | 57 | <% end %> |
| 58 | - <%= display_delete_button(article) %> | |
| 58 | + <%= display_delete_button(article) if !remove_content_button(:delete) %> | |
| 59 | 59 | </td> |
| 60 | 60 | </tr> |
| 61 | 61 | <% end %> | ... | ... |
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 | 11 | <% labelled_form_for :contact, @contact do |f| %> |
| 7 | 12 | <%= hidden_field_tag(:confirm, 'false') %> | ... | ... |
app/views/content_viewer/_article_toolbar.rhtml
| 1 | 1 | <div<%= user && " class='logged-in'" %>> |
| 2 | 2 | <div id="article-actions"> |
| 3 | 3 | |
| 4 | - <% if @page.allow_edit?(user) %> | |
| 5 | - <%= link_to content_tag( 'span', label_for_edit_article(@page) ), | |
| 6 | - profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }), | |
| 7 | - :class => 'button with-text icon-edit' %> | |
| 4 | + | |
| 5 | + <% if @page.allow_edit?(user) && !remove_content_button(:edit) %> | |
| 6 | + <% content = content_tag('span', label_for_edit_article(@page)) %> | |
| 7 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }) %> | |
| 8 | + <%= expirable_button @page, :edit, content, url %> | |
| 8 | 9 | <% end %> |
| 9 | 10 | |
| 10 | - <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) %> | |
| 11 | - <%= link_to content_tag( 'span', _('Delete') ), | |
| 12 | - profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page}), | |
| 13 | - :method => :post, | |
| 14 | - :class => 'button with-text icon-delete', | |
| 15 | - :confirm => delete_article_message(@page) %> | |
| 11 | + <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) && !remove_content_button(:delete)%> | |
| 12 | + <% content = content_tag( 'span', _('Delete') ) %> | |
| 13 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page}) %> | |
| 14 | + <% options = {:method => :post, :confirm => delete_article_message(@page)} %> | |
| 15 | + <%= expirable_button @page, :delete, content, url, options %> | |
| 16 | 16 | <% end %> |
| 17 | 17 | |
| 18 | - <% if !@page.folder? && @page.allow_spread?(user) %> | |
| 18 | + <% if !@page.folder? && @page.allow_spread?(user) && !remove_content_button(:spread) %> | |
| 19 | + <% content = content_tag( 'span', _('Spread this') ) %> | |
| 20 | + <% url = nil %> | |
| 19 | 21 | <% if profile.kind_of?(Person) %> |
| 20 | - <%= link_to content_tag( 'span', _('Spread this') ), | |
| 21 | - profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page }), | |
| 22 | - :class => 'button with-text icon-spread' %> | |
| 22 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page }) %> | |
| 23 | 23 | <% elsif profile.kind_of?(Community) && environment.portal_community %> |
| 24 | - <%= link_to content_tag( 'span', _('Spread this') ), | |
| 25 | - profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page }), | |
| 26 | - :class => 'button with-text icon-spread' %> | |
| 24 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page }) %> | |
| 27 | 25 | <% end %> |
| 26 | + <%= expirable_button @page, :spread, content, url if url %> | |
| 28 | 27 | <% end %> |
| 29 | 28 | |
| 30 | 29 | <% if !@page.gallery? && @page.allow_create?(user) %> |
| 31 | - <%= link_to _('Add translation'), | |
| 32 | - profile.admin_url.merge(:controller => 'cms', :action => 'new', | |
| 33 | - :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)), | |
| 34 | - :type => @page.type, :article => { :translation_of_id => @page.native_translation.id }), | |
| 35 | - :class => 'button with-text icon-locale' if @page.translatable? && !@page.native_translation.language.blank? %> | |
| 30 | + <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %> | |
| 31 | + <% content = _('Add translation') %> | |
| 32 | + <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %> | |
| 33 | + <% url = profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => parent_id, :type => @page.type, :article => { :translation_of_id => @page.native_translation.id })%> | |
| 34 | + <%= expirable_button @page, :locale, content, url %> | |
| 35 | + <% end %> | |
| 36 | + | |
| 36 | 37 | <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %> |
| 37 | 38 | <% end %> |
| 38 | 39 | |
| ... | ... | @@ -40,8 +41,11 @@ |
| 40 | 41 | <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) %> |
| 41 | 42 | <% end %> |
| 42 | 43 | |
| 43 | - <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) %> | |
| 44 | - <%= link_to content_tag( 'span', _('Suggest an article') ), profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}), :id => 'suggest-article-link', :class => 'button with-text icon-new' %> | |
| 44 | + <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %> | |
| 45 | + <% content = content_tag( 'span', _('Suggest an article') ) %> | |
| 46 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %> | |
| 47 | + <% options = {:id => 'suggest-article-link'} %> | |
| 48 | + <%= expirable_button @page, :suggest, content, url, options %> | |
| 45 | 49 | <% end %> |
| 46 | 50 | |
| 47 | 51 | <%= report_abuse(profile, :link, @page) %> | ... | ... |
app/views/content_viewer/_comment.rhtml
| 1 | 1 | <li id="<%= comment.anchor %>" class="article-comment"> |
| 2 | 2 | <div class="article-comment-inner"> |
| 3 | 3 | |
| 4 | - <div class="comment-content comment-logged-<%= comment.author ? 'in' : 'out' %> <%= 'comment-from-owner' if ( comment.author && (@page.profile.name == comment.author.name) ) %>"> | |
| 4 | + <div class="comment-content comment-logged-<%= comment.author ? 'in' : 'out' %> <%= 'comment-from-owner' if ( comment.author && (profile == comment.author) ) %>"> | |
| 5 | 5 | |
| 6 | 6 | <% if comment.author %> |
| 7 | 7 | <%= link_to image_tag(profile_icon(comment.author, :minor)) + |
| ... | ... | @@ -29,17 +29,12 @@ |
| 29 | 29 | <% end %> |
| 30 | 30 | |
| 31 | 31 | <% comment_balloon do %> |
| 32 | - <% if logged_in? && (user == @page.profile || user == comment.author || user.has_permission?(:moderate_comments, @page.profile)) %> | |
| 33 | - <% button_bar(:style => 'float: right; margin-top: 0px;') do %> | |
| 34 | - <%= icon_button(:delete, _('Remove this comment and all its replies'), { :profile => params[:profile], :remove_comment => comment.id, :view => params[:view] }, :method => :post, :confirm => _('Are you sure you want to remove this comment and all its replies?')) %> | |
| 35 | - <% end %> | |
| 36 | - <% end %> | |
| 37 | 32 | |
| 38 | 33 | <div class="comment-details"> |
| 39 | 34 | <div class="comment-created-at"> |
| 40 | 35 | <%= show_time(comment.created_at) %> |
| 41 | 36 | </div> |
| 42 | - <h4><%= comment.title %></h4> | |
| 37 | + <h4><%= comment.title.blank? && ' ' || comment.title %></h4> | |
| 43 | 38 | <div class="comment-text"> |
| 44 | 39 | <p/> |
| 45 | 40 | <%= txt2html comment.body %> |
| ... | ... | @@ -57,18 +52,42 @@ |
| 57 | 52 | </script> |
| 58 | 53 | <% end %> |
| 59 | 54 | <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> |
| 60 | - <%= link_to_function _('Reply'), | |
| 61 | - "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id, | |
| 55 | + | |
| 56 | + <% if comment.spam? %> | |
| 57 | + | |
| 58 | + <%= link_to_function(_('Mark as NOT SPAM'), 'remove_comment(this, %s); return false;' % url_for(:mark_comment_as_ham => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide') %> | |
| 59 | + <% else %> | |
| 60 | + <% if (logged_in? && (user == profile || user.has_permission?(:moderate_comments, profile))) %> | |
| 61 | + | |
| 62 | + <%= link_to_function(_('Mark as SPAM'), 'remove_comment(this, %s, %s); return false;' % [url_for(:mark_comment_as_spam => comment.id).to_json, _('Are you sure you want to mark this comment as SPAM?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide') %> | |
| 63 | + <% end %> | |
| 64 | + <% end %> | |
| 65 | + | |
| 66 | + <% if comment.author && comment.author == user %> | |
| 67 | + | |
| 68 | + <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %> | |
| 69 | + <% end %> | |
| 70 | + | |
| 71 | + <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %> | |
| 72 | + | |
| 73 | + <%= link_to_function(_('Remove'), 'remove_comment(this, %s, %s); return false ;' % [url_for(:profile => params[:profile], :remove_comment => comment.id, :view => params[:view]).to_json, _('Are you sure you want to remove this comment and all its replies?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide remove-children') %> | |
| 74 | + <% end %> | |
| 75 | + | |
| 76 | + <% unless comment.spam? %> | |
| 77 | + | |
| 78 | + <%= link_to_function _('Reply'), | |
| 79 | + "var f = add_comment_reply_form(this, %s); f.find('comment_title, textarea').val(''); return false" % comment.id, | |
| 62 | 80 | :class => 'comment-footer comment-footer-link comment-footer-hide', |
| 63 | 81 | :id => 'comment-reply-to-' + comment.id.to_s |
| 64 | - %> | |
| 82 | + %> | |
| 83 | + <% end %> | |
| 65 | 84 | </div> |
| 66 | 85 | |
| 67 | 86 | <% end %> |
| 68 | 87 | |
| 69 | 88 | </div> |
| 70 | 89 | |
| 71 | - <% unless comment.replies.blank? %> | |
| 90 | + <% unless comment.replies.blank? || comment.spam? %> | |
| 72 | 91 | <ul class="comment-replies"> |
| 73 | 92 | <% comment.replies.each do |reply| %> |
| 74 | 93 | <%= render :partial => 'comment', :locals => { :comment => reply } %> | ... | ... |
app/views/content_viewer/_comment_form.rhtml
| ... | ... | @@ -32,15 +32,17 @@ function submit_comment_form(button) { |
| 32 | 32 | |
| 33 | 33 | <div class="post_comment_box <%= @form_div %>"> |
| 34 | 34 | |
| 35 | -<h4 onclick="var d = jQuery(this).parent('.post_comment_box'); | |
| 36 | - if (d.hasClass('closed')) { | |
| 37 | - d.removeClass('closed'); | |
| 38 | - d.addClass('opened'); | |
| 39 | - d.find('input[name=comment[title]], textarea').val(''); | |
| 40 | - d.find('.comment_form input[name=comment[<%= focus_on %>]]').focus(); | |
| 41 | - }"> | |
| 42 | - <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %> | |
| 43 | -</h4> | |
| 35 | +<% if display_link %> | |
| 36 | + <h4 onclick="var d = jQuery(this).parent('.post_comment_box'); | |
| 37 | + if (d.hasClass('closed')) { | |
| 38 | + d.removeClass('closed'); | |
| 39 | + d.addClass('opened'); | |
| 40 | + d.find('input[name=comment[title]], textarea').val(''); | |
| 41 | + d.find('.comment_form input[name=comment[<%= focus_on %>]]').focus(); | |
| 42 | + }"> | |
| 43 | + <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %> | |
| 44 | + </h4> | |
| 45 | +<% end %> | |
| 44 | 46 | |
| 45 | 47 | <% unless pass_without_comment_captcha? %> |
| 46 | 48 | <div id="recaptcha-container" style="display: none"> |
| ... | ... | @@ -59,7 +61,7 @@ function submit_comment_form(button) { |
| 59 | 61 | </script> |
| 60 | 62 | <% end %> |
| 61 | 63 | |
| 62 | -<% form_tag( url_for(@page.view_url.merge({:only_path => true})), { :class => 'comment_form' } ) do %> | |
| 64 | +<% form_tag( url, { :class => 'comment_form' } ) do %> | |
| 63 | 65 | <%= hidden_field_tag(:confirm, 'false') %> |
| 64 | 66 | |
| 65 | 67 | <%= required_fields_message %> |
| ... | ... | @@ -84,7 +86,11 @@ function submit_comment_form(button) { |
| 84 | 86 | |
| 85 | 87 | <% button_bar do %> |
| 86 | 88 | <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %> |
| 87 | - <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %> | |
| 89 | + <% if cancel_triggers_hide %> | |
| 90 | + <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %> | |
| 91 | + <% else %> | |
| 92 | + <%= button('cancel', _('Cancel'), {:action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path})%> | |
| 93 | + <% end %> | |
| 88 | 94 | <% end %> |
| 89 | 95 | <% end %> |
| 90 | 96 | ... | ... |
app/views/content_viewer/view_page.rhtml
| ... | ... | @@ -98,13 +98,7 @@ |
| 98 | 98 | </ul> |
| 99 | 99 | |
| 100 | 100 | <% if @page.accept_comments? %> |
| 101 | - <div id="page-comment-form"><%= render :partial => 'comment_form' %></div> | |
| 102 | - <script type="text/javascript"> | |
| 103 | - jQuery( function() { | |
| 104 | - jQuery('.article-comment').live('mouseover', function() { jQuery(this).find('.icon-delete:first').show(); }); | |
| 105 | - jQuery('.article-comment').live('mouseout', function() { jQuery(this).find('.icon-delete').hide(); }); | |
| 106 | - }); | |
| 107 | - </script> | |
| 101 | + <div id="page-comment-form"><%= render :partial => 'comment_form', :locals => {:url => url_for(@page.view_url.merge({:only_path => true})), :display_link => true, :cancel_triggers_hide => true}%></div> | |
| 108 | 102 | <% end %> |
| 109 | 103 | </div><!-- end class="comments" --> |
| 110 | 104 | ... | ... |
app/views/features/index.rhtml
| ... | ... | @@ -26,17 +26,12 @@ Check all the features you want to enable for your environment, uncheck all the |
| 26 | 26 | |
| 27 | 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 | 36 | <div> |
| 42 | 37 | <% button_bar do %> | ... | ... |
app/views/friends/index.rhtml
| ... | ... | @@ -31,7 +31,7 @@ |
| 31 | 31 | :class => 'button icon-remove', |
| 32 | 32 | :title => _('remove') %> |
| 33 | 33 | <%= link_to content_tag('span',_('contact')), |
| 34 | - friend.url.merge(:controller => 'contact', :action => 'new'), | |
| 34 | + friend.url.merge(:controller => 'contact', :action => 'new', :profile => friend.identifier), | |
| 35 | 35 | :class => 'button icon-menu-mail', |
| 36 | 36 | :title => _('contact') %> |
| 37 | 37 | </div><!-- end class="controll" --> | ... | ... |
app/views/layouts/_javascript.rhtml
| ... | ... | @@ -2,7 +2,8 @@ |
| 2 | 2 | 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox', |
| 3 | 3 | 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate', |
| 4 | 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 | 8 | <% language = FastGettext.locale %> |
| 8 | 9 | <% %w{messages methods}.each do |type| %> | ... | ... |
app/views/layouts/application-ng.rhtml
| ... | ... | @@ -56,10 +56,18 @@ |
| 56 | 56 | <%= usermenu_logged_in %> |
| 57 | 57 | </span> |
| 58 | 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 | 63 | <div id='inlineLoginBox' style='display: none;'> |
| 61 | 64 | <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> |
| 62 | 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 | 71 | </span> |
| 64 | 72 | <form action="/search" class="search_form" method="get" class="clean"> |
| 65 | 73 | <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> | ... | ... |
app/views/plugins/index.rhtml
| 1 | 1 | <h1><%= _('Manage plugins') %></h1> |
| 2 | -<%= _('Here you can enable or disable any plugin of your environment.')%> | |
| 2 | + | |
| 3 | +<p> | |
| 4 | +<%= _('Select which plugins you want to enable in your environment') %> | |
| 5 | +</p> | |
| 3 | 6 | |
| 4 | 7 | <% labelled_form_for(:environment, @environment, :url => {:action => 'update'}) do |f| %> |
| 5 | 8 | |
| 6 | -<table> | |
| 7 | - <tr> | |
| 8 | - <th><%= _('Plugin') %></th> | |
| 9 | - <th><%= _('Description') %></th> | |
| 10 | - <th><%= _('Enabled?') %></th> | |
| 11 | - </tr> | |
| 12 | - <%= hidden_field_tag('environment[enabled_plugins][]', '') %> | |
| 13 | - <% @active_plugins.each do |plugin| %> | |
| 14 | - <tr> | |
| 15 | - <td><%= plugin.has_admin_url? ? link_to(plugin.plugin_name, plugin.admin_url) : plugin.plugin_name %></td> | |
| 16 | - <td><%= plugin.plugin_description %></td> | |
| 17 | - <td><%= check_box_tag "environment[enabled_plugins][]", plugin, @environment.enabled_plugins.include?(plugin.to_s), :id => plugin.plugin_name %></td> | |
| 18 | - </tr> | |
| 19 | - <% end %> | |
| 20 | -</table> | |
| 9 | + <table> | |
| 10 | + <% @active_plugins.sort_by(&:plugin_name).each do |plugin| %> | |
| 11 | + <tr> | |
| 12 | + <td style='vertical-align: top'><%= check_box_tag "environment[enabled_plugins][]", plugin, @environment.enabled_plugins.include?(plugin.to_s), :id => plugin.plugin_name %></td> | |
| 13 | + <td> | |
| 14 | + <%= hidden_field_tag('environment[enabled_plugins][]', '') %> | |
| 15 | + <strong><%= plugin.plugin_name %></strong> | |
| 16 | + <br/> | |
| 17 | + <%= plugin.plugin_description %> | |
| 18 | + <% if plugin.has_admin_url? %> | |
| 19 | + <br/> | |
| 20 | + <br/> | |
| 21 | + <%= link_to(_('Configuration'), plugin.admin_url) %> | |
| 22 | + <% end %> | |
| 23 | + </td> | |
| 24 | + </tr> | |
| 25 | + <% end %> | |
| 26 | + </table> | |
| 21 | 27 | |
| 22 | 28 | <div> |
| 23 | 29 | <% button_bar do %> | ... | ... |
app/views/profile/_comment.rhtml
| ... | ... | @@ -5,19 +5,35 @@ |
| 5 | 5 | <li class="article-comment" style='border-bottom:none;'> |
| 6 | 6 | <div class="article-comment-inner"> |
| 7 | 7 | |
| 8 | - <div class="comment-content comment-logged-in"> | |
| 8 | + <div class="comment-content comment-logged-<%= comment.author ? 'in' : 'out' %>"> | |
| 9 | 9 | |
| 10 | 10 | <% if comment.author %> |
| 11 | 11 | <%= link_to image_tag(profile_icon(comment.author, :minor)), |
| 12 | - Person.find(comment.author_id).url, | |
| 12 | + comment.author_url, | |
| 13 | 13 | :class => 'comment-picture', |
| 14 | 14 | :title => comment.author_name |
| 15 | 15 | %> |
| 16 | + <% else %> | |
| 17 | + <% url_image, status_class = comment.author_id ? | |
| 18 | + [comment.removed_user_image, 'icon-user-removed'] : | |
| 19 | + [str_gravatar_url_for( comment.email ), 'icon-user-unknown'] %> | |
| 20 | + | |
| 21 | + <%= link_to( | |
| 22 | + image_tag(url_image, :onerror=>'gravatarCommentFailback(this)', | |
| 23 | + 'data-gravatar'=>str_gravatar_url_for(comment.email)) + | |
| 24 | + content_tag('span', comment.author_name, :class => 'comment-info') + | |
| 25 | + content_tag('span', comment.message, | |
| 26 | + :class => 'comment-user-status comment-user-status-wall ' + status_class), | |
| 27 | + gravatar_profile_url(comment.email), | |
| 28 | + :target => '_blank', | |
| 29 | + :class => 'comment-picture', | |
| 30 | + :title => '%s %s' % [comment.author_name, comment.message] | |
| 31 | + )%> | |
| 16 | 32 | <% end %> |
| 17 | 33 | |
| 18 | 34 | <div class="comment-details"> |
| 19 | 35 | <div class="comment-text"> |
| 20 | - <%= link_to(comment.author_name, comment.author.url) %> | |
| 36 | + <%= comment.author.present? ? link_to(comment.author_name, comment.author.url) : content_tag('strong', comment.author_name) %> | |
| 21 | 37 | <% unless comment.title.blank? %> |
| 22 | 38 | <span class="comment-title"><%= comment.title %></span><br/> |
| 23 | 39 | <% end %> |
| ... | ... | @@ -30,7 +46,7 @@ |
| 30 | 46 | |
| 31 | 47 | <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %> |
| 32 | 48 | <% button_bar(:style => 'float: right; margin-top: 0px;') do %> |
| 33 | - <%= icon_button(:delete, _('Remove'), { :action => :remove_comment, :comment_id => comment.id }, :method => :get, :confirm => _('Are you sure you want to remove this comment and all its replies?')) %> | |
| 49 | + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.article-comment'", url_for(:profile => params[:profile], :action => :remove_comment, :comment_id => comment.id, :view => params[:view]).to_json, _('Are you sure you want to remove this comment and all its replies?').to_json], :class => 'button icon-button icon-delete') %> | |
| 34 | 50 | <% end %> |
| 35 | 51 | <% end %> |
| 36 | 52 | <br style="clear: both;" /> |
| ... | ... | @@ -46,6 +62,10 @@ |
| 46 | 62 | </script> |
| 47 | 63 | <% end %> |
| 48 | 64 | <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> |
| 65 | + <% if comment.author && comment.author == user %> | |
| 66 | + <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %> | |
| 67 | + <%= content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') %> | |
| 68 | + <% end %> | |
| 49 | 69 | <%= link_to_function _('Reply'), |
| 50 | 70 | "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id, |
| 51 | 71 | :class => 'comment-footer comment-footer-link comment-footer-hide', | ... | ... |
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 | 1 | <% unless @action %> |
| 12 | 2 | <% cache_timeout(profile.cache_key + '-profile-general-info', 4.hours) do %> |
| 13 | 3 | <tr> | ... | ... |
app/views/profile/_create_article.rhtml
| ... | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> |
| 16 | 16 | <div class='profile-wall-actions'> |
| 17 | 17 | <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> |
| 18 | - <%= link_to_remote(content_tag(:span, _('Remove')), :url =>{:action => 'remove_activity', :activity_id => activity.id, :only_hide => true}, :confirm => _('Are you sure?'), :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %> | |
| 18 | + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.profile-activity-item'", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :only_hide => true, :view => params[:view]).to_json, _('Are you sure you want to remove this activity and all its replies?').to_json]) if logged_in? && current_person == @profile %> | |
| 19 | 19 | </div> |
| 20 | 20 | </div> |
| 21 | 21 | ... | ... |
app/views/profile/_default_activity.rhtml
| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> |
| 7 | 7 | <div class='profile-wall-actions'> |
| 8 | 8 | <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> |
| 9 | - <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %> | |
| 9 | + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.profile-activity-item'", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]).to_json, _('Are you sure you want to remove this activity and all its replies?').to_json]) if logged_in? && current_person == @profile %> | |
| 10 | 10 | </div> |
| 11 | 11 | </div> |
| 12 | 12 | ... | ... |
app/views/profile/_leave_scrap.rhtml
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> |
| 6 | 6 | <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> |
| 7 | 7 | <div class='profile-wall-actions'> |
| 8 | - <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %> | |
| 8 | + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.profile-activity-item'", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]).to_json, _('Are you sure you want to remove this activity and all its replies?').to_json]) if logged_in? && current_person == @profile %> | |
| 9 | 9 | </div> |
| 10 | 10 | </div> |
| 11 | 11 | ... | ... |
app/views/profile/_person_profile.rhtml
| ... | ... | @@ -37,7 +37,7 @@ |
| 37 | 37 | <tr> |
| 38 | 38 | <th colspan='2'><%= __('Enterprises') %></th> |
| 39 | 39 | </tr> |
| 40 | - <% profile.enterprises.each do |item| %> | |
| 40 | + <% profile.enterprises.includes(:environment,:domains, :preferred_domain).each do |item| %> | |
| 41 | 41 | <tr> |
| 42 | 42 | <td></td> |
| 43 | 43 | <td><%= button 'menu-enterprise', item.name, item.url %></td> | ... | ... |
app/views/profile/_profile_scrap.rhtml
| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | <%= link_to_function s_('profile|Comment'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);$('reply_content_#{scrap.id}').value='';$('reply_content_#{scrap.id}').focus();return false", :class => "profile-send-reply" %> |
| 13 | 13 | </span> |
| 14 | 14 | <% end %> |
| 15 | - <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_scrap', :scrap_id => scrap.id}, :update => "profile-activity-item-#{scrap.id}") if logged_in? && user.can_control_scrap?(scrap) %> | |
| 15 | + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.profile-activity-item'", url_for(:profile => params[:profile], :action => :remove_scrap, :scrap_id => scrap.id, :view => params[:view]).to_json, _('Are you sure you want to remove this scrap and all its replies?').to_json]) if logged_in? && user.can_control_scrap?(scrap) %> | |
| 16 | 16 | </div> |
| 17 | 17 | </div> |
| 18 | 18 | ... | ... |
app/views/profile/_upload_image.rhtml
| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> |
| 7 | 7 | <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> |
| 8 | 8 | <div class='profile-wall-actions'> |
| 9 | - <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %> | |
| 9 | + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.profile-activity-item'", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]).to_json, _('Are you sure you want to remove this activity and all its replies?').to_json]) if logged_in? && current_person == @profile %> | |
| 10 | 10 | </div> |
| 11 | 11 | </div> |
| 12 | 12 | </div> | ... | ... |
app/views/profile/members.rhtml
| ... | ... | @@ -16,8 +16,13 @@ |
| 16 | 16 | |
| 17 | 17 | <% button_bar do %> |
| 18 | 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 | 26 | <% end %> |
| 22 | 27 | <% end %> |
| 23 | 28 | ... | ... |
| ... | ... | @@ -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/edit.rhtml
| ... | ... | @@ -24,61 +24,24 @@ |
| 24 | 24 | <h2><%= _('Privacy options') %></h2> |
| 25 | 25 | |
| 26 | 26 | <% 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> | |
| 27 | + <div> | |
| 28 | + <%= labelled_radio_button _('Public — show my contents to all internet users'), 'profile_data[public_profile]', true, @profile.public_profile? %> | |
| 29 | + </div> | |
| 30 | + <div> | |
| 31 | + <%= labelled_radio_button _('Private — show my contents only to friends'), 'profile_data[public_profile]', false, !@profile.public_profile? %> | |
| 32 | + </div> | |
| 54 | 33 | <% 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> | |
| 34 | + <div> | |
| 35 | + <%= labelled_radio_button _('Public — show content of this group to all internet users'), 'profile_data[public_profile]', true, @profile.public_profile? %> | |
| 36 | + </div> | |
| 37 | + <div> | |
| 38 | + <%= labelled_radio_button _('Private — show content of this group only to members'), 'profile_data[public_profile]', false, !@profile.public_profile? %> | |
| 39 | + </div> | |
| 40 | + <% end %> | |
| 41 | + | |
| 42 | + <% if environment.enabled?('allow_change_of_redirection_after_login') %> | |
| 43 | + <h2><%= _('Page to redirect after login') %></h2> | |
| 44 | + <%= select 'profile_data', 'redirection_after_login', Environment.login_redirection_options.map{|key,value|[value,key]}, { :selected => @profile.preferred_login_redirection} %> | |
| 82 | 45 | <% end %> |
| 83 | 46 | |
| 84 | 47 | <h2><%= _('Translations') %></h2> | ... | ... |
app/views/profile_editor/index.rhtml
| ... | ... | @@ -66,6 +66,8 @@ |
| 66 | 66 | |
| 67 | 67 | <%= control_panel_button(_('Manage my groups'), 'groups', :controller => 'memberships') if profile.person? %> |
| 68 | 68 | |
| 69 | + <%= control_panel_button(_('Manage SPAM'), 'manage-spam', :controller => 'spam', :action => 'index') %> | |
| 70 | + | |
| 69 | 71 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> |
| 70 | 72 | <%= control_panel_button(button[:title], button[:icon], button[:url]) %> |
| 71 | 73 | <% end %> | ... | ... |
app/views/profile_members/_index_buttons.rhtml
| ... | ... | @@ -4,7 +4,9 @@ |
| 4 | 4 | <% if profile.community? and user.has_permission?(:invite_members, profile) %> |
| 5 | 5 | <%= button :search, _('Invite your friends to join %s') % profile.short_name, :controller => 'invite', :action => 'select_address_book' %> |
| 6 | 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 | 10 | <% @plugins.dispatch(:manage_members_extra_buttons).each do |plugin_button| %> |
| 9 | 11 | <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url] %> |
| 10 | 12 | <% end %> | ... | ... |
app/views/profile_members/send_mail.rhtml
| ... | ... | @@ -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/_display_results.rhtml
| 1 | -<div id="search-results" class="<%= @results.size == 1 ? 'only-one-result-box' : 'multiple-results-boxes' %>"> | |
| 1 | +<div id="search-results" class="<%= !multiple_search? ? 'only-one-result-box' : 'multiple-results-boxes' %>"> | |
| 2 | 2 | <% @order.each do |name| %> |
| 3 | 3 | <% results = @results[name] %> |
| 4 | 4 | <% empty = results.nil? || results.empty? %> |
| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | <% if not empty %> |
| 8 | 8 | <% partial = partial_for_class(results.first.class.class_name.constantize) %> |
| 9 | 9 | |
| 10 | - <% if @results.size > 1 %> | |
| 10 | + <% if multiple_search? %> | |
| 11 | 11 | <h3><%= @names[name] %></h3> |
| 12 | 12 | <% if results.total_entries > SearchController::MULTIPLE_SEARCH_LIMIT %> |
| 13 | 13 | <%= link_to(_('see all (%d)') % results.total_entries, params.merge(:action => name), :class => 'see-more' ) %> |
| ... | ... | @@ -22,9 +22,10 @@ |
| 22 | 22 | </ul> |
| 23 | 23 | </div> |
| 24 | 24 | <% else %> |
| 25 | - <% if @results.size > 1 %> | |
| 25 | + <% if multiple_search? %> | |
| 26 | 26 | <h3><%= @names[name] %></h3> |
| 27 | 27 | <% end %> |
| 28 | + | |
| 28 | 29 | <div class="search-results-innerbox search-results-type-empty"> |
| 29 | 30 | <div> <%= _('None') %> </div> |
| 30 | 31 | </div> | ... | ... |
app/views/search/_image.rhtml
| 1 | 1 | <div class="search-image-container"> |
| 2 | 2 | |
| 3 | 3 | <% if image.is_a? UploadedFile and image.filename %> |
| 4 | - <% extension = image.filename[(image.filename.rindex('.')+1)..-1].downcase %> | |
| 4 | + <% extension = image.extension %> | |
| 5 | 5 | <% if ['jpg', 'jpeg', 'gif', 'png', 'tiff', 'svg'].include? extension %> |
| 6 | 6 | <%= link_to '', image.view_url, :class => "search-image-pic", :style => 'background-image: url(%s)'% image.public_filename(:thumb) %> |
| 7 | 7 | <% if image.width && image.height %> | ... | ... |
app/views/search/_profile.rhtml
| 1 | 1 | <li class="search-profile-item"> |
| 2 | -<% if @empty_query or @results.size > 1 or !profile.enterprise? %> | |
| 2 | +<% if @empty_query or multiple_search? or !profile.enterprise? %> | |
| 3 | 3 | <%= profile_image_link profile, :portrait, 'div', |
| 4 | 4 | @filter == 'more_recent' ? profile.send(@filter + '_label') + show_date(profile.created_at) : profile.send(@filter + '_label') %> |
| 5 | 5 | <% else %> | ... | ... |
app/views/search/communities.rhtml
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | <% if logged_in? %> |
| 5 | 5 | <% button_bar do %> |
| 6 | 6 | <%# FIXME shouldn't the user create the community in the current environment instead of going to its home environment? %> |
| 7 | - <%= button(:add, __('New community'), user.url.merge(:controller => 'memberships', :action => 'new_community')) %> | |
| 7 | + <%= button(:add, __('New community'), user.url.merge(:controller => 'memberships', :action => 'new_community', :profile => user.identifier)) %> | |
| 8 | 8 | <% end %> |
| 9 | 9 | <% end %> |
| 10 | 10 | ... | ... |
| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | +<h1><%= _('Manage SPAM') %></h1> | |
| 2 | + | |
| 3 | +<% button_bar do %> | |
| 4 | + <%= button :back, _('Back to control panel'), :controller => :profile_editor %> | |
| 5 | +<% end %> | |
| 6 | + | |
| 7 | +<%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> | |
| 8 | +<div id='article'> | |
| 9 | + <div class="comments" id="comments_list"> | |
| 10 | + <ul class="article-comments-list"> | |
| 11 | + <%= render :partial => 'content_viewer/comment', :collection => @spam %> | |
| 12 | + </ul> | |
| 13 | + </div> | |
| 14 | +</div> | |
| 15 | + | |
| 16 | +<%= pagination_links @spam %> | |
| 17 | + | |
| 18 | +<% button_bar do %> | |
| 19 | + <%= button :back, _('Back to control panel'), :controller => :profile_editor %> | |
| 20 | +<% end %> | ... | ... |
app/views/tasks/_task.rhtml
| ... | ... | @@ -50,13 +50,13 @@ |
| 50 | 50 | <% fields_for "tasks[#{task.id}][task]", task do |f| %> |
| 51 | 51 | <% if task.accept_details %> |
| 52 | 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 | 54 | </div> |
| 55 | 55 | <% end %> |
| 56 | 56 | |
| 57 | 57 | <% if task.reject_details %> |
| 58 | 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 | 60 | </div> |
| 61 | 61 | <% end %> |
| 62 | 62 | <% end %> | ... | ... |
app/views/tasks/processed.rhtml
config/initializers/action_tracker.rb
| ... | ... | @@ -23,7 +23,28 @@ ActionTrackerConfig.verbs = { |
| 23 | 23 | }, |
| 24 | 24 | |
| 25 | 25 | :upload_image => { |
| 26 | - :description => lambda { n_('uploaded 1 image<br />%{thumbnails}<br style="clear: both;" />', 'uploaded %{num} images<br />%{thumbnails}<br style="clear: both;" />', get_view_url.size) % { :num => get_view_url.size, :thumbnails => '{{ta.collect_group_with_index(:thumbnail_path){ |t,i| content_tag(:span, link_to(image_tag(t), ta.get_view_url[i]))}.last(3).join}}' } }, | |
| 26 | + :description => lambda do | |
| 27 | + total = get_view_url.size | |
| 28 | + n_('uploaded 1 image', 'uploaded %d images', total) % total + | |
| 29 | + '<br />{{'+ | |
| 30 | + 'ta.collect_group_with_index(:thumbnail_path) { |t,i|' + | |
| 31 | + " if ( #{total} == 1 );" + | |
| 32 | + ' link_to( image_tag(t), ta.get_view_url[i], :class => \'upimg\' );' + | |
| 33 | + ' else;' + | |
| 34 | + " pos = #{total}-i;" + | |
| 35 | + ' morethen2 = pos>2 ? \'morethen2\' : \'\';' + | |
| 36 | + ' morethen5 = pos>5 ? \'morethen5\' : \'\';' + | |
| 37 | + ' t = t.gsub(/(.*)(display)(.*)/, \'\\1thumb\\3\');' + | |
| 38 | + ' link_to( \' \', ta.get_view_url[i],' + | |
| 39 | + ' :style => "background-image:url(#{t})",' + | |
| 40 | + ' :class => "upimg pos#{pos} #{morethen2} #{morethen5}" );' + | |
| 41 | + ' end' + | |
| 42 | + '}.reverse.join}}' + | |
| 43 | + ( total > 5 ? | |
| 44 | + '<span class="more" onclick="this.parentNode.className+=\' show-all\'">' + | |
| 45 | + '…</span>' : '' ) + | |
| 46 | + '<br style="clear: both;" />' | |
| 47 | + end, | |
| 27 | 48 | :type => :groupable |
| 28 | 49 | }, |
| 29 | 50 | ... | ... |
config/initializers/plugins.rb
| 1 | 1 | require 'noosfero/plugin' |
| 2 | -require 'noosfero/plugin/acts_as_having_hotspots' | |
| 2 | +require 'noosfero/plugin/hot_spot' | |
| 3 | 3 | require 'noosfero/plugin/manager' |
| 4 | -require 'noosfero/plugin/context' | |
| 5 | 4 | require 'noosfero/plugin/active_record' |
| 6 | 5 | require 'noosfero/plugin/mailer_base' |
| 7 | 6 | Noosfero::Plugin.init_system if $NOOSFERO_LOAD_PLUGINS | ... | ... |
config/routes.rb
| ... | ... | @@ -19,16 +19,17 @@ ActionController::Routing::Routes.draw do |map| |
| 19 | 19 | |
| 20 | 20 | # -- just remember to delete public/index.html. |
| 21 | 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 | 23 | map.connect '', :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } |
| 23 | 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 | 34 | # online documentation |
| 34 | 35 | map.doc 'doc', :controller => 'doc', :action => 'index' |
| ... | ... | @@ -121,9 +122,12 @@ ActionController::Routing::Routes.draw do |map| |
| 121 | 122 | # cache stuff - hack |
| 122 | 123 | map.cache 'public/:action/:id', :controller => 'public' |
| 123 | 124 | |
| 125 | + map.connect ':profile/edit_comment/:id/*page', :controller => 'content_viewer', :action => 'edit_comment', :profile => /#{Noosfero.identifier_format}/ | |
| 126 | + | |
| 124 | 127 | # match requests for profiles that don't have a custom domain |
| 125 | 128 | map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } |
| 126 | 129 | |
| 130 | + | |
| 127 | 131 | # match requests for content in domains hosted for profiles |
| 128 | 132 | map.connect '*page', :controller => 'content_viewer', :action => 'view_page' |
| 129 | 133 | ... | ... |
db/migrate/20120824165019_add_permission_for_send_mail_to_members_to_admin_and_moderator_roles.rb
0 → 100644
| ... | ... | @@ -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 @@ |
| 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/migrate/20120825185219_add_user_agent_and_referrer_to_comments.rb
0 → 100644
| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | +class AddUserAgentAndReferrerToComments < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + add_column :comments, :user_agent, :string | |
| 4 | + add_column :comments, :referrer, :string | |
| 5 | + end | |
| 6 | + | |
| 7 | + def self.down | |
| 8 | + remove_column :comments, :user_agent | |
| 9 | + remove_column :comments, :referrer | |
| 10 | + end | |
| 11 | +end | ... | ... |
db/schema.rb
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | # |
| 10 | 10 | # It's strongly recommended to check this file into your version control system. |
| 11 | 11 | |
| 12 | -ActiveRecord::Schema.define(:version => 20120818030329) do | |
| 12 | +ActiveRecord::Schema.define(:version => 20121008185303) do | |
| 13 | 13 | |
| 14 | 14 | create_table "abuse_reports", :force => true do |t| |
| 15 | 15 | t.integer "reporter_id" |
| ... | ... | @@ -213,6 +213,8 @@ ActiveRecord::Schema.define(:version => 20120818030329) do |
| 213 | 213 | t.string "ip_address" |
| 214 | 214 | t.boolean "spam" |
| 215 | 215 | t.string "source_type" |
| 216 | + t.string "user_agent" | |
| 217 | + t.string "referrer" | |
| 216 | 218 | end |
| 217 | 219 | |
| 218 | 220 | create_table "contact_lists", :force => true do |t| |
| ... | ... | @@ -259,6 +261,8 @@ ActiveRecord::Schema.define(:version => 20120818030329) do |
| 259 | 261 | t.datetime "created_at" |
| 260 | 262 | t.datetime "updated_at" |
| 261 | 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" | |
| 262 | 266 | end |
| 263 | 267 | |
| 264 | 268 | create_table "external_feeds", :force => true do |t| |
| ... | ... | @@ -436,6 +440,7 @@ ActiveRecord::Schema.define(:version => 20120818030329) do |
| 436 | 440 | t.string "national_region_code" |
| 437 | 441 | t.boolean "is_template", :default => false |
| 438 | 442 | t.integer "template_id" |
| 443 | + t.string "redirection_after_login" | |
| 439 | 444 | end |
| 440 | 445 | |
| 441 | 446 | add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" | ... | ... |
debian/changelog
| 1 | +noosfero (0.39.0~1) UNRELEASED; urgency=low | |
| 2 | + | |
| 3 | + * Pre-release to test the antispam mechanism. | |
| 4 | + | |
| 5 | + -- Antonio Terceiro <terceiro@debian.org> Thu, 30 Aug 2012 14:55:10 -0300 | |
| 6 | + | |
| 7 | +noosfero (0.38.2) unstable; urgency=low | |
| 8 | + | |
| 9 | + * Bugfixes release | |
| 10 | + | |
| 11 | + -- Antonio Terceiro <terceiro@colivre.coop.br> Wed, 05 Sep 2012 10:07:58 -0300 | |
| 12 | + | |
| 1 | 13 | noosfero (0.38.1) unstable; urgency=low |
| 2 | 14 | |
| 3 | 15 | * Bugfixes release | ... | ... |
debian/control
| ... | ... | @@ -62,8 +62,7 @@ Description: free web-based platform for social networks |
| 62 | 62 | |
| 63 | 63 | Package: noosfero-apache |
| 64 | 64 | Architecture: all |
| 65 | -Depends: apache2, debconf | |
| 66 | -Suggests: noosfero | |
| 65 | +Depends: apache2, debconf, noosfero | |
| 67 | 66 | Description: free web-based platform for social networks (apache frontend) |
| 68 | 67 | Noosfero is a web platform for social and solidarity economy networks with |
| 69 | 68 | blog, e-Porfolios, CMS, RSS, thematic discussion, events agenda and collective | ... | ... |
debian/noosfero-console
etc/noosfero/varnish-noosfero.vcl
| 1 | 1 | sub vcl_recv { |
| 2 | + if (req.request == "GET" || req.request == "HEAD") { | |
| 2 | 3 | if (req.http.Cookie) { |
| 3 | - # We only care about the "_noosfero_session.*" cookie, used for | |
| 4 | - # authentication. | |
| 5 | - if (req.http.Cookie ~ "_noosfero_session.*" ) { | |
| 6 | - return (pass); | |
| 7 | - } | |
| 8 | - # Else strip all cookies | |
| 4 | + # We only care about the "_noosfero_session.*" cookie, used for | |
| 5 | + # authentication. | |
| 6 | + if (req.http.Cookie !~ "_noosfero_session.*" ) { | |
| 7 | + # strip all cookies | |
| 9 | 8 | unset req.http.Cookie; |
| 9 | + } | |
| 10 | 10 | } |
| 11 | + } | |
| 11 | 12 | } |
| 12 | 13 | |
| 13 | 14 | sub vcl_error { | ... | ... |
features/edit_environment_templates.feature
| ... | ... | @@ -8,7 +8,7 @@ Feature: edit environment templates |
| 8 | 8 | Scenario: See links to edit all templates |
| 9 | 9 | Given I am logged in as admin |
| 10 | 10 | When I follow "Administration" |
| 11 | - And I follow "Edit Templates" | |
| 11 | + And I follow "Profile templates" | |
| 12 | 12 | Then I should see "Person template" link |
| 13 | 13 | And I should see "Community template" link |
| 14 | 14 | And I should see "Enterprise template" link |
| ... | ... | @@ -17,28 +17,28 @@ Feature: edit environment templates |
| 17 | 17 | Scenario: Go to control panel of person template |
| 18 | 18 | Given I am logged in as admin |
| 19 | 19 | When I follow "Administration" |
| 20 | - And I follow "Edit Templates" | |
| 20 | + And I follow "Profile templates" | |
| 21 | 21 | And I follow "Person template" |
| 22 | 22 | Then I should be on Person template's control panel |
| 23 | 23 | |
| 24 | 24 | Scenario: Go to control panel of enterprise template |
| 25 | 25 | Given I am logged in as admin |
| 26 | 26 | When I follow "Administration" |
| 27 | - And I follow "Edit Templates" | |
| 27 | + And I follow "Profile templates" | |
| 28 | 28 | And I follow "Enterprise template" |
| 29 | 29 | Then I should be on Enterprise template's control panel |
| 30 | 30 | |
| 31 | 31 | Scenario: Go to control panel of inactive enterprise template |
| 32 | 32 | Given I am logged in as admin |
| 33 | 33 | When I follow "Administration" |
| 34 | - And I follow "Edit Templates" | |
| 34 | + And I follow "Profile templates" | |
| 35 | 35 | And I follow "Inactive enterprise template" |
| 36 | 36 | Then I should be on Inactive Enterprise template's control panel |
| 37 | 37 | |
| 38 | 38 | Scenario: Go to control panel of community template |
| 39 | 39 | Given I am logged in as admin |
| 40 | 40 | When I follow "Administration" |
| 41 | - And I follow "Edit Templates" | |
| 41 | + And I follow "Profile templates" | |
| 42 | 42 | And I follow "Community template" |
| 43 | 43 | Then I should be on Community template's control panel |
| 44 | 44 | |
| ... | ... | @@ -46,7 +46,7 @@ Feature: edit environment templates |
| 46 | 46 | Given that the default environment have no Inactive Enterprise template |
| 47 | 47 | And I am logged in as admin |
| 48 | 48 | When I follow "Administration" |
| 49 | - And I follow "Edit Templates" | |
| 49 | + And I follow "Profile templates" | |
| 50 | 50 | Then I should see "Person template" link |
| 51 | 51 | And I should see "Community template" link |
| 52 | 52 | And I should see "Enterprise template" link | ... | ... |