Commit d29ca9e2cc8fff7951cb1be4787575334704a3d1
Exists in
master
and in
29 other branches
Merge branch 'master' into chat
Conflicts: public/stylesheets/application.css
Showing
359 changed files
with
15972 additions
and
1016 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 359 files displayed.
Gemfile
1 | source "https://rubygems.org" | 1 | source "https://rubygems.org" |
2 | -gem 'rails', '~> 3.2.19' | 2 | +gem 'rails', '~> 3.2.21' |
3 | gem 'minitest', '~> 3.2.0' | 3 | gem 'minitest', '~> 3.2.0' |
4 | gem 'fast_gettext', '~> 0.6.8' | 4 | gem 'fast_gettext', '~> 0.6.8' |
5 | gem 'acts-as-taggable-on', '~> 3.0.2' | 5 | gem 'acts-as-taggable-on', '~> 3.0.2' |
@@ -21,6 +21,8 @@ gem 'exception_notification', '~> 4.0.1' | @@ -21,6 +21,8 @@ gem 'exception_notification', '~> 4.0.1' | ||
21 | gem 'gettext', '~> 2.2.1', :require => false, :group => :development | 21 | gem 'gettext', '~> 2.2.1', :require => false, :group => :development |
22 | gem 'locale', '~> 2.0.5' | 22 | gem 'locale', '~> 2.0.5' |
23 | 23 | ||
24 | +gem 'whenever', :require => false | ||
25 | + | ||
24 | # FIXME list here all actual dependencies (i.e. the ones in debian/control), | 26 | # FIXME list here all actual dependencies (i.e. the ones in debian/control), |
25 | # with their GEM names (not the Debian package names) | 27 | # with their GEM names (not the Debian package names) |
26 | 28 |
MIGRATION_ISSUES
@@ -1,41 +0,0 @@ | @@ -1,41 +0,0 @@ | ||
1 | -* ruby-get-text incmopatible with rails3. Maybe we can use it's gem | ||
2 | - | ||
3 | -* all js code is inside miscellaneous.js. Would be nice to refactor this | ||
4 | - | ||
5 | -* rails 2 uses prototype instead of jquery | ||
6 | - | ||
7 | -* config/environment.rb maybe still have some code that should be on the initializers | ||
8 | - | ||
9 | -* initializers session_store.rb inflections.rb... don't exist | ||
10 | - | ||
11 | -* rails gems version have to be forced on Gemfile or it will use incompatible pre3vious versions (3.1.3) | ||
12 | - | ||
13 | -* Sweepers are now natively supported on Rails 3. Would be nice to refactor it | ||
14 | - | ||
15 | -* On Rails 3 it is no more possible to add allowed tags to avoid scape. The html_safe initializer is an option. | ||
16 | - | ||
17 | -* error when call sqlite_extensiosn | ||
18 | - | ||
19 | -* error related to action_tracker | ||
20 | - | ||
21 | -* check FIXME's in script/quick-start | ||
22 | - | ||
23 | -* check FIXME's in Gemfile | ||
24 | - | ||
25 | -* Check the FIXME in config/routes.rb | ||
26 | - | ||
27 | -* rewrite conditional routing. See FIXME in lib/route_if.rb and re-implement using the Rails 3 mechanism - http://guides.rubyonrails.org/routing.html#advanced-constraints | ||
28 | - | ||
29 | -* check FIXME's in config/environment.rb | ||
30 | - | ||
31 | -* xss_terminate sucks. We should replace it with the builtin mechanism in Rails 3 | ||
32 | - | ||
33 | -* instance_eval on Ruby 1.9 yields self, so lambdas that are passed to instance_eval and do not accept exactly 1 argument will blow up. See http://www.ruby-forum.com/topic/213313 ... search for instance_eval and fix where necessary. In special, most of the blocks still need fixing. | ||
34 | - | ||
35 | -* all instances of <% *_form_for ... %> must be changed to <%= instead of <% | ||
36 | - | ||
37 | -* all ActiveRecord models have to declare explicitly which attributes must be allowed for mass assignment with attr_accessible. | ||
38 | - | ||
39 | -* check if we need to update config/locales/* | ||
40 | - | ||
41 | -* check observe_field and labelled_form_for in app/helpers/application_helper.rb |
app/controllers/admin/region_validators_controller.rb
@@ -33,7 +33,7 @@ class RegionValidatorsController < AdminController | @@ -33,7 +33,7 @@ class RegionValidatorsController < AdminController | ||
33 | def load_region_and_search | 33 | def load_region_and_search |
34 | @region = environment.regions.find(params[:id]) | 34 | @region = environment.regions.find(params[:id]) |
35 | if params[:search] | 35 | if params[:search] |
36 | - @search = find_by_contents(:organizations, Organization, params[:search])[:results].reject {|item| @region.validator_ids.include?(item.id) } | 36 | + @search = find_by_contents(:organizations, environment, Organization, params[:search])[:results].reject {|item| @region.validator_ids.include?(item.id) } |
37 | end | 37 | end |
38 | end | 38 | end |
39 | 39 |
app/controllers/admin/users_controller.rb
@@ -18,7 +18,7 @@ class UsersController < AdminController | @@ -18,7 +18,7 @@ class UsersController < AdminController | ||
18 | end | 18 | end |
19 | scope = scope.order('name ASC') | 19 | scope = scope.order('name ASC') |
20 | @q = params[:q] | 20 | @q = params[:q] |
21 | - @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results] | 21 | + @collection = find_by_contents(:people, environment, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results] |
22 | end | 22 | end |
23 | 23 | ||
24 | def set_admin_role | 24 | def set_admin_role |
app/controllers/application_controller.rb
@@ -183,21 +183,19 @@ class ApplicationController < ActionController::Base | @@ -183,21 +183,19 @@ class ApplicationController < ActionController::Base | ||
183 | end | 183 | end |
184 | end | 184 | end |
185 | 185 | ||
186 | - def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={}) | ||
187 | - plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) || | ||
188 | - fallback_find_by_contents(asset, scope, query, paginate_options, options) | ||
189 | - end | 186 | + include SearchTermHelper |
190 | 187 | ||
191 | - private | 188 | + def find_by_contents(asset, context, scope, query, paginate_options={:page => 1}, options={}) |
189 | + search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) | ||
190 | + register_search_term(query, scope.count, search[:results].count, context, asset) | ||
191 | + search | ||
192 | + end | ||
192 | 193 | ||
193 | - def fallback_find_by_contents(asset, scope, query, paginate_options, options) | ||
194 | - scope = scope.like_search(query) unless query.blank? | ||
195 | - scope = scope.send(options[:filter]) unless options[:filter].blank? | ||
196 | - {:results => scope.paginate(paginate_options)} | 194 | + def find_suggestions(query, context, asset, options={}) |
195 | + plugins.dispatch_first(:find_suggestions, query, context, asset, options) | ||
197 | end | 196 | end |
198 | 197 | ||
199 | def private_environment? | 198 | def private_environment? |
200 | @environment.enabled?(:restrict_to_members) | 199 | @environment.enabled?(:restrict_to_members) |
201 | end | 200 | end |
202 | - | ||
203 | end | 201 | end |
app/controllers/my_profile/cms_controller.rb
@@ -23,6 +23,9 @@ class CmsController < MyProfileController | @@ -23,6 +23,9 @@ class CmsController < MyProfileController | ||
23 | end | 23 | end |
24 | 24 | ||
25 | before_filter :login_required, :except => [:suggest_an_article] | 25 | before_filter :login_required, :except => [:suggest_an_article] |
26 | + before_filter :load_recent_files, :only => [:new, :edit] | ||
27 | + | ||
28 | + helper_method :file_types | ||
26 | 29 | ||
27 | protect_if :only => :upload_files do |c, user, profile| | 30 | protect_if :only => :upload_files do |c, user, profile| |
28 | article_id = c.params[:parent_id] | 31 | article_id = c.params[:parent_id] |
@@ -30,7 +33,7 @@ class CmsController < MyProfileController | @@ -30,7 +33,7 @@ class CmsController < MyProfileController | ||
30 | (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) | 33 | (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) |
31 | end | 34 | end |
32 | 35 | ||
33 | - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files, :new] do |c, user, profile| | 36 | + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :publish_on_portal_community, :publish_on_communities, :search_communities_to_publish, :upload_files, :new] do |c, user, profile| |
34 | user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) | 37 | user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) |
35 | end | 38 | end |
36 | 39 | ||
@@ -40,7 +43,7 @@ class CmsController < MyProfileController | @@ -40,7 +43,7 @@ class CmsController < MyProfileController | ||
40 | (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) | 43 | (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) |
41 | end | 44 | end |
42 | 45 | ||
43 | - protect_if :only => [:destroy, :publish] do |c, user, profile| | 46 | + protect_if :only => :destroy do |c, user, profile| |
44 | profile.articles.find(c.params[:id]).allow_post_content?(user) | 47 | profile.articles.find(c.params[:id]).allow_post_content?(user) |
45 | end | 48 | end |
46 | 49 | ||
@@ -117,7 +120,7 @@ class CmsController < MyProfileController | @@ -117,7 +120,7 @@ class CmsController < MyProfileController | ||
117 | @success_back_to = params[:success_back_to] | 120 | @success_back_to = params[:success_back_to] |
118 | # user must choose an article type first | 121 | # user must choose an article type first |
119 | 122 | ||
120 | - @parent = profile.articles.find(params[:parent_id]) if params && params[:parent_id] | 123 | + @parent = profile.articles.find(params[:parent_id]) if params && params[:parent_id].present? |
121 | record_coming | 124 | record_coming |
122 | @type = params[:type] | 125 | @type = params[:type] |
123 | if @type.blank? | 126 | if @type.blank? |
@@ -163,7 +166,10 @@ class CmsController < MyProfileController | @@ -163,7 +166,10 @@ class CmsController < MyProfileController | ||
163 | if continue | 166 | if continue |
164 | redirect_to :action => 'edit', :id => @article | 167 | redirect_to :action => 'edit', :id => @article |
165 | else | 168 | else |
166 | - success_redirect | 169 | + respond_to do |format| |
170 | + format.html { success_redirect } | ||
171 | + format.json { render :text => {:id => @article.id, :full_name => profile.identifier + '/' + @article.full_name}.to_json } | ||
172 | + end | ||
167 | end | 173 | end |
168 | return | 174 | return |
169 | end | 175 | end |
@@ -256,28 +262,53 @@ class CmsController < MyProfileController | @@ -256,28 +262,53 @@ class CmsController < MyProfileController | ||
256 | render :template => 'shared/update_categories', :locals => { :category => @current_category, :object_name => 'article' } | 262 | render :template => 'shared/update_categories', :locals => { :category => @current_category, :object_name => 'article' } |
257 | end | 263 | end |
258 | 264 | ||
265 | + def search_communities_to_publish | ||
266 | + render :text => find_by_contents(:profiles, environment, user.memberships, params['q'], {:page => 1}, {:fields => ['name']})[:results].map {|community| {:id => community.id, :name => community.name} }.to_json | ||
267 | + end | ||
268 | + | ||
259 | def publish | 269 | def publish |
260 | @article = profile.articles.find(params[:id]) | 270 | @article = profile.articles.find(params[:id]) |
261 | record_coming | 271 | record_coming |
262 | - @groups = profile.memberships - [profile] | ||
263 | - @marked_groups = [] | ||
264 | - groups_ids = profile.memberships.map{|m|m.id.to_s} | ||
265 | - @marked_groups = params[:marked_groups].map do |key, item| | ||
266 | - if groups_ids.include?(item[:group_id]) | ||
267 | - item.merge :group => Profile.find(item.delete(:group_id)) | 272 | + @failed = {} |
273 | + if request.post? | ||
274 | + article_name = params[:name] | ||
275 | + task = ApproveArticle.create!(:article => @article, :name => article_name, :target => user, :requestor => user) | ||
276 | + begin | ||
277 | + task.finish | ||
278 | + rescue Exception => ex | ||
279 | + @failed[ex.message] ? @failed[ex.message] << @article.name : @failed[ex.message] = [@article.name] | ||
280 | + task.cancel | ||
281 | + end | ||
282 | + if @failed.blank? | ||
283 | + session[:notice] = _("Your publish request was sent successfully") | ||
284 | + if @back_to | ||
285 | + redirect_to @back_to | ||
286 | + else | ||
287 | + redirect_to @article.view_url | ||
288 | + end | ||
268 | end | 289 | end |
269 | - end.compact unless params[:marked_groups].nil? | 290 | + end |
291 | + end | ||
292 | + | ||
293 | + def publish_on_communities | ||
270 | if request.post? | 294 | if request.post? |
295 | + @back_to = params[:back_to] | ||
296 | + @article = profile.articles.find(params[:id]) | ||
271 | @failed = {} | 297 | @failed = {} |
298 | + article_name = params[:name] | ||
299 | + params_marked = (params['q'] || '').split(',').select { |marked| user.memberships.map(&:id).include? marked.to_i } | ||
300 | + @marked_groups = Profile.find(params_marked) | ||
272 | if @marked_groups.empty? | 301 | if @marked_groups.empty? |
302 | + redirect_to @back_to | ||
273 | return session[:notice] = _("Select some group to publish your article") | 303 | return session[:notice] = _("Select some group to publish your article") |
274 | end | 304 | end |
275 | @marked_groups.each do |item| | 305 | @marked_groups.each do |item| |
276 | - task = ApproveArticle.create!(:article => @article, :name => item[:name], :target => item[:group], :requestor => profile) | 306 | + task = ApproveArticle.create!(:article => @article, :name => article_name, :target => item, :requestor => user) |
277 | begin | 307 | begin |
278 | - task.finish unless item[:group].moderated_articles? | 308 | + task.finish unless item.moderated_articles? |
279 | rescue Exception => ex | 309 | rescue Exception => ex |
280 | - @failed[ex.message] ? @failed[ex.message] << item[:group].name : @failed[ex.message] = [item[:group].name] | 310 | + @failed[ex.message] ? @failed[ex.message] << item.name : @failed[ex.message] = [item.name] |
311 | + task.cancel | ||
281 | end | 312 | end |
282 | end | 313 | end |
283 | if @failed.blank? | 314 | if @failed.blank? |
@@ -287,23 +318,27 @@ class CmsController < MyProfileController | @@ -287,23 +318,27 @@ class CmsController < MyProfileController | ||
287 | else | 318 | else |
288 | redirect_to @article.view_url | 319 | redirect_to @article.view_url |
289 | end | 320 | end |
321 | + else | ||
322 | + session[:notice] = _("Some of your publish requests couldn't be sent.") | ||
323 | + render :action => 'publish' | ||
290 | end | 324 | end |
291 | end | 325 | end |
292 | end | 326 | end |
293 | 327 | ||
294 | def publish_on_portal_community | 328 | def publish_on_portal_community |
295 | - @article = profile.articles.find(params[:id]) | ||
296 | if request.post? | 329 | if request.post? |
297 | - if environment.portal_community | 330 | + @article = profile.articles.find(params[:id]) |
331 | + if environment.portal_enabled | ||
298 | task = ApproveArticle.create!(:article => @article, :name => params[:name], :target => environment.portal_community, :requestor => user) | 332 | task = ApproveArticle.create!(:article => @article, :name => params[:name], :target => environment.portal_community, :requestor => user) |
299 | begin | 333 | begin |
300 | task.finish unless environment.portal_community.moderated_articles? | 334 | task.finish unless environment.portal_community.moderated_articles? |
301 | - flash[:notice] = _("Your publish request was sent successfully") | 335 | + session[:notice] = _("Your publish request was sent successfully") |
302 | rescue | 336 | rescue |
303 | - flash[:error] = _("Your publish request couldn't be sent.") | 337 | + session[:notice] = _("Your publish request couldn't be sent.") |
338 | + task.cancel | ||
304 | end | 339 | end |
305 | else | 340 | else |
306 | - flash[:notice] = _("There is no portal community to publish your article.") | 341 | + session[:notice] = _("There is no portal community to publish your article.") |
307 | end | 342 | end |
308 | 343 | ||
309 | if @back_to | 344 | if @back_to |
@@ -331,7 +366,7 @@ class CmsController < MyProfileController | @@ -331,7 +366,7 @@ class CmsController < MyProfileController | ||
331 | 366 | ||
332 | def search | 367 | def search |
333 | query = params[:q] | 368 | query = params[:q] |
334 | - results = find_by_contents(:uploaded_files, profile.files.published, query)[:results] | 369 | + results = find_by_contents(:uploaded_files, profile, profile.files.published, query)[:results] |
335 | render :text => article_list_to_json(results), :content_type => 'application/json' | 370 | render :text => article_list_to_json(results), :content_type => 'application/json' |
336 | end | 371 | end |
337 | 372 | ||
@@ -342,15 +377,26 @@ class CmsController < MyProfileController | @@ -342,15 +377,26 @@ class CmsController < MyProfileController | ||
342 | end | 377 | end |
343 | 378 | ||
344 | def media_upload | 379 | def media_upload |
345 | - files_uploaded = [] | ||
346 | parent = check_parent(params[:parent_id]) | 380 | parent = check_parent(params[:parent_id]) |
347 | - files = [:file1,:file2, :file3].map { |f| params[f] }.compact | ||
348 | if request.post? | 381 | if request.post? |
349 | - files.each do |file| | ||
350 | - files_uploaded << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => parent) unless file == '' | 382 | + begin |
383 | + @file = UploadedFile.create!(:uploaded_data => params[:file], :profile => profile, :parent => parent) unless params[:file] == '' | ||
384 | + @file = FilePresenter.for(@file) | ||
385 | + rescue Exception => exception | ||
386 | + render :text => exception.to_s, :status => :bad_request | ||
351 | end | 387 | end |
352 | end | 388 | end |
353 | - render :text => article_list_to_json(files_uploaded), :content_type => 'text/plain' | 389 | + end |
390 | + | ||
391 | + def published_media_items | ||
392 | + load_recent_files(params[:parent_id], params[:q]) | ||
393 | + render :partial => 'published_media_items' | ||
394 | + end | ||
395 | + | ||
396 | + def view_all_media | ||
397 | + paginate_options = {:page => params[:page].blank? ? 1 : params[:page] } | ||
398 | + @key = params[:key].to_sym | ||
399 | + load_recent_files(params[:parent_id], params[:q], paginate_options) | ||
354 | end | 400 | end |
355 | 401 | ||
356 | protected | 402 | protected |
@@ -445,4 +491,36 @@ class CmsController < MyProfileController | @@ -445,4 +491,36 @@ class CmsController < MyProfileController | ||
445 | end | 491 | end |
446 | end | 492 | end |
447 | 493 | ||
494 | + def file_types | ||
495 | + {:images => _('Images'), :generics => _('Files')} | ||
496 | + end | ||
497 | + | ||
498 | + def load_recent_files(parent_id = nil, q = nil, paginate_options = {:page => 1, :per_page => 6}) | ||
499 | + #TODO Since we only have special support for images, I'm limiting myself to | ||
500 | + # consider generic files as non-images. In the future, with more supported | ||
501 | + # file types we'll need to have a smart way to fetch from the database | ||
502 | + # scopes of each supported type as well as the non-supported types as a | ||
503 | + # whole. | ||
504 | + @recent_files = {} | ||
505 | + | ||
506 | + parent = parent_id.present? ? profile.articles.find(parent_id) : nil | ||
507 | + if parent.present? | ||
508 | + files = parent.children.files | ||
509 | + else | ||
510 | + files = profile.files | ||
511 | + end | ||
512 | + | ||
513 | + files = files.reorder('created_at DESC') | ||
514 | + images = files.images | ||
515 | + generics = files.no_images | ||
516 | + | ||
517 | + if q.present? | ||
518 | + @recent_files[:images] = find_by_contents(:images, profile, images, q, paginate_options)[:results] | ||
519 | + @recent_files[:generics] = find_by_contents(:generics, profile, generics, q, paginate_options)[:results] | ||
520 | + else | ||
521 | + @recent_files[:images] = images.paginate(paginate_options) | ||
522 | + @recent_files[:generics] = generics.paginate(paginate_options) | ||
523 | + end | ||
524 | + end | ||
525 | + | ||
448 | end | 526 | end |
app/controllers/my_profile/friends_controller.rb
@@ -3,6 +3,7 @@ class FriendsController < MyProfileController | @@ -3,6 +3,7 @@ class FriendsController < MyProfileController | ||
3 | protect 'manage_friends', :profile | 3 | protect 'manage_friends', :profile |
4 | 4 | ||
5 | def index | 5 | def index |
6 | + @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | ||
6 | if is_cache_expired?(profile.manage_friends_cache_key(params)) | 7 | if is_cache_expired?(profile.manage_friends_cache_key(params)) |
7 | @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) | 8 | @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) |
8 | end | 9 | end |
@@ -16,6 +17,30 @@ class FriendsController < MyProfileController | @@ -16,6 +17,30 @@ class FriendsController < MyProfileController | ||
16 | end | 17 | end |
17 | end | 18 | end |
18 | 19 | ||
20 | + def suggest | ||
21 | + @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | ||
22 | + end | ||
23 | + | ||
24 | + def remove_suggestion | ||
25 | + @person = profile.suggested_people.find_by_identifier(params[:id]) | ||
26 | + redirect_to :action => 'suggest' unless @person | ||
27 | + if @person && request.post? | ||
28 | + profile.remove_suggestion(@person) | ||
29 | + @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | ||
30 | + render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page } | ||
31 | + end | ||
32 | + end | ||
33 | + | ||
34 | + def connections | ||
35 | + @suggestion = profile.profile_suggestions.of_person.enabled.find_by_suggestion_id(params[:id]) | ||
36 | + if @suggestion | ||
37 | + @tags = @suggestion.tag_connections | ||
38 | + @profiles = @suggestion.profile_connections | ||
39 | + else | ||
40 | + redirect_to :action => 'suggest' | ||
41 | + end | ||
42 | + end | ||
43 | + | ||
19 | protected | 44 | protected |
20 | 45 | ||
21 | class << self | 46 | class << self |
app/controllers/my_profile/memberships_controller.rb
@@ -20,12 +20,54 @@ class MembershipsController < MyProfileController | @@ -20,12 +20,54 @@ class MembershipsController < MyProfileController | ||
20 | @community.environment = environment | 20 | @community.environment = environment |
21 | @back_to = params[:back_to] || url_for(:action => 'index') | 21 | @back_to = params[:back_to] || url_for(:action => 'index') |
22 | if request.post? && @community.valid? | 22 | if request.post? && @community.valid? |
23 | - @community = Community.create_after_moderation(user, params[:community].merge({:environment => environment})) | ||
24 | - if @community.new_record? | 23 | + begin |
24 | + # Community was created | ||
25 | + @community = Community.create_after_moderation(user, params[:community].merge({:environment => environment})) | ||
26 | + @community.reload | ||
27 | + redirect_to :action => 'welcome', :community_id => @community.id, :back_to => @back_to | ||
28 | + rescue ActiveRecord::RecordNotFound | ||
29 | + # Community pending approval | ||
25 | session[:notice] = _('Your new community creation request will be evaluated by an administrator. You will be notified.') | 30 | session[:notice] = _('Your new community creation request will be evaluated by an administrator. You will be notified.') |
31 | + redirect_to @back_to | ||
26 | end | 32 | end |
27 | - redirect_to @back_to | ||
28 | return | 33 | return |
29 | end | 34 | end |
30 | end | 35 | end |
36 | + | ||
37 | + def welcome | ||
38 | + @community = Community.find(params[:community_id]) | ||
39 | + @back_to = params[:back_to] | ||
40 | + end | ||
41 | + | ||
42 | + def suggest | ||
43 | + @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(per_page) | ||
44 | + end | ||
45 | + | ||
46 | + def remove_suggestion | ||
47 | + @community = profile.suggested_communities.find_by_identifier(params[:id]) | ||
48 | + custom_per_page = params[:per_page] || per_page | ||
49 | + redirect_to :action => 'suggest' unless @community | ||
50 | + if @community && request.post? | ||
51 | + profile.remove_suggestion(@community) | ||
52 | + @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(custom_per_page) | ||
53 | + render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page} | ||
54 | + end | ||
55 | + end | ||
56 | + | ||
57 | + def connections | ||
58 | + @suggestion = profile.profile_suggestions.of_community.enabled.find_by_suggestion_id(params[:id]) | ||
59 | + if @suggestion | ||
60 | + @tags = @suggestion.tag_connections | ||
61 | + @profiles = @suggestion.profile_connections | ||
62 | + else | ||
63 | + redirect_to :action => 'suggest' | ||
64 | + end | ||
65 | + end | ||
66 | + | ||
67 | + protected | ||
68 | + | ||
69 | + def per_page | ||
70 | + 12 | ||
71 | + end | ||
72 | + | ||
31 | end | 73 | end |
app/controllers/my_profile/profile_editor_controller.rb
@@ -3,6 +3,10 @@ class ProfileEditorController < MyProfileController | @@ -3,6 +3,10 @@ class ProfileEditorController < MyProfileController | ||
3 | protect 'edit_profile', :profile, :except => [:destroy_profile] | 3 | protect 'edit_profile', :profile, :except => [:destroy_profile] |
4 | protect 'destroy_profile', :profile, :only => [:destroy_profile] | 4 | protect 'destroy_profile', :profile, :only => [:destroy_profile] |
5 | 5 | ||
6 | + before_filter :access_welcome_page, :only => [:welcome_page] | ||
7 | + before_filter :back_to | ||
8 | + helper_method :has_welcome_page | ||
9 | + | ||
6 | def index | 10 | def index |
7 | @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)} | 11 | @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)} |
8 | end | 12 | end |
@@ -85,6 +89,21 @@ class ProfileEditorController < MyProfileController | @@ -85,6 +89,21 @@ class ProfileEditorController < MyProfileController | ||
85 | end | 89 | end |
86 | end | 90 | end |
87 | 91 | ||
92 | + def welcome_page | ||
93 | + @welcome_page = profile.welcome_page || TinyMceArticle.new(:name => 'Welcome Page', :profile => profile, :published => false) | ||
94 | + if request.post? | ||
95 | + begin | ||
96 | + @welcome_page.update_attributes!(params[:welcome_page]) | ||
97 | + profile.welcome_page = @welcome_page | ||
98 | + profile.save! | ||
99 | + session[:notice] = _('Welcome page saved successfully.') | ||
100 | + redirect_to :action => 'index' | ||
101 | + rescue Exception => exception | ||
102 | + session[:notice] = _('Welcome page could not be saved.') | ||
103 | + end | ||
104 | + end | ||
105 | + end | ||
106 | + | ||
88 | def deactivate_profile | 107 | def deactivate_profile |
89 | if environment.admins.include?(current_person) | 108 | if environment.admins.include?(current_person) |
90 | profile = environment.profiles.find(params[:id]) | 109 | profile = environment.profiles.find(params[:id]) |
@@ -116,9 +135,24 @@ class ProfileEditorController < MyProfileController | @@ -116,9 +135,24 @@ class ProfileEditorController < MyProfileController | ||
116 | protected | 135 | protected |
117 | 136 | ||
118 | def redirect_to_previous_location | 137 | def redirect_to_previous_location |
119 | - back = request.referer | ||
120 | - back = "/" if back.nil? | 138 | + redirect_to @back_to |
139 | + end | ||
121 | 140 | ||
122 | - redirect_to back | 141 | + #TODO Consider using this as a general controller feature to be available on every action. |
142 | + def back_to | ||
143 | + @back_to = params[:back_to] || request.referer || "/" | ||
123 | end | 144 | end |
145 | + | ||
146 | + private | ||
147 | + | ||
148 | + def has_welcome_page | ||
149 | + profile.is_template | ||
150 | + end | ||
151 | + | ||
152 | + def access_welcome_page | ||
153 | + unless has_welcome_page | ||
154 | + render_access_denied | ||
155 | + end | ||
156 | + end | ||
157 | + | ||
124 | end | 158 | end |
app/controllers/public/account_controller.rb
@@ -82,10 +82,12 @@ class AccountController < ApplicationController | @@ -82,10 +82,12 @@ class AccountController < ApplicationController | ||
82 | if @plugins.dispatch(:allow_user_registration).include?(false) | 82 | if @plugins.dispatch(:allow_user_registration).include?(false) |
83 | redirect_back_or_default(:controller => 'home') | 83 | redirect_back_or_default(:controller => 'home') |
84 | session[:notice] = _("This environment doesn't allow user registration.") | 84 | session[:notice] = _("This environment doesn't allow user registration.") |
85 | + return | ||
85 | end | 86 | end |
86 | 87 | ||
87 | store_location(request.referer) unless params[:return_to] or session[:return_to] | 88 | store_location(request.referer) unless params[:return_to] or session[:return_to] |
88 | 89 | ||
90 | + # Tranforming to boolean | ||
89 | @block_bot = !!session[:may_be_a_bot] | 91 | @block_bot = !!session[:may_be_a_bot] |
90 | @invitation_code = params[:invitation_code] | 92 | @invitation_code = params[:invitation_code] |
91 | begin | 93 | begin |
@@ -129,8 +131,8 @@ class AccountController < ApplicationController | @@ -129,8 +131,8 @@ class AccountController < ApplicationController | ||
129 | check_join_in_community(@user) | 131 | check_join_in_community(@user) |
130 | go_to_signup_initial_page | 132 | go_to_signup_initial_page |
131 | else | 133 | else |
134 | + redirect_to :controller => :home, :action => :welcome, :template_id => (@user.person.template && @user.person.template.id) | ||
132 | session[:notice] = _('Thanks for registering!') | 135 | session[:notice] = _('Thanks for registering!') |
133 | - @register_pending = true | ||
134 | end | 136 | end |
135 | end | 137 | end |
136 | end | 138 | end |
@@ -461,6 +463,8 @@ class AccountController < ApplicationController | @@ -461,6 +463,8 @@ class AccountController < ApplicationController | ||
461 | redirect_to user.url | 463 | redirect_to user.url |
462 | when 'user_control_panel' | 464 | when 'user_control_panel' |
463 | redirect_to user.admin_url | 465 | redirect_to user.admin_url |
466 | + when 'welcome_page' | ||
467 | + redirect_to :controller => :home, :action => :welcome, :template_id => (user.template && user.template.id) | ||
464 | else | 468 | else |
465 | redirect_back_or_default(default) | 469 | redirect_back_or_default(default) |
466 | end | 470 | end |
app/controllers/public/home_controller.rb
@@ -18,4 +18,10 @@ class HomeController < PublicController | @@ -18,4 +18,10 @@ class HomeController < PublicController | ||
18 | @no_design_blocks = true | 18 | @no_design_blocks = true |
19 | end | 19 | end |
20 | 20 | ||
21 | + def welcome | ||
22 | + @no_design_blocks = true | ||
23 | + @display_confirmation_tips = !user.present? && !environment.enabled?(:skip_new_user_email_confirmation) | ||
24 | + @person_template = user && user.template || params[:template_id] && Person.find(params[:template_id]) | ||
25 | + end | ||
26 | + | ||
21 | end | 27 | end |
app/controllers/public/invite_controller.rb
@@ -4,8 +4,15 @@ class InviteController < PublicController | @@ -4,8 +4,15 @@ class InviteController < PublicController | ||
4 | before_filter :login_required | 4 | before_filter :login_required |
5 | before_filter :check_permissions_to_invite | 5 | before_filter :check_permissions_to_invite |
6 | 6 | ||
7 | - def select_address_book | 7 | + def invite_friends |
8 | @import_from = params[:import_from] || "manual" | 8 | @import_from = params[:import_from] || "manual" |
9 | + @mail_template = params[:mail_template] || environment.invitation_mail_template(profile) | ||
10 | + | ||
11 | + labels = Profile::SEARCHABLE_FIELDS.except(:nickname).merge(User::SEARCHABLE_FIELDS).map { |name,info| info[:label].downcase } | ||
12 | + last = labels.pop | ||
13 | + label = labels.join(', ') | ||
14 | + @search_fields = "#{label} #{_('or')} #{last}" | ||
15 | + | ||
9 | if request.post? | 16 | if request.post? |
10 | contact_list = ContactList.create | 17 | contact_list = ContactList.create |
11 | Delayed::Job.enqueue GetEmailContactsJob.new(@import_from, params[:login], params[:password], contact_list.id) if @import_from != 'manual' | 18 | Delayed::Job.enqueue GetEmailContactsJob.new(@import_from, params[:login], params[:password], contact_list.id) if @import_from != 'manual' |
@@ -22,7 +29,7 @@ class InviteController < PublicController | @@ -22,7 +29,7 @@ class InviteController < PublicController | ||
22 | webmail_import_addresses = params[:webmail_import_addresses] | 29 | webmail_import_addresses = params[:webmail_import_addresses] |
23 | contacts_to_invite = Invitation.join_contacts(manual_import_addresses, webmail_import_addresses) | 30 | contacts_to_invite = Invitation.join_contacts(manual_import_addresses, webmail_import_addresses) |
24 | if !contacts_to_invite.empty? | 31 | if !contacts_to_invite.empty? |
25 | - Delayed::Job.enqueue InvitationJob.new(current_user.person.id, contacts_to_invite, params[:mail_template], profile.id, @contact_list.id, locale) | 32 | + Delayed::Job.enqueue InvitationJob.new(user.id, contacts_to_invite, params[:mail_template], profile.id, @contact_list.id, locale) |
26 | session[:notice] = _('Your invitations are being sent.') | 33 | session[:notice] = _('Your invitations are being sent.') |
27 | if profile.person? | 34 | if profile.person? |
28 | redirect_to :controller => 'profile', :action => 'friends' | 35 | redirect_to :controller => 'profile', :action => 'friends' |
@@ -52,16 +59,36 @@ class InviteController < PublicController | @@ -52,16 +59,36 @@ class InviteController < PublicController | ||
52 | def cancel_fetching_emails | 59 | def cancel_fetching_emails |
53 | contact_list = ContactList.find(params[:contact_list]) | 60 | contact_list = ContactList.find(params[:contact_list]) |
54 | contact_list.destroy | 61 | contact_list.destroy |
55 | - redirect_to :action => 'select_address_book' | 62 | + redirect_to :action => 'invite_friends' |
63 | + end | ||
64 | + | ||
65 | + def invite_registered_friend | ||
66 | + contacts_to_invite = params['q'].split(',') | ||
67 | + if !contacts_to_invite.empty? && request.post? | ||
68 | + Delayed::Job.enqueue InvitationJob.new(user.id, contacts_to_invite, '', profile.id, nil, locale) | ||
69 | + session[:notice] = _('Your invitations are being sent.') | ||
70 | + if profile.person? | ||
71 | + redirect_to :controller => 'profile', :action => 'friends' | ||
72 | + else | ||
73 | + redirect_to :controller => 'profile', :action => 'members' | ||
74 | + end | ||
75 | + else | ||
76 | + redirect_to :action => 'invite_friends' | ||
77 | + session[:notice] = _('Please enter a valid profile.') | ||
78 | + end | ||
79 | + end | ||
80 | + | ||
81 | + def search | ||
82 | + scope = profile.invite_friends_only ? user.friends : environment.people | ||
83 | + scope = scope.not_members_of(profile) if profile.organization? | ||
84 | + scope = scope.not_friends_of(profile) if profile.person? | ||
85 | + results = find_by_contents(:people, environment, scope, params['q'], {:page => 1}, {:joins => :user})[:results] | ||
86 | + render :text => prepare_to_token_input(results).to_json | ||
56 | end | 87 | end |
57 | 88 | ||
58 | protected | 89 | protected |
59 | 90 | ||
60 | def check_permissions_to_invite | 91 | def check_permissions_to_invite |
61 | - if profile.person? and !current_user.person.has_permission?(:manage_friends, profile) or | ||
62 | - profile.community? and !current_user.person.has_permission?(:invite_members, profile) | ||
63 | - render_access_denied | ||
64 | - end | 92 | + render_access_denied if !profile.allow_invitation_from?(user) |
65 | end | 93 | end |
66 | - | ||
67 | end | 94 | end |
app/controllers/public/profile_search_controller.rb
@@ -9,9 +9,12 @@ class ProfileSearchController < PublicController | @@ -9,9 +9,12 @@ class ProfileSearchController < PublicController | ||
9 | @q = params[:q] | 9 | @q = params[:q] |
10 | unless @q.blank? | 10 | unless @q.blank? |
11 | if params[:where] == 'environment' | 11 | if params[:where] == 'environment' |
12 | - redirect_to :controller => 'search', :query => @q | 12 | + # user is using global search, redirects to the search controller with |
13 | + # the query | ||
14 | + search_path = url_for(:controller => 'search', :query => @q) | ||
15 | + request.xhr? ? render(:js => "window.location.href = #{search_path.to_json}") : redirect_to(search_path) | ||
13 | else | 16 | else |
14 | - @results = find_by_contents(:articles, profile.articles.published, @q, {:per_page => 10, :page => params[:page]})[:results] | 17 | + @results = find_by_contents(:articles, profile, profile.articles.published, @q, {:per_page => 10, :page => params[:page]})[:results] |
15 | end | 18 | end |
16 | end | 19 | end |
17 | end | 20 | end |
app/controllers/public/search_controller.rb
@@ -4,11 +4,11 @@ class SearchController < PublicController | @@ -4,11 +4,11 @@ class SearchController < PublicController | ||
4 | include SearchHelper | 4 | include SearchHelper |
5 | include ActionView::Helpers::NumberHelper | 5 | include ActionView::Helpers::NumberHelper |
6 | 6 | ||
7 | - before_filter :redirect_asset_param, :except => :assets | ||
8 | - before_filter :load_category | ||
9 | - before_filter :load_search_assets | ||
10 | - before_filter :load_query | ||
11 | - before_filter :load_filter | 7 | + before_filter :redirect_asset_param, :except => [:assets, :suggestions] |
8 | + before_filter :load_category, :except => :suggestions | ||
9 | + before_filter :load_search_assets, :except => :suggestions | ||
10 | + before_filter :load_query, :except => :suggestions | ||
11 | + before_filter :load_order, :except => :suggestions | ||
12 | 12 | ||
13 | # Backwards compatibility with old URLs | 13 | # Backwards compatibility with old URLs |
14 | def redirect_asset_param | 14 | def redirect_asset_param |
@@ -20,7 +20,7 @@ class SearchController < PublicController | @@ -20,7 +20,7 @@ class SearchController < PublicController | ||
20 | 20 | ||
21 | def index | 21 | def index |
22 | @searches = {} | 22 | @searches = {} |
23 | - @order = [] | 23 | + @assets = [] |
24 | @names = {} | 24 | @names = {} |
25 | @results_only = true | 25 | @results_only = true |
26 | 26 | ||
@@ -28,7 +28,7 @@ class SearchController < PublicController | @@ -28,7 +28,7 @@ class SearchController < PublicController | ||
28 | load_query | 28 | load_query |
29 | @asset = key | 29 | @asset = key |
30 | send(key) | 30 | send(key) |
31 | - @order << key | 31 | + @assets << key |
32 | @names[key] = _(description) | 32 | @names[key] = _(description) |
33 | end | 33 | end |
34 | @asset = nil | 34 | @asset = nil |
@@ -42,7 +42,7 @@ class SearchController < PublicController | @@ -42,7 +42,7 @@ class SearchController < PublicController | ||
42 | # view the summary of one category | 42 | # view the summary of one category |
43 | def category_index | 43 | def category_index |
44 | @searches = {} | 44 | @searches = {} |
45 | - @order = [] | 45 | + @assets = [] |
46 | @names = {} | 46 | @names = {} |
47 | limit = MULTIPLE_SEARCH_LIMIT | 47 | limit = MULTIPLE_SEARCH_LIMIT |
48 | [ | 48 | [ |
@@ -53,7 +53,7 @@ class SearchController < PublicController | @@ -53,7 +53,7 @@ class SearchController < PublicController | ||
53 | [ :communities, _('Communities'), :recent_communities ], | 53 | [ :communities, _('Communities'), :recent_communities ], |
54 | [ :articles, _('Contents'), :recent_articles ] | 54 | [ :articles, _('Contents'), :recent_articles ] |
55 | ].each do |asset, name, filter| | 55 | ].each do |asset, name, filter| |
56 | - @order << asset | 56 | + @assets << asset |
57 | @searches[asset]= {:results => @category.send(filter, limit)} | 57 | @searches[asset]= {:results => @category.send(filter, limit)} |
58 | raise "No total_entries for: #{asset}" unless @searches[asset][:results].respond_to?(:total_entries) | 58 | raise "No total_entries for: #{asset}" unless @searches[asset][:results].respond_to?(:total_entries) |
59 | @names[asset] = name | 59 | @names[asset] = name |
@@ -147,12 +147,16 @@ class SearchController < PublicController | @@ -147,12 +147,16 @@ class SearchController < PublicController | ||
147 | render :partial => 'events/events' | 147 | render :partial => 'events/events' |
148 | end | 148 | end |
149 | 149 | ||
150 | + def suggestions | ||
151 | + render :text => find_suggestions(normalize_term(params[:term]), environment, params[:asset]).to_json | ||
152 | + end | ||
153 | + | ||
150 | ####################################################### | 154 | ####################################################### |
151 | protected | 155 | protected |
152 | 156 | ||
153 | def load_query | 157 | def load_query |
154 | @asset = (params[:asset] || params[:action]).to_sym | 158 | @asset = (params[:asset] || params[:action]).to_sym |
155 | - @order ||= [@asset] | 159 | + @assets ||= [@asset] |
156 | @searches ||= {} | 160 | @searches ||= {} |
157 | 161 | ||
158 | @query = params[:query] || '' | 162 | @query = params[:query] || '' |
@@ -173,13 +177,22 @@ class SearchController < PublicController | @@ -173,13 +177,22 @@ class SearchController < PublicController | ||
173 | end | 177 | end |
174 | end | 178 | end |
175 | 179 | ||
180 | + AVAILABLE_SEARCHES = ActiveSupport::OrderedHash[ | ||
181 | + :articles, _('Contents'), | ||
182 | + :people, _('People'), | ||
183 | + :communities, _('Communities'), | ||
184 | + :enterprises, _('Enterprises'), | ||
185 | + :products, _('Products and Services'), | ||
186 | + :events, _('Events'), | ||
187 | + ] | ||
188 | + | ||
176 | def load_search_assets | 189 | def load_search_assets |
177 | - if SEARCHES.keys.include?(params[:action].to_sym) && environment.enabled?("disable_asset_#{params[:action]}") | 190 | + if AVAILABLE_SEARCHES.keys.include?(params[:action].to_sym) && environment.enabled?("disable_asset_#{params[:action]}") |
178 | render_not_found | 191 | render_not_found |
179 | return | 192 | return |
180 | end | 193 | end |
181 | 194 | ||
182 | - @enabled_searches = SEARCHES.select {|key, name| environment.disabled?("disable_asset_#{key}") } | 195 | + @enabled_searches = AVAILABLE_SEARCHES.select {|key, name| environment.disabled?("disable_asset_#{key}") } |
183 | @searching = {} | 196 | @searching = {} |
184 | @titles = {} | 197 | @titles = {} |
185 | @enabled_searches.each do |key, name| | 198 | @enabled_searches.each do |key, name| |
@@ -189,11 +202,11 @@ class SearchController < PublicController | @@ -189,11 +202,11 @@ class SearchController < PublicController | ||
189 | @names = @titles if @names.nil? | 202 | @names = @titles if @names.nil? |
190 | end | 203 | end |
191 | 204 | ||
192 | - def load_filter | ||
193 | - @filter = 'more_recent' | ||
194 | - if SEARCHES.keys.include?(@asset.to_sym) | ||
195 | - available_filters = asset_class(@asset)::SEARCH_FILTERS | ||
196 | - @filter = params[:filter] if available_filters.include?(params[:filter]) | 205 | + def load_order |
206 | + @order = 'more_recent' | ||
207 | + if AVAILABLE_SEARCHES.keys.include?(@asset.to_sym) | ||
208 | + available_orders = asset_class(@asset)::SEARCH_FILTERS[:order] | ||
209 | + @order = params[:order] if available_orders.include?(params[:order]) | ||
197 | end | 210 | end |
198 | end | 211 | end |
199 | 212 | ||
@@ -217,7 +230,7 @@ class SearchController < PublicController | @@ -217,7 +230,7 @@ class SearchController < PublicController | ||
217 | end | 230 | end |
218 | 231 | ||
219 | def full_text_search | 232 | def full_text_search |
220 | - @searches[@asset] = find_by_contents(@asset, @scope, @query, paginate_options, {:category => @category, :filter => @filter}) | 233 | + @searches[@asset] = find_by_contents(@asset, environment, @scope, @query, paginate_options, {:category => @category, :filter => @order}) |
221 | end | 234 | end |
222 | 235 | ||
223 | private | 236 | private |
@@ -232,4 +245,14 @@ class SearchController < PublicController | @@ -232,4 +245,14 @@ class SearchController < PublicController | ||
232 | 20 | 245 | 20 |
233 | end | 246 | end |
234 | 247 | ||
248 | + def available_assets | ||
249 | + assets = ActiveSupport::OrderedHash[ | ||
250 | + :articles, _('Contents'), | ||
251 | + :enterprises, _('Enterprises'), | ||
252 | + :people, _('People'), | ||
253 | + :communities, _('Communities'), | ||
254 | + :products, _('Products and Services'), | ||
255 | + ] | ||
256 | + end | ||
257 | + | ||
235 | end | 258 | end |
app/helpers/application_helper.rb
@@ -1307,8 +1307,19 @@ module ApplicationHelper | @@ -1307,8 +1307,19 @@ module ApplicationHelper | ||
1307 | end | 1307 | end |
1308 | end | 1308 | end |
1309 | 1309 | ||
1310 | - def remove_content_button(action) | ||
1311 | - @plugins.dispatch("content_remove_#{action.to_s}", @page).include?(true) | 1310 | + def content_remove_spread(content) |
1311 | + !content.public? || content.folder? || (profile == user && user.communities.blank? && !environment.portal_enabled) | ||
1312 | + end | ||
1313 | + | ||
1314 | + def remove_content_button(action, content) | ||
1315 | + method_name = "content_remove_#{action.to_s}" | ||
1316 | + plugin_condition = @plugins.dispatch(method_name, content).include?(true) | ||
1317 | + begin | ||
1318 | + core_condition = self.send(method_name, content) | ||
1319 | + rescue NoMethodError | ||
1320 | + core_condition = false | ||
1321 | + end | ||
1322 | + core_condition || plugin_condition | ||
1312 | end | 1323 | end |
1313 | 1324 | ||
1314 | def template_options(kind, field_name) | 1325 | def template_options(kind, field_name) |
@@ -1411,6 +1422,43 @@ module ApplicationHelper | @@ -1411,6 +1422,43 @@ module ApplicationHelper | ||
1411 | content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))}) | 1422 | content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))}) |
1412 | end | 1423 | end |
1413 | 1424 | ||
1425 | + def search_input_with_suggestions(name, asset, default, options = {}) | ||
1426 | + text_field_tag name, default, options.merge({:class => 'search-input-with-suggestions', 'data-asset' => asset}) | ||
1427 | + end | ||
1428 | + | ||
1429 | + def profile_suggestion_profile_connections(suggestion) | ||
1430 | + profiles = suggestion.profile_connections.first(4).map do |profile| | ||
1431 | + link_to(profile_image(profile, :icon, :title => profile.name), profile.url, :class => 'profile-suggestion-connection-icon') | ||
1432 | + end | ||
1433 | + | ||
1434 | + controller_target = suggestion.suggestion_type == 'Person' ? :friends : :memberships | ||
1435 | + profiles << link_to("<big> +#{suggestion.profile_connections.count - 4}</big>", :controller => controller_target, :action => :connections, :id => suggestion.suggestion_id) if suggestion.profile_connections.count > 4 | ||
1436 | + | ||
1437 | + if profiles.present? | ||
1438 | + content_tag(:div, profiles.join , :class => 'profile-connections') | ||
1439 | + else | ||
1440 | + '' | ||
1441 | + end | ||
1442 | + end | ||
1443 | + | ||
1444 | + def profile_suggestion_tag_connections(suggestion) | ||
1445 | + tags = suggestion.tag_connections.first(4).map do |tag| | ||
1446 | + tag.name + ', ' | ||
1447 | + end | ||
1448 | + last_tag = tags.pop | ||
1449 | + tags << last_tag.strip.chop if last_tag.present? | ||
1450 | + title = tags.join | ||
1451 | + | ||
1452 | + controller_target = suggestion.suggestion_type == 'Person' ? :friends : :memberships | ||
1453 | + tags << ' ' + link_to('...', {:controller => controller_target, :action => :connections, :id => suggestion.suggestion_id}, :class => 'more-tag-connections', :title => _('See all connections')) if suggestion.tag_connections.count > 4 | ||
1454 | + | ||
1455 | + if tags.present? | ||
1456 | + content_tag(:div, tags.join, :class => 'tag-connections', :title => title) | ||
1457 | + else | ||
1458 | + '' | ||
1459 | + end | ||
1460 | + end | ||
1461 | + | ||
1414 | def labelled_colorpicker_field(human_name, object_name, method, options = {}) | 1462 | def labelled_colorpicker_field(human_name, object_name, method, options = {}) |
1415 | options[:id] ||= 'text-field-' + FormsHelper.next_id_number | 1463 | options[:id] ||= 'text-field-' + FormsHelper.next_id_number |
1416 | content_tag('label', human_name, :for => options[:id], :class => 'formlabel') + | 1464 | content_tag('label', human_name, :for => options[:id], :class => 'formlabel') + |
app/helpers/cms_helper.rb
@@ -40,12 +40,8 @@ module CmsHelper | @@ -40,12 +40,8 @@ module CmsHelper | ||
40 | end | 40 | end |
41 | end | 41 | end |
42 | 42 | ||
43 | - def display_spread_button(profile, article) | ||
44 | - if profile.person? | ||
45 | - expirable_button article, :spread, _('Spread this'), :action => 'publish', :id => article.id | ||
46 | - elsif profile.community? && environment.portal_community | ||
47 | - expirable_button article, :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id | ||
48 | - end | 43 | + def display_spread_button(article) |
44 | + expirable_button article, :spread, _('Spread this'), {:action => 'publish', :id => article.id}, {:class => 'colorbox'} | ||
49 | end | 45 | end |
50 | 46 | ||
51 | def display_delete_button(article) | 47 | def display_delete_button(article) |
app/helpers/forms_helper.rb
@@ -265,7 +265,7 @@ module FormsHelper | @@ -265,7 +265,7 @@ module FormsHelper | ||
265 | ) | 265 | ) |
266 | end | 266 | end |
267 | 267 | ||
268 | - def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}, find_options = {}) | 268 | + def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}, find_options = {}, extra_options = {}) |
269 | if find_options.empty? | 269 | if find_options.empty? |
270 | folders = profile.folders | 270 | folders = profile.folders |
271 | else | 271 | else |
@@ -276,7 +276,7 @@ module FormsHelper | @@ -276,7 +276,7 @@ module FormsHelper | ||
276 | select_tag( | 276 | select_tag( |
277 | field_id, | 277 | field_id, |
278 | options_for_select( | 278 | options_for_select( |
279 | - [[profile.identifier, '']] + | 279 | + [[(extra_options[:root_label] || profile.identifier), '']] + |
280 | folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id.to_s ] }, | 280 | folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id.to_s ] }, |
281 | default_value.to_s | 281 | default_value.to_s |
282 | ), | 282 | ), |
app/helpers/layout_helper.rb
app/helpers/search_helper.rb
@@ -5,20 +5,23 @@ module SearchHelper | @@ -5,20 +5,23 @@ module SearchHelper | ||
5 | BLOCKS_SEARCH_LIMIT = 24 | 5 | BLOCKS_SEARCH_LIMIT = 24 |
6 | MULTIPLE_SEARCH_LIMIT = 8 | 6 | MULTIPLE_SEARCH_LIMIT = 8 |
7 | 7 | ||
8 | - SEARCHES = ActiveSupport::OrderedHash[ | ||
9 | - :articles, _('Contents'), | ||
10 | - :enterprises, _('Enterprises'), | ||
11 | - :people, _('People'), | ||
12 | - :communities, _('Communities'), | ||
13 | - :products, _('Products and Services'), | ||
14 | - :events, _('Events'), | ||
15 | - ] | 8 | + FILTERS_TRANSLATIONS = { |
9 | + :order => _('Order'), | ||
10 | + :display => _('Display') | ||
11 | + } | ||
16 | 12 | ||
17 | - FILTER_TRANSLATION = { | ||
18 | - 'more_popular' => _('More popular'), | ||
19 | - 'more_active' => _('More active'), | ||
20 | - 'more_recent' => _('More recent'), | ||
21 | - 'more_comments' => _('More comments') | 13 | + FILTERS_OPTIONS_TRANSLATION = { |
14 | + :order => { | ||
15 | + 'more_popular' => _('More popular'), | ||
16 | + 'more_active' => _('More active'), | ||
17 | + 'more_recent' => _('More recent'), | ||
18 | + 'more_comments' => _('More comments') | ||
19 | + }, | ||
20 | + :display => { | ||
21 | + 'map' => _('Map'), | ||
22 | + 'full' => _('Full'), | ||
23 | + 'compact' => _('Compact') | ||
24 | + } | ||
22 | } | 25 | } |
23 | 26 | ||
24 | COMMON_PROFILE_LIST_BLOCK = [ | 27 | COMMON_PROFILE_LIST_BLOCK = [ |
@@ -56,7 +59,7 @@ module SearchHelper | @@ -56,7 +59,7 @@ module SearchHelper | ||
56 | end | 59 | end |
57 | 60 | ||
58 | def display?(asset, mode) | 61 | def display?(asset, mode) |
59 | - defined?(asset_class(asset)::SEARCH_DISPLAYS) && asset_class(asset)::SEARCH_DISPLAYS.include?(mode.to_s) | 62 | + defined?(asset_class(asset)::SEARCH_FILTERS[:display]) && asset_class(asset)::SEARCH_FILTERS[:display].include?(mode.to_s) |
60 | end | 63 | end |
61 | 64 | ||
62 | def display_results(searches=nil, asset=nil) | 65 | def display_results(searches=nil, asset=nil) |
@@ -93,6 +96,16 @@ module SearchHelper | @@ -93,6 +96,16 @@ module SearchHelper | ||
93 | end | 96 | end |
94 | end | 97 | end |
95 | 98 | ||
99 | + def select_filter(name, options, default = nil) | ||
100 | + if options.size <= 1 | ||
101 | + return | ||
102 | + else | ||
103 | + options = options.map {|option| [FILTERS_OPTIONS_TRANSLATION[name][option], option]} | ||
104 | + options = options_for_select(options, :selected => (params[name] || default)) | ||
105 | + select_tag(name, options) | ||
106 | + end | ||
107 | + end | ||
108 | + | ||
96 | def display_selector(asset, display, float = 'right') | 109 | def display_selector(asset, display, float = 'right') |
97 | display = nil if display.blank? | 110 | display = nil if display.blank? |
98 | display ||= asset_class(asset).default_search_display | 111 | display ||= asset_class(asset).default_search_display |
@@ -107,36 +120,32 @@ module SearchHelper | @@ -107,36 +120,32 @@ module SearchHelper | ||
107 | end | 120 | end |
108 | end | 121 | end |
109 | 122 | ||
110 | - def filter_selector(asset, filter, float = 'right') | 123 | + def filters(asset) |
124 | + return if !asset | ||
111 | klass = asset_class(asset) | 125 | klass = asset_class(asset) |
112 | - if klass::SEARCH_FILTERS.count > 1 | ||
113 | - options = options_for_select(klass::SEARCH_FILTERS.map {|f| [FILTER_TRANSLATION[f], f]}, filter) | ||
114 | - url_params = url_for(params.merge(:filter => 'FILTER')) | ||
115 | - onchange = "document.location.href = '#{url_params}'.replace('FILTER', this.value)" | ||
116 | - select_field = select_tag(:filter, options, :onchange => onchange) | ||
117 | - content_tag('div', | ||
118 | - content_tag('strong', _('Filter')) + ': ' + select_field, | ||
119 | - :class => "search-customize-options" | ||
120 | - ) | ||
121 | - end | 126 | + content_tag('div', klass::SEARCH_FILTERS.map do |name, options| |
127 | + default = klass.respond_to?("default_search_#{name}") ? klass.send("default_search_#{name}".to_s) : nil | ||
128 | + select_filter(name, options, default) | ||
129 | + end.join("\n"), :id => 'search-filters') | ||
130 | + end | ||
131 | + | ||
132 | + def assets_menu(selected) | ||
133 | + assets = @enabled_searches.keys | ||
134 | + # Events is a search asset but do not have a good interface for | ||
135 | + #TODO searching. When this is solved we may add it back again to the assets | ||
136 | + # menu. | ||
137 | + assets.delete(:events) | ||
138 | + content_tag('ul', | ||
139 | + assets.map do |asset| | ||
140 | + options = {} | ||
141 | + options.merge!(:class => 'selected') if selected.to_s == asset.to_s | ||
142 | + content_tag('li', asset_link(asset), options) | ||
143 | + end.join("\n"), | ||
144 | + :id => 'assets-menu') | ||
122 | end | 145 | end |
123 | 146 | ||
124 | - def filter_title(asset, filter) | ||
125 | - { | ||
126 | - 'articles_more_recent' => _('More recent contents from network'), | ||
127 | - 'articles_more_popular' => _('More viewed contents from network'), | ||
128 | - 'articles_more_comments' => _('Most commented contents from network'), | ||
129 | - 'people_more_recent' => _('More recent people from network'), | ||
130 | - 'people_more_active' => _('More active people from network'), | ||
131 | - 'people_more_popular' => _('More popular people from network'), | ||
132 | - 'communities_more_recent' => _('More recent communities from network'), | ||
133 | - 'communities_more_active' => _('More active communities from network'), | ||
134 | - 'communities_more_popular' => _('More popular communities from network'), | ||
135 | - 'enterprises_more_recent' => _('More recent enterprises from network'), | ||
136 | - 'enterprises_more_active' => _('More active enterprises from network'), | ||
137 | - 'enterprises_more_popular' => _('More popular enterprises from network'), | ||
138 | - 'products_more_recent' => _('Highlights'), | ||
139 | - }[asset.to_s + '_' + filter].to_s | 147 | + def asset_link(asset) |
148 | + link_to(@enabled_searches[asset], "/search/#{asset}") | ||
140 | end | 149 | end |
141 | 150 | ||
142 | end | 151 | end |
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | +module SearchTermHelper | ||
2 | + def register_search_term(term, total, indexed, context, asset='all') | ||
3 | + normalized_term = normalize_term(term) | ||
4 | + if normalized_term.present? | ||
5 | + search_term = SearchTerm.find_or_create(normalized_term, context, asset) | ||
6 | + SearchTermOccurrence.create!(:search_term => search_term, :total => total, :indexed => indexed) | ||
7 | + end | ||
8 | + end | ||
9 | + | ||
10 | + #FIXME For some reason the job is created but nothing is ran. | ||
11 | + #handle_asynchronously :register_search_term | ||
12 | + | ||
13 | + #TODO Think smarter criteria to normalize search terms properly | ||
14 | + def normalize_term(search_term) | ||
15 | + search_term ||= '' | ||
16 | + search_term.downcase | ||
17 | + end | ||
18 | +end |
app/helpers/token_helper.rb
@@ -12,6 +12,7 @@ module TokenHelper | @@ -12,6 +12,7 @@ module TokenHelper | ||
12 | options[:search_delay] ||= 1000 | 12 | options[:search_delay] ||= 1000 |
13 | options[:prevent_duplicates] ||= true | 13 | options[:prevent_duplicates] ||= true |
14 | options[:backspace_delete_item] ||= false | 14 | options[:backspace_delete_item] ||= false |
15 | + options[:zindex] ||= 999 | ||
15 | options[:focus] ||= false | 16 | options[:focus] ||= false |
16 | options[:avoid_enter] ||= true | 17 | options[:avoid_enter] ||= true |
17 | options[:on_result] ||= 'null' | 18 | options[:on_result] ||= 'null' |
@@ -31,6 +32,7 @@ module TokenHelper | @@ -31,6 +32,7 @@ module TokenHelper | ||
31 | searchDelay: #{options[:search_delay].to_json}, | 32 | searchDelay: #{options[:search_delay].to_json}, |
32 | preventDuplicates: #{options[:prevent_duplicates].to_json}, | 33 | preventDuplicates: #{options[:prevent_duplicates].to_json}, |
33 | backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, | 34 | backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, |
35 | + zindex: #{options[:zindex].to_json}, | ||
34 | queryParam: #{options[:query_param].to_json}, | 36 | queryParam: #{options[:query_param].to_json}, |
35 | tokenLimit: #{options[:token_limit].to_json}, | 37 | tokenLimit: #{options[:token_limit].to_json}, |
36 | onResult: #{options[:on_result]}, | 38 | onResult: #{options[:on_result]}, |
app/mailers/user_mailer.rb
@@ -41,6 +41,23 @@ class UserMailer < ActionMailer::Base | @@ -41,6 +41,23 @@ class UserMailer < ActionMailer::Base | ||
41 | ) | 41 | ) |
42 | end | 42 | end |
43 | 43 | ||
44 | + def profiles_suggestions_email(user) | ||
45 | + @recipient = user.name | ||
46 | + @environment = user.environment.name | ||
47 | + @url = user.environment.top_url | ||
48 | + @people_suggestions_url = user.people_suggestions_url | ||
49 | + @people_suggestions = user.suggested_people.sample(3) | ||
50 | + @communities_suggestions_url = user.communities_suggestions_url | ||
51 | + @communities_suggestions = user.suggested_communities.sample(3) | ||
52 | + | ||
53 | + mail( | ||
54 | + content_type: 'text/html', | ||
55 | + to: user.email, | ||
56 | + from: "#{user.environment.name} <#{user.environment.contact_email}>", | ||
57 | + subject: _("[%s] What about grow up your network?") % user.environment.name | ||
58 | + ) | ||
59 | + end | ||
60 | + | ||
44 | class Job < Struct.new(:user, :method) | 61 | class Job < Struct.new(:user, :method) |
45 | def perform | 62 | def perform |
46 | UserMailer.send(method, user).deliver | 63 | UserMailer.send(method, user).deliver |
app/models/add_friend.rb
@@ -14,6 +14,11 @@ class AddFriend < Task | @@ -14,6 +14,11 @@ class AddFriend < Task | ||
14 | alias :friend :target | 14 | alias :friend :target |
15 | alias :friend= :target= | 15 | alias :friend= :target= |
16 | 16 | ||
17 | + after_create do |task| | ||
18 | + TaskMailer.invitation_notification(task).deliver unless task.friend | ||
19 | + remove_from_suggestion_list(task) | ||
20 | + end | ||
21 | + | ||
17 | def perform | 22 | def perform |
18 | target.add_friend(requestor, group_for_friend) | 23 | target.add_friend(requestor, group_for_friend) |
19 | requestor.add_friend(target, group_for_person) | 24 | requestor.add_friend(target, group_for_person) |
@@ -48,4 +53,8 @@ class AddFriend < Task | @@ -48,4 +53,8 @@ class AddFriend < Task | ||
48 | {:type => :profile_image, :profile => requestor, :url => requestor.url} | 53 | {:type => :profile_image, :profile => requestor, :url => requestor.url} |
49 | end | 54 | end |
50 | 55 | ||
56 | + def remove_from_suggestion_list(task) | ||
57 | + suggestion = task.requestor.profile_suggestions.find_by_suggestion_id task.target.id | ||
58 | + suggestion.disable if suggestion | ||
59 | + end | ||
51 | end | 60 | end |
app/models/add_member.rb
@@ -10,6 +10,10 @@ class AddMember < Task | @@ -10,6 +10,10 @@ class AddMember < Task | ||
10 | 10 | ||
11 | settings_items :roles | 11 | settings_items :roles |
12 | 12 | ||
13 | + after_create do |task| | ||
14 | + remove_from_suggestion_list(task) | ||
15 | + end | ||
16 | + | ||
13 | def perform | 17 | def perform |
14 | if !self.roles or (self.roles.uniq.compact.length == 1 and self.roles.uniq.compact.first.to_i.zero?) | 18 | if !self.roles or (self.roles.uniq.compact.length == 1 and self.roles.uniq.compact.first.to_i.zero?) |
15 | self.roles = [Profile::Roles.member(organization.environment.id).id] | 19 | self.roles = [Profile::Roles.member(organization.environment.id).id] |
@@ -46,4 +50,9 @@ class AddMember < Task | @@ -46,4 +50,9 @@ class AddMember < Task | ||
46 | _('You will need login to %{system} in order to accept or reject %{requestor} as a member of %{organization}.') % { :system => target.environment.name, :requestor => requestor.name, :organization => organization.name } | 50 | _('You will need login to %{system} in order to accept or reject %{requestor} as a member of %{organization}.') % { :system => target.environment.name, :requestor => requestor.name, :organization => organization.name } |
47 | end | 51 | end |
48 | 52 | ||
53 | + def remove_from_suggestion_list(task) | ||
54 | + suggestion = task.requestor.profile_suggestions.find_by_suggestion_id task.target.id | ||
55 | + suggestion.disable if suggestion | ||
56 | + end | ||
57 | + | ||
49 | end | 58 | end |
app/models/article.rb
@@ -14,20 +14,17 @@ class Article < ActiveRecord::Base | @@ -14,20 +14,17 @@ class Article < ActiveRecord::Base | ||
14 | acts_as_having_image | 14 | acts_as_having_image |
15 | 15 | ||
16 | SEARCHABLE_FIELDS = { | 16 | SEARCHABLE_FIELDS = { |
17 | - :name => 10, | ||
18 | - :abstract => 3, | ||
19 | - :body => 2, | ||
20 | - :slug => 1, | ||
21 | - :filename => 1, | 17 | + :name => {:label => _('Name'), :weight => 10}, |
18 | + :abstract => {:label => _('Abstract'), :weight => 3}, | ||
19 | + :body => {:label => _('Content'), :weight => 2}, | ||
20 | + :slug => {:label => _('Slug'), :weight => 1}, | ||
21 | + :filename => {:label => _('Filename'), :weight => 1}, | ||
22 | } | 22 | } |
23 | 23 | ||
24 | - SEARCH_FILTERS = %w[ | ||
25 | - more_recent | ||
26 | - more_popular | ||
27 | - more_comments | ||
28 | - ] | ||
29 | - | ||
30 | - SEARCH_DISPLAYS = %w[full] | 24 | + SEARCH_FILTERS = { |
25 | + :order => %w[more_recent more_popular more_comments], | ||
26 | + :display => %w[full] | ||
27 | + } | ||
31 | 28 | ||
32 | def self.default_search_display | 29 | def self.default_search_display |
33 | 'full' | 30 | 'full' |
@@ -477,7 +474,9 @@ class Article < ActiveRecord::Base | @@ -477,7 +474,9 @@ class Article < ActiveRecord::Base | ||
477 | scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}} | 474 | scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}} |
478 | scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ] | 475 | scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ] |
479 | scope :images, :conditions => { :is_image => true } | 476 | scope :images, :conditions => { :is_image => true } |
477 | + scope :no_images, :conditions => { :is_image => false } | ||
480 | scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] | 478 | scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] |
479 | + scope :files, :conditions => { :type => 'UploadedFile' } | ||
481 | scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } } | 480 | scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } } |
482 | 481 | ||
483 | scope :more_popular, :order => 'hits DESC' | 482 | scope :more_popular, :order => 'hits DESC' |
@@ -528,7 +527,10 @@ class Article < ActiveRecord::Base | @@ -528,7 +527,10 @@ class Article < ActiveRecord::Base | ||
528 | end | 527 | end |
529 | 528 | ||
530 | alias :allow_delete? :allow_post_content? | 529 | alias :allow_delete? :allow_post_content? |
531 | - alias :allow_spread? :allow_post_content? | 530 | + |
531 | + def allow_spread?(user = nil) | ||
532 | + user && public? | ||
533 | + end | ||
532 | 534 | ||
533 | def allow_create?(user) | 535 | def allow_create?(user) |
534 | allow_post_content?(user) || allow_publish_content?(user) | 536 | allow_post_content?(user) || allow_publish_content?(user) |
app/models/category.rb
@@ -3,10 +3,10 @@ class Category < ActiveRecord::Base | @@ -3,10 +3,10 @@ class Category < ActiveRecord::Base | ||
3 | attr_accessible :name, :parent_id, :display_color, :display_in_menu, :image_builder, :environment, :parent | 3 | attr_accessible :name, :parent_id, :display_color, :display_in_menu, :image_builder, :environment, :parent |
4 | 4 | ||
5 | SEARCHABLE_FIELDS = { | 5 | SEARCHABLE_FIELDS = { |
6 | - :name => 10, | ||
7 | - :acronym => 5, | ||
8 | - :abbreviation => 5, | ||
9 | - :slug => 1, | 6 | + :name => {:label => _('Name'), :weight => 10}, |
7 | + :acronym => {:label => _('Acronym'), :weight => 5}, | ||
8 | + :abbreviation => {:label => _('Abbreviation'), :weight => 5}, | ||
9 | + :slug => {:label => _('Slug'), :weight => 1}, | ||
10 | } | 10 | } |
11 | 11 | ||
12 | validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('{fn} cannot be like that.').fix_i18n | 12 | validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('{fn} cannot be like that.').fix_i18n |
app/models/certifier.rb
@@ -3,9 +3,9 @@ class Certifier < ActiveRecord::Base | @@ -3,9 +3,9 @@ class Certifier < ActiveRecord::Base | ||
3 | attr_accessible :name, :environment | 3 | attr_accessible :name, :environment |
4 | 4 | ||
5 | SEARCHABLE_FIELDS = { | 5 | SEARCHABLE_FIELDS = { |
6 | - :name => 10, | ||
7 | - :description => 3, | ||
8 | - :link => 1, | 6 | + :name => {:label => _('Name'), :weight => 10}, |
7 | + :description => {:label => _('Description'), :weight => 3}, | ||
8 | + :link => {:label => _('Link'), :weight => 1}, | ||
9 | } | 9 | } |
10 | 10 | ||
11 | belongs_to :environment | 11 | belongs_to :environment |
app/models/comment.rb
1 | class Comment < ActiveRecord::Base | 1 | class Comment < ActiveRecord::Base |
2 | 2 | ||
3 | SEARCHABLE_FIELDS = { | 3 | SEARCHABLE_FIELDS = { |
4 | - :title => 10, | ||
5 | - :name => 4, | ||
6 | - :body => 2, | 4 | + :title => {:label => _('Title'), :weight => 10}, |
5 | + :name => {:label => _('Name'), :weight => 4}, | ||
6 | + :body => {:label => _('Content'), :weight => 2}, | ||
7 | } | 7 | } |
8 | 8 | ||
9 | attr_accessible :body, :author, :name, :email, :title, :reply_of_id, :source | 9 | attr_accessible :body, :author, :name, :email, :title, :reply_of_id, :source |
app/models/communities_block.rb
@@ -14,19 +14,17 @@ class CommunitiesBlock < ProfileListBlock | @@ -14,19 +14,17 @@ class CommunitiesBlock < ProfileListBlock | ||
14 | _('This block displays the communities in which the user is a member.') | 14 | _('This block displays the communities in which the user is a member.') |
15 | end | 15 | end |
16 | 16 | ||
17 | + def suggestions | ||
18 | + return nil unless owner.kind_of?(Profile) | ||
19 | + owner.profile_suggestions.of_community.enabled.limit(3).includes(:suggestion) | ||
20 | + end | ||
21 | + | ||
17 | def footer | 22 | def footer |
18 | owner = self.owner | 23 | owner = self.owner |
19 | - case owner | ||
20 | - when Profile | ||
21 | - lambda do |context| | ||
22 | - link_to s_('communities|View all'), :profile => owner.identifier, :controller => 'profile', :action => 'communities' | ||
23 | - end | ||
24 | - when Environment | ||
25 | - lambda do |context| | ||
26 | - link_to s_('communities|View all'), :controller => 'search', :action => 'communities' | ||
27 | - end | ||
28 | - else | ||
29 | - '' | 24 | + suggestions = self.suggestions |
25 | + return '' unless owner.kind_of?(Profile) || owner.kind_of?(Environment) | ||
26 | + proc do | ||
27 | + render :file => 'blocks/communities', :locals => { :owner => owner, :suggestions => suggestions } | ||
30 | end | 28 | end |
31 | end | 29 | end |
32 | 30 |
app/models/create_enterprise.rb
@@ -73,7 +73,13 @@ class CreateEnterprise < Task | @@ -73,7 +73,13 @@ class CreateEnterprise < Task | ||
73 | 73 | ||
74 | # sets the associated region for the enterprise creation | 74 | # sets the associated region for the enterprise creation |
75 | def region=(value) | 75 | def region=(value) |
76 | - raise ArgumentError.new("Region expected, but got #{value.class}") unless value.kind_of?(Region) | 76 | + unless value.kind_of?(Region) |
77 | + begin | ||
78 | + value = Region.find(value) | ||
79 | + rescue | ||
80 | + raise ArgumentError.new("Could not find any region with the id #{value}") | ||
81 | + end | ||
82 | + end | ||
77 | 83 | ||
78 | @region = value | 84 | @region = value |
79 | self.region_id = value.id | 85 | self.region_id = value.id |
app/models/enterprise.rb
@@ -4,7 +4,10 @@ class Enterprise < Organization | @@ -4,7 +4,10 @@ class Enterprise < Organization | ||
4 | 4 | ||
5 | attr_accessible :business_name, :address_reference, :district, :tag_list, :organization_website, :historic_and_current_context, :activities_short_description, :products_per_catalog_page | 5 | attr_accessible :business_name, :address_reference, :district, :tag_list, :organization_website, :historic_and_current_context, :activities_short_description, :products_per_catalog_page |
6 | 6 | ||
7 | - SEARCH_DISPLAYS += %w[map full] | 7 | + SEARCH_FILTERS = { |
8 | + :order => %w[more_recent more_popular more_active], | ||
9 | + :display => %w[compact full map] | ||
10 | + } | ||
8 | 11 | ||
9 | def self.type_name | 12 | def self.type_name |
10 | _('Enterprise') | 13 | _('Enterprise') |
app/models/environment.rb
@@ -10,6 +10,7 @@ class Environment < ActiveRecord::Base | @@ -10,6 +10,7 @@ class Environment < ActiveRecord::Base | ||
10 | self.partial_updates = false | 10 | self.partial_updates = false |
11 | 11 | ||
12 | has_many :tasks, :dependent => :destroy, :as => 'target' | 12 | has_many :tasks, :dependent => :destroy, :as => 'target' |
13 | + has_many :search_terms, :as => :context | ||
13 | 14 | ||
14 | IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ | 15 | IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ |
15 | 16 | ||
@@ -85,7 +86,9 @@ class Environment < ActiveRecord::Base | @@ -85,7 +86,9 @@ class Environment < ActiveRecord::Base | ||
85 | end | 86 | end |
86 | 87 | ||
87 | def admins | 88 | def admins |
88 | - Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', Environment::Roles.admin(self).id]) | 89 | + admin_role = Environment::Roles.admin(self) |
90 | + return [] if admin_role.blank? | ||
91 | + Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', admin_role.id]) | ||
89 | end | 92 | end |
90 | 93 | ||
91 | # returns the available features for a Environment, in the form of a | 94 | # returns the available features for a Environment, in the form of a |
@@ -155,7 +158,8 @@ class Environment < ActiveRecord::Base | @@ -155,7 +158,8 @@ class Environment < ActiveRecord::Base | ||
155 | 'site_homepage' => _('Redirects the user to the environment homepage.'), | 158 | 'site_homepage' => _('Redirects the user to the environment homepage.'), |
156 | 'user_profile_page' => _('Redirects the user to his profile page.'), | 159 | 'user_profile_page' => _('Redirects the user to his profile page.'), |
157 | 'user_homepage' => _('Redirects the user to his homepage.'), | 160 | 'user_homepage' => _('Redirects the user to his homepage.'), |
158 | - 'user_control_panel' => _('Redirects the user to his control panel.') | 161 | + 'user_control_panel' => _('Redirects the user to his control panel.'), |
162 | + 'welcome_page' => _('Redirects the user to the environment welcome page.') | ||
159 | } | 163 | } |
160 | end | 164 | end |
161 | validates_inclusion_of :redirection_after_signup, :in => Environment.signup_redirection_options.keys, :allow_nil => true | 165 | validates_inclusion_of :redirection_after_signup, :in => Environment.signup_redirection_options.keys, :allow_nil => true |
@@ -824,6 +828,10 @@ class Environment < ActiveRecord::Base | @@ -824,6 +828,10 @@ class Environment < ActiveRecord::Base | ||
824 | "home-page-news/#{cache_key}-#{language}" | 828 | "home-page-news/#{cache_key}-#{language}" |
825 | end | 829 | end |
826 | 830 | ||
831 | + def portal_enabled | ||
832 | + portal_community && enabled?('use_portal_community') | ||
833 | + end | ||
834 | + | ||
827 | def notification_emails | 835 | def notification_emails |
828 | [contact_email].select(&:present?) + admins.map(&:email) | 836 | [contact_email].select(&:present?) + admins.map(&:email) |
829 | end | 837 | end |
app/models/invitation.rb
@@ -51,7 +51,10 @@ class Invitation < Task | @@ -51,7 +51,10 @@ class Invitation < Task | ||
51 | next if contact_to_invite == _("Firstname Lastname <friend@email.com>") | 51 | next if contact_to_invite == _("Firstname Lastname <friend@email.com>") |
52 | 52 | ||
53 | contact_to_invite.strip! | 53 | contact_to_invite.strip! |
54 | - if match = contact_to_invite.match(/(.*)<(.*)>/) and match[2].match(Noosfero::Constants::EMAIL_FORMAT) | 54 | + find_by_profile_id = false |
55 | + if contact_to_invite.match(/^\d*$/) | ||
56 | + find_by_profile_id = true | ||
57 | + elsif match = contact_to_invite.match(/(.*)<(.*)>/) and match[2].match(Noosfero::Constants::EMAIL_FORMAT) | ||
55 | friend_name = match[1].strip | 58 | friend_name = match[1].strip |
56 | friend_email = match[2] | 59 | friend_email = match[2] |
57 | elsif match = contact_to_invite.strip.match(Noosfero::Constants::EMAIL_FORMAT) | 60 | elsif match = contact_to_invite.strip.match(Noosfero::Constants::EMAIL_FORMAT) |
@@ -61,11 +64,15 @@ class Invitation < Task | @@ -61,11 +64,15 @@ class Invitation < Task | ||
61 | next | 64 | next |
62 | end | 65 | end |
63 | 66 | ||
64 | - user = User.find_by_email(friend_email) | 67 | + begin |
68 | + user = find_by_profile_id ? Person.find_by_id(contact_to_invite).user : User.find_by_email(friend_email) | ||
69 | + rescue | ||
70 | + user = nil | ||
71 | + end | ||
65 | 72 | ||
66 | - task_args = if user.nil? | 73 | + task_args = if user.nil? && !find_by_profile_id |
67 | {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message} | 74 | {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message} |
68 | - else | 75 | + elsif user.present? && !(user.person.is_a_friend?(person) && profile.person?) |
69 | {:person => person, :target => user.person} | 76 | {:person => person, :target => user.person} |
70 | end | 77 | end |
71 | 78 |
app/models/invite_friend.rb
1 | class InviteFriend < Invitation | 1 | class InviteFriend < Invitation |
2 | 2 | ||
3 | settings_items :group_for_person, :group_for_friend | 3 | settings_items :group_for_person, :group_for_friend |
4 | + before_create :check_for_invitation_existence | ||
4 | 5 | ||
5 | def perform | 6 | def perform |
6 | person.add_friend(friend, group_for_person) | 7 | person.add_friend(friend, group_for_person) |
@@ -41,4 +42,11 @@ class InviteFriend < Invitation | @@ -41,4 +42,11 @@ class InviteFriend < Invitation | ||
41 | ].join("\n\n") | 42 | ].join("\n\n") |
42 | end | 43 | end |
43 | 44 | ||
45 | + private | ||
46 | + def check_for_invitation_existence | ||
47 | + if friend | ||
48 | + friend.tasks.pending.of("InviteFriend").find(:all, :conditions => {:requestor_id => person.id, :target_id => friend.id}).blank? | ||
49 | + end | ||
50 | + end | ||
51 | + | ||
44 | end | 52 | end |
app/models/invite_member.rb
@@ -2,6 +2,7 @@ class InviteMember < Invitation | @@ -2,6 +2,7 @@ class InviteMember < Invitation | ||
2 | 2 | ||
3 | settings_items :community_id, :type => :integer | 3 | settings_items :community_id, :type => :integer |
4 | validates_presence_of :community_id | 4 | validates_presence_of :community_id |
5 | + before_create :check_for_invitation_existence | ||
5 | 6 | ||
6 | def community | 7 | def community |
7 | Community.find(community_id) | 8 | Community.find(community_id) |
@@ -39,6 +40,14 @@ class InviteMember < Invitation | @@ -39,6 +40,14 @@ class InviteMember < Invitation | ||
39 | _('%{requestor} invited you to join %{community}.') % {:requestor => requestor.name, :community => community.name} | 40 | _('%{requestor} invited you to join %{community}.') % {:requestor => requestor.name, :community => community.name} |
40 | end | 41 | end |
41 | 42 | ||
43 | + def target_notification_message | ||
44 | + if friend | ||
45 | + _('%{requestor} is inviting you to join "%{community}" on %{system}.') % { :system => target.environment.name, :requestor => requestor.name, :community => community.name } | ||
46 | + else | ||
47 | + super | ||
48 | + end | ||
49 | + end | ||
50 | + | ||
42 | def expanded_message | 51 | def expanded_message |
43 | super.gsub /<community>/, community.name | 52 | super.gsub /<community>/, community.name |
44 | end | 53 | end |
@@ -53,4 +62,11 @@ class InviteMember < Invitation | @@ -53,4 +62,11 @@ class InviteMember < Invitation | ||
53 | ].join("\n\n") | 62 | ].join("\n\n") |
54 | end | 63 | end |
55 | 64 | ||
65 | + private | ||
66 | + def check_for_invitation_existence | ||
67 | + if friend | ||
68 | + friend.tasks.pending.of("InviteMember").find(:all, :conditions => {:requestor_id => person.id}).select { |t| t.data[:community_id] == community_id }.blank? | ||
69 | + end | ||
70 | + end | ||
71 | + | ||
56 | end | 72 | end |
app/models/license.rb
@@ -3,8 +3,8 @@ class License < ActiveRecord::Base | @@ -3,8 +3,8 @@ class License < ActiveRecord::Base | ||
3 | attr_accessible :name, :url | 3 | attr_accessible :name, :url |
4 | 4 | ||
5 | SEARCHABLE_FIELDS = { | 5 | SEARCHABLE_FIELDS = { |
6 | - :name => 10, | ||
7 | - :url => 5, | 6 | + :name => {:label => _('Name'), :weight => 10}, |
7 | + :url => {:label => _('URL'), :weight => 5}, | ||
8 | } | 8 | } |
9 | 9 | ||
10 | belongs_to :environment | 10 | belongs_to :environment |
app/models/national_region.rb
1 | class NationalRegion < ActiveRecord::Base | 1 | class NationalRegion < ActiveRecord::Base |
2 | 2 | ||
3 | SEARCHABLE_FIELDS = { | 3 | SEARCHABLE_FIELDS = { |
4 | - :name => 1, | ||
5 | - :national_region_code => 1, | 4 | + :name => {:label => _('Name'), :weight => 1}, |
5 | + :national_region_code => {:label => _('Region Code'), :weight => 1}, | ||
6 | } | 6 | } |
7 | 7 | ||
8 | def self.search_city(city_name, like = false, state = nil) | 8 | def self.search_city(city_name, like = false, state = nil) |
app/models/organization.rb
@@ -3,10 +3,11 @@ class Organization < Profile | @@ -3,10 +3,11 @@ class Organization < Profile | ||
3 | 3 | ||
4 | attr_accessible :moderated_articles, :foundation_year, :contact_person, :acronym, :legal_form, :economic_activity, :management_information, :cnpj, :display_name, :enable_contact_us | 4 | attr_accessible :moderated_articles, :foundation_year, :contact_person, :acronym, :legal_form, :economic_activity, :management_information, :cnpj, :display_name, :enable_contact_us |
5 | 5 | ||
6 | - SEARCH_FILTERS += %w[ | ||
7 | - more_popular | ||
8 | - more_active | ||
9 | - ] | 6 | + SEARCH_FILTERS = { |
7 | + :order => %w[more_recent more_popular more_active], | ||
8 | + :display => %w[compact] | ||
9 | + } | ||
10 | + | ||
10 | 11 | ||
11 | settings_items :closed, :type => :boolean, :default => false | 12 | settings_items :closed, :type => :boolean, :default => false |
12 | def closed? | 13 | def closed? |
@@ -176,4 +177,8 @@ class Organization < Profile | @@ -176,4 +177,8 @@ class Organization < Profile | ||
176 | self.visible = false | 177 | self.visible = false |
177 | save! | 178 | save! |
178 | end | 179 | end |
180 | + | ||
181 | + def allow_invitation_from?(person) | ||
182 | + (followed_by?(person) && self.allow_members_to_invite) || person.has_permission?('invite-members', self) | ||
183 | + end | ||
179 | end | 184 | end |
app/models/person.rb
@@ -3,10 +3,11 @@ class Person < Profile | @@ -3,10 +3,11 @@ class Person < Profile | ||
3 | 3 | ||
4 | attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, :custom_area_of_study, :professional_activity, :organization_website | 4 | attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, :custom_area_of_study, :professional_activity, :organization_website |
5 | 5 | ||
6 | - SEARCH_FILTERS += %w[ | ||
7 | - more_popular | ||
8 | - more_active | ||
9 | - ] | 6 | + SEARCH_FILTERS = { |
7 | + :order => %w[more_recent more_popular more_active], | ||
8 | + :display => %w[compact] | ||
9 | + } | ||
10 | + | ||
10 | 11 | ||
11 | def self.type_name | 12 | def self.type_name |
12 | _('Person') | 13 | _('Person') |
@@ -21,16 +22,34 @@ class Person < Profile | @@ -21,16 +22,34 @@ class Person < Profile | ||
21 | { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } | 22 | { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } |
22 | } | 23 | } |
23 | 24 | ||
25 | + scope :not_members_of, lambda { |resources| | ||
26 | + resources = [resources] if !resources.kind_of?(Array) | ||
27 | + conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ') | ||
28 | + { :select => 'DISTINCT profiles.*', :conditions => ['"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "role_assignments" ON "role_assignments"."accessor_id" = "profiles"."id" AND "role_assignments"."accessor_type" = (\'Profile\') WHERE "profiles"."type" IN (\'Person\') AND (%s))' % conditions] } | ||
29 | + } | ||
30 | + | ||
24 | scope :by_role, lambda { |roles| | 31 | scope :by_role, lambda { |roles| |
25 | roles = [roles] unless roles.kind_of?(Array) | 32 | roles = [roles] unless roles.kind_of?(Array) |
26 | { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.role_id IN (?)', | 33 | { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.role_id IN (?)', |
27 | roles] } | 34 | roles] } |
28 | } | 35 | } |
29 | 36 | ||
30 | - def has_permission_with_plugins?(permission, profile) | ||
31 | - permissions = [has_permission_without_plugins?(permission, profile)] | 37 | + scope :not_friends_of, lambda { |resources| |
38 | + resources = Array(resources) | ||
39 | + { :select => 'DISTINCT profiles.*', :conditions => ['"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "friendships" ON "friendships"."person_id" = "profiles"."id" WHERE "friendships"."friend_id" IN (%s))' % resources.map(&:id)] } | ||
40 | + } | ||
41 | + | ||
42 | + def has_permission_with_admin?(permission, resource) | ||
43 | + return true if resource.blank? || resource.admins.include?(self) | ||
44 | + return true if resource.kind_of?(Profile) && resource.environment.admins.include?(self) | ||
45 | + has_permission_without_admin?(permission, resource) | ||
46 | + end | ||
47 | + alias_method_chain :has_permission?, :admin | ||
48 | + | ||
49 | + def has_permission_with_plugins?(permission, resource) | ||
50 | + permissions = [has_permission_without_plugins?(permission, resource)] | ||
32 | permissions += plugins.map do |plugin| | 51 | permissions += plugins.map do |plugin| |
33 | - plugin.has_permission?(self, permission, profile) | 52 | + plugin.has_permission?(self, permission, resource) |
34 | end | 53 | end |
35 | permissions.include?(true) | 54 | permissions.include?(true) |
36 | end | 55 | end |
@@ -45,9 +64,9 @@ roles] } | @@ -45,9 +64,9 @@ roles] } | ||
45 | ScopeTool.union *scopes | 64 | ScopeTool.union *scopes |
46 | end | 65 | end |
47 | 66 | ||
48 | - def memberships_by_role(role) | ||
49 | - memberships.where('role_assignments.role_id = ?', role.id) | ||
50 | - end | 67 | + def memberships_by_role(role) |
68 | + memberships.where('role_assignments.role_id = ?', role.id) | ||
69 | + end | ||
51 | 70 | ||
52 | has_many :friendships, :dependent => :destroy | 71 | has_many :friendships, :dependent => :destroy |
53 | has_many :friends, :class_name => 'Person', :through => :friendships | 72 | has_many :friends, :class_name => 'Person', :through => :friendships |
@@ -65,6 +84,10 @@ roles] } | @@ -65,6 +84,10 @@ roles] } | ||
65 | has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' | 84 | has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' |
66 | has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' | 85 | has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' |
67 | 86 | ||
87 | + has_many :profile_suggestions, :foreign_key => :person_id, :order => 'score DESC', :dependent => :destroy | ||
88 | + has_many :suggested_people, :through => :profile_suggestions, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Person', true] | ||
89 | + has_many :suggested_communities, :through => :profile_suggestions, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true] | ||
90 | + | ||
68 | scope :more_popular, :order => 'friends_count DESC' | 91 | scope :more_popular, :order => 'friends_count DESC' |
69 | 92 | ||
70 | scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*' | 93 | scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*' |
@@ -118,12 +141,12 @@ roles] } | @@ -118,12 +141,12 @@ roles] } | ||
118 | end | 141 | end |
119 | 142 | ||
120 | def add_friend(friend, group = nil) | 143 | def add_friend(friend, group = nil) |
121 | - unless self.is_a_friend?(friend) | 144 | + unless self.is_a_friend?(friend) |
122 | friendship = self.friendships.build | 145 | friendship = self.friendships.build |
123 | friendship.friend = friend | 146 | friendship.friend = friend |
124 | friendship.group = group | 147 | friendship.group = group |
125 | friendship.save | 148 | friendship.save |
126 | - end | 149 | + end |
127 | end | 150 | end |
128 | 151 | ||
129 | def already_request_friendship?(person) | 152 | def already_request_friendship?(person) |
@@ -497,6 +520,15 @@ roles] } | @@ -497,6 +520,15 @@ roles] } | ||
497 | person.notifier.reschedule_next_notification_mail | 520 | person.notifier.reschedule_next_notification_mail |
498 | end | 521 | end |
499 | 522 | ||
523 | + def remove_suggestion(profile) | ||
524 | + suggestion = profile_suggestions.find_by_suggestion_id profile.id | ||
525 | + suggestion.disable if suggestion | ||
526 | + end | ||
527 | + | ||
528 | + def allow_invitation_from?(person) | ||
529 | + person.has_permission?(:manage_friends, self) | ||
530 | + end | ||
531 | + | ||
500 | protected | 532 | protected |
501 | 533 | ||
502 | def followed_by?(profile) | 534 | def followed_by?(profile) |
app/models/product.rb
1 | class Product < ActiveRecord::Base | 1 | class Product < ActiveRecord::Base |
2 | 2 | ||
3 | SEARCHABLE_FIELDS = { | 3 | SEARCHABLE_FIELDS = { |
4 | - :name => 10, | ||
5 | - :description => 1, | 4 | + :name => {:label => _('Name'), :weight => 10}, |
5 | + :description => {:label => _('Description'), :weight => 1}, | ||
6 | } | 6 | } |
7 | 7 | ||
8 | - SEARCH_FILTERS = %w[ | ||
9 | - more_recent | ||
10 | - ] | ||
11 | - | ||
12 | - SEARCH_DISPLAYS = %w[map full] | 8 | + SEARCH_FILTERS = { |
9 | + :order => %w[more_recent], | ||
10 | + :display => %w[full map] | ||
11 | + } | ||
13 | 12 | ||
14 | attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list | 13 | attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list |
15 | 14 |
app/models/profile.rb
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | # which by default is the one returned by Environment:default. | 3 | # which by default is the one returned by Environment:default. |
4 | class Profile < ActiveRecord::Base | 4 | class Profile < ActiveRecord::Base |
5 | 5 | ||
6 | - attr_accessible :name, :identifier, :public_profile, :nickname, :custom_footer, :custom_header, :address, :zip_code, :contact_phone, :image_builder, :description, :closed, :template_id, :environment, :lat, :lng, :is_template, :fields_privacy, :preferred_domain_id, :category_ids, :country, :city, :state, :national_region_code, :email, :contact_email, :redirect_l10n, :notification_time, :redirection_after_login | 6 | + attr_accessible :name, :identifier, :public_profile, :nickname, :custom_footer, :custom_header, :address, :zip_code, :contact_phone, :image_builder, :description, :closed, :template_id, :environment, :lat, :lng, :is_template, :fields_privacy, :preferred_domain_id, :category_ids, :country, :city, :state, :national_region_code, :email, :contact_email, :redirect_l10n, :notification_time, :redirection_after_login, :email_suggestions, :allow_members_to_invite, :invite_friends_only |
7 | 7 | ||
8 | # use for internationalizable human type names in search facets | 8 | # use for internationalizable human type names in search facets |
9 | # reimplement on subclasses | 9 | # reimplement on subclasses |
@@ -12,16 +12,15 @@ class Profile < ActiveRecord::Base | @@ -12,16 +12,15 @@ class Profile < ActiveRecord::Base | ||
12 | end | 12 | end |
13 | 13 | ||
14 | SEARCHABLE_FIELDS = { | 14 | SEARCHABLE_FIELDS = { |
15 | - :name => 10, | ||
16 | - :identifier => 5, | ||
17 | - :nickname => 2, | 15 | + :name => {:label => _('Name'), :weight => 10}, |
16 | + :identifier => {:label => _('Username'), :weight => 5}, | ||
17 | + :nickname => {:label => _('Nickname'), :weight => 2}, | ||
18 | } | 18 | } |
19 | 19 | ||
20 | - SEARCH_FILTERS = %w[ | ||
21 | - more_recent | ||
22 | - ] | ||
23 | - | ||
24 | - SEARCH_DISPLAYS = %w[compact] | 20 | + SEARCH_FILTERS = { |
21 | + :order => %w[more_recent], | ||
22 | + :display => %w[compact] | ||
23 | + } | ||
25 | 24 | ||
26 | def self.default_search_display | 25 | def self.default_search_display |
27 | 'compact' | 26 | 'compact' |
@@ -140,6 +139,17 @@ class Profile < ActiveRecord::Base | @@ -140,6 +139,17 @@ class Profile < ActiveRecord::Base | ||
140 | 139 | ||
141 | has_many :comments_received, :class_name => 'Comment', :through => :articles, :source => :comments | 140 | has_many :comments_received, :class_name => 'Comment', :through => :articles, :source => :comments |
142 | 141 | ||
142 | + # Although this should be a has_one relation, there are no non-silly names for | ||
143 | + # a foreign key on article to reference the template to which it is | ||
144 | + # welcome_page... =P | ||
145 | + belongs_to :welcome_page, :class_name => 'Article', :dependent => :destroy | ||
146 | + | ||
147 | + def welcome_page_content | ||
148 | + welcome_page && welcome_page.published ? welcome_page.body : nil | ||
149 | + end | ||
150 | + | ||
151 | + has_many :search_terms, :as => :context | ||
152 | + | ||
143 | def scraps(scrap=nil) | 153 | def scraps(scrap=nil) |
144 | scrap = scrap.is_a?(Scrap) ? scrap.id : scrap | 154 | scrap = scrap.is_a?(Scrap) ? scrap.id : scrap |
145 | scrap.nil? ? Scrap.all_scraps(self) : Scrap.all_scraps(self).find(scrap) | 155 | scrap.nil? ? Scrap.all_scraps(self) : Scrap.all_scraps(self).find(scrap) |
@@ -155,6 +165,7 @@ class Profile < ActiveRecord::Base | @@ -155,6 +165,7 @@ class Profile < ActiveRecord::Base | ||
155 | settings_items :public_content, :type => :boolean, :default => true | 165 | settings_items :public_content, :type => :boolean, :default => true |
156 | settings_items :description | 166 | settings_items :description |
157 | settings_items :fields_privacy, :type => :hash, :default => {} | 167 | settings_items :fields_privacy, :type => :hash, :default => {} |
168 | + settings_items :email_suggestions, :type => :boolean, :default => false | ||
158 | 169 | ||
159 | validates_length_of :description, :maximum => 550, :allow_nil => true | 170 | validates_length_of :description, :maximum => 550, :allow_nil => true |
160 | 171 | ||
@@ -219,6 +230,8 @@ class Profile < ActiveRecord::Base | @@ -219,6 +230,8 @@ class Profile < ActiveRecord::Base | ||
219 | 230 | ||
220 | has_many :abuse_complaints, :foreign_key => 'requestor_id', :dependent => :destroy | 231 | has_many :abuse_complaints, :foreign_key => 'requestor_id', :dependent => :destroy |
221 | 232 | ||
233 | + has_many :profile_suggestions, :foreign_key => :suggestion_id, :dependent => :destroy | ||
234 | + | ||
222 | def top_level_categorization | 235 | def top_level_categorization |
223 | ret = {} | 236 | ret = {} |
224 | self.profile_categorizations.each do |c| | 237 | self.profile_categorizations.each do |c| |
@@ -514,6 +527,14 @@ class Profile < ActiveRecord::Base | @@ -514,6 +527,14 @@ class Profile < ActiveRecord::Base | ||
514 | generate_url(:profile => identifier, :controller => 'profile', :action => 'index') | 527 | generate_url(:profile => identifier, :controller => 'profile', :action => 'index') |
515 | end | 528 | end |
516 | 529 | ||
530 | + def people_suggestions_url | ||
531 | + generate_url(:profile => identifier, :controller => 'friends', :action => 'suggest') | ||
532 | + end | ||
533 | + | ||
534 | + def communities_suggestions_url | ||
535 | + generate_url(:profile => identifier, :controller => 'memberships', :action => 'suggest') | ||
536 | + end | ||
537 | + | ||
517 | def generate_url(options) | 538 | def generate_url(options) |
518 | url_options.merge(options) | 539 | url_options.merge(options) |
519 | end | 540 | end |
@@ -603,7 +624,7 @@ private :generate_url, :url_options | @@ -603,7 +624,7 @@ private :generate_url, :url_options | ||
603 | end | 624 | end |
604 | 625 | ||
605 | def copy_article_tree(article, parent=nil) | 626 | def copy_article_tree(article, parent=nil) |
606 | - return if article.is_a?(RssFeed) | 627 | + return if !copy_article?(article) |
607 | original_article = self.articles.find_by_name(article.name) | 628 | original_article = self.articles.find_by_name(article.name) |
608 | if original_article | 629 | if original_article |
609 | num = 2 | 630 | num = 2 |
@@ -623,6 +644,11 @@ private :generate_url, :url_options | @@ -623,6 +644,11 @@ private :generate_url, :url_options | ||
623 | end | 644 | end |
624 | end | 645 | end |
625 | 646 | ||
647 | + def copy_article?(article) | ||
648 | + !article.is_a?(RssFeed) && | ||
649 | + !(is_template && article.slug=='welcome-page') | ||
650 | + end | ||
651 | + | ||
626 | # Adds a person as member of this Profile. | 652 | # Adds a person as member of this Profile. |
627 | def add_member(person) | 653 | def add_member(person) |
628 | if self.has_members? | 654 | if self.has_members? |
@@ -632,6 +658,8 @@ private :generate_url, :url_options | @@ -632,6 +658,8 @@ private :generate_url, :url_options | ||
632 | self.affiliate(person, Profile::Roles.admin(environment.id)) if members.count == 0 | 658 | self.affiliate(person, Profile::Roles.admin(environment.id)) if members.count == 0 |
633 | self.affiliate(person, Profile::Roles.member(environment.id)) | 659 | self.affiliate(person, Profile::Roles.member(environment.id)) |
634 | end | 660 | end |
661 | + person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } | ||
662 | + remove_from_suggestion_list person | ||
635 | else | 663 | else |
636 | raise _("%s can't have members") % self.class.name | 664 | raise _("%s can't have members") % self.class.name |
637 | end | 665 | end |
@@ -769,7 +797,10 @@ private :generate_url, :url_options | @@ -769,7 +797,10 @@ private :generate_url, :url_options | ||
769 | end | 797 | end |
770 | 798 | ||
771 | def admins | 799 | def admins |
772 | - self.members_by_role(Profile::Roles.admin(environment.id)) | 800 | + return [] if environment.blank? |
801 | + admin_role = Profile::Roles.admin(environment.id) | ||
802 | + return [] if admin_role.blank? | ||
803 | + self.members_by_role(admin_role) | ||
773 | end | 804 | end |
774 | 805 | ||
775 | def enable_contact? | 806 | def enable_contact? |
@@ -967,4 +998,14 @@ private :generate_url, :url_options | @@ -967,4 +998,14 @@ private :generate_url, :url_options | ||
967 | def preferred_login_redirection | 998 | def preferred_login_redirection |
968 | redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login | 999 | redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login |
969 | end | 1000 | end |
1001 | + | ||
1002 | + def remove_from_suggestion_list(person) | ||
1003 | + suggestion = person.profile_suggestions.find_by_suggestion_id self.id | ||
1004 | + suggestion.disable if suggestion | ||
1005 | + end | ||
1006 | + | ||
1007 | + def allow_invitation_from(person) | ||
1008 | + false | ||
1009 | + end | ||
1010 | + | ||
970 | end | 1011 | end |
@@ -0,0 +1,290 @@ | @@ -0,0 +1,290 @@ | ||
1 | +class ProfileSuggestion < ActiveRecord::Base | ||
2 | + belongs_to :person | ||
3 | + belongs_to :suggestion, :class_name => 'Profile', :foreign_key => :suggestion_id | ||
4 | + | ||
5 | + attr_accessible :person, :suggestion, :suggestion_type, :categories, :enabled | ||
6 | + | ||
7 | + has_many :suggestion_connections, :foreign_key => 'suggestion_id' | ||
8 | + has_many :profile_connections, :through => :suggestion_connections, :source => :connection, :source_type => 'Profile' | ||
9 | + has_many :tag_connections, :through => :suggestion_connections, :source => :connection, :source_type => 'ActsAsTaggableOn::Tag' | ||
10 | + | ||
11 | + before_create do |profile_suggestion| | ||
12 | + profile_suggestion.suggestion_type = self.suggestion.class.to_s | ||
13 | + end | ||
14 | + | ||
15 | + after_destroy do |profile_suggestion| | ||
16 | + self.class.generate_profile_suggestions(profile_suggestion.person) | ||
17 | + end | ||
18 | + | ||
19 | + acts_as_having_settings :field => :categories | ||
20 | + | ||
21 | + validate :must_be_a_valid_category, :on => :create | ||
22 | + def must_be_a_valid_category | ||
23 | + if categories.keys.map { |cat| self.respond_to?(cat)}.include?(false) | ||
24 | + errors.add(:categories, 'Category must be valid') | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + validates_uniqueness_of :suggestion_id, :scope => [ :person_id ] | ||
29 | + scope :of_person, :conditions => { :suggestion_type => 'Person' } | ||
30 | + scope :of_community, :conditions => { :suggestion_type => 'Community' } | ||
31 | + scope :enabled, :conditions => { :enabled => true } | ||
32 | + | ||
33 | + # {:category_type => ['category-icon', 'category-label']} | ||
34 | + CATEGORIES = { | ||
35 | + :people_with_common_friends => ['menu-people', _('Friends in common')], | ||
36 | + :people_with_common_communities => ['menu-community',_('Communities in common')], | ||
37 | + :people_with_common_tags => ['edit', _('Tags in common')], | ||
38 | + :communities_with_common_friends => ['menu-people', _('Friends in common')], | ||
39 | + :communities_with_common_tags => ['edit', _('Tags in common')] | ||
40 | + } | ||
41 | + | ||
42 | + def category_icon(category) | ||
43 | + 'icon-' + ProfileSuggestion::CATEGORIES[category][0] | ||
44 | + end | ||
45 | + | ||
46 | + def category_label(category) | ||
47 | + ProfileSuggestion::CATEGORIES[category][1] | ||
48 | + end | ||
49 | + | ||
50 | + RULES = { | ||
51 | + :people_with_common_communities => { | ||
52 | + :threshold => 2, :weight => 1, :connection => 'Profile' | ||
53 | + }, | ||
54 | + :people_with_common_friends => { | ||
55 | + :threshold => 2, :weight => 1, :connection => 'Profile' | ||
56 | + }, | ||
57 | + :people_with_common_tags => { | ||
58 | + :threshold => 2, :weight => 1, :connection => 'ActsAsTaggableOn::Tag' | ||
59 | + }, | ||
60 | + :communities_with_common_friends => { | ||
61 | + :threshold => 2, :weight => 1, :connection => 'Profile' | ||
62 | + }, | ||
63 | + :communities_with_common_tags => { | ||
64 | + :threshold => 2, :weight => 1, :connection => 'ActsAsTaggableOn::Tag' | ||
65 | + } | ||
66 | + } | ||
67 | + | ||
68 | + RULES.keys.each do |rule| | ||
69 | + settings_items rule | ||
70 | + attr_accessible rule | ||
71 | + end | ||
72 | + | ||
73 | + # Number of suggestions by rule | ||
74 | + N_SUGGESTIONS = 30 | ||
75 | + | ||
76 | + # Minimum number of suggestions | ||
77 | + MIN_LIMIT = 10 | ||
78 | + | ||
79 | + def self.profile_id(rule) | ||
80 | + "#{rule}_profile_id" | ||
81 | + end | ||
82 | + | ||
83 | + def self.connections(rule) | ||
84 | + "#{rule}_connections" | ||
85 | + end | ||
86 | + | ||
87 | + def self.counter(rule) | ||
88 | + "#{rule}_count" | ||
89 | + end | ||
90 | + | ||
91 | + # If you are about to rewrite the following sql queries, think twice. After | ||
92 | + # that make sure that whatever you are writing to replace it should be faster | ||
93 | + # than how it is now. Yes, sqls are ugly but are fast! And fast is what we | ||
94 | + # need here. | ||
95 | + # | ||
96 | + # The logic behind this code is to produce a table somewhat like this: | ||
97 | + # profile_id | rule1_count | rule1_connections | rule2_count | rule2_connections | ... | score | | ||
98 | + # 12 | 2 | {32,54} | 3 | {8,22,27} | ... | 13 | | ||
99 | + # 13 | 4 | {3,12,32,54} | 2 | {11,24} | ... | 15 | | ||
100 | + # 14 | | | 2 | {44,56} | ... | 17 | | ||
101 | + # ... | ||
102 | + # ... | ||
103 | + # | ||
104 | + # This table has the suggested profile id and the count and connections of | ||
105 | + # each rule that made this profile be suggested. Each suggestion has a score | ||
106 | + # associated based on the rules' counts and rules' weights. | ||
107 | + # | ||
108 | + # From this table, we can sort suggestions by the score and save a small | ||
109 | + # amount of them in the database. At this moment we also register the | ||
110 | + # connections of each suggestion. | ||
111 | + | ||
112 | + def self.calculate_suggestions(person) | ||
113 | + suggested_profiles = all_suggestions(person) | ||
114 | + return if suggested_profiles.nil? | ||
115 | + | ||
116 | + already_suggested_profiles = person.profile_suggestions.map(&:suggestion_id).join(',') | ||
117 | + suggested_profiles = suggested_profiles.where("profiles.id NOT IN (#{already_suggested_profiles})") if already_suggested_profiles.present? | ||
118 | + #TODO suggested_profiles = suggested_profiles.order('score DESC') | ||
119 | + suggested_profiles = suggested_profiles.limit(N_SUGGESTIONS) | ||
120 | + return if suggested_profiles.blank? | ||
121 | + | ||
122 | + suggested_profiles.each do |suggested_profile| | ||
123 | + suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(suggested_profile.id) | ||
124 | + RULES.each do |rule, options| | ||
125 | + begin | ||
126 | + value = suggested_profile.send("#{rule}_count").to_i | ||
127 | + rescue NoMethodError | ||
128 | + next | ||
129 | + end | ||
130 | + connections = suggested_profile.send("#{rule}_connections") | ||
131 | + if connections.present? | ||
132 | + connections = connections[1..-2].split(',') | ||
133 | + else | ||
134 | + connections = [] | ||
135 | + end | ||
136 | + suggestion.send("#{rule}=", value) | ||
137 | + connections.each do |connection_id| | ||
138 | + next if SuggestionConnection.where(:suggestion_id => suggestion.id, :connection_id => connection_id, :connection_type => options[:connection]).present? | ||
139 | + SuggestionConnection.create!(:suggestion => suggestion, :connection_id => connection_id, :connection_type => options[:connection]) | ||
140 | + end | ||
141 | + suggestion.score += value * options[:weight] | ||
142 | + end | ||
143 | + suggestion.save! | ||
144 | + end | ||
145 | + end | ||
146 | + | ||
147 | + def self.people_with_common_friends(person) | ||
148 | + person_friends = person.friends.map(&:id) | ||
149 | + rule = "people_with_common_friends" | ||
150 | + return if person_friends.blank? | ||
151 | + "SELECT person_id as #{profile_id(rule)}, | ||
152 | + array_agg(friend_id) as #{connections(rule)}, | ||
153 | + count(person_id) as #{counter(rule)} | ||
154 | + FROM friendships WHERE friend_id IN (#{person_friends.join(',')}) | ||
155 | + AND person_id NOT IN (#{(person_friends << person.id).join(',')}) | ||
156 | + GROUP BY person_id" | ||
157 | + end | ||
158 | + | ||
159 | + def self.people_with_common_communities(person) | ||
160 | + person_communities = person.communities.map(&:id) | ||
161 | + rule = "people_with_common_communities" | ||
162 | + return if person_communities.blank? | ||
163 | + "SELECT common_members.accessor_id as #{profile_id(rule)}, | ||
164 | + array_agg(common_members.resource_id) as #{connections(rule)}, | ||
165 | + count(common_members.accessor_id) as #{counter(rule)} | ||
166 | + FROM | ||
167 | + (SELECT DISTINCT accessor_id, resource_id FROM | ||
168 | + role_assignments WHERE role_assignments.resource_id IN (#{person_communities.join(',')}) AND | ||
169 | + role_assignments.accessor_id != #{person.id} AND role_assignments.resource_type = 'Profile' AND | ||
170 | + role_assignments.accessor_type = 'Profile') AS common_members | ||
171 | + GROUP BY common_members.accessor_id" | ||
172 | + end | ||
173 | + | ||
174 | + def self.people_with_common_tags(person) | ||
175 | + profile_tags = person.articles.select('tags.id').joins(:tags).map(&:id) | ||
176 | + rule = "people_with_common_tags" | ||
177 | + return if profile_tags.blank? | ||
178 | + "SELECT results.profiles_id as #{profile_id(rule)}, | ||
179 | + array_agg(results.tags_id) as #{connections(rule)}, | ||
180 | + count(results.profiles_id) as #{counter(rule)} | ||
181 | + FROM ( | ||
182 | + SELECT DISTINCT tags.id as tags_id, profiles.id as profiles_id FROM profiles | ||
183 | + INNER JOIN articles ON articles.profile_id = profiles.id | ||
184 | + INNER JOIN taggings ON taggings.taggable_id = articles.id AND taggings.context = ('tags') AND taggings.taggable_type = 'Article' | ||
185 | + INNER JOIN tags ON tags.id = taggings.tag_id | ||
186 | + WHERE (tags.id in (#{profile_tags.join(',')}) AND profiles.id != #{person.id})) AS results | ||
187 | + GROUP BY results.profiles_id" | ||
188 | + end | ||
189 | + | ||
190 | + def self.communities_with_common_friends(person) | ||
191 | + person_friends = person.friends.map(&:id) | ||
192 | + rule = "communities_with_common_friends" | ||
193 | + return if person_friends.blank? | ||
194 | + "SELECT common_communities.resource_id as #{profile_id(rule)}, | ||
195 | + array_agg(common_communities.accessor_id) as #{connections(rule)}, | ||
196 | + count(common_communities.resource_id) as #{counter(rule)} | ||
197 | + FROM | ||
198 | + (SELECT DISTINCT accessor_id, resource_id FROM | ||
199 | + role_assignments WHERE role_assignments.accessor_id IN (#{person_friends.join(',')}) AND | ||
200 | + role_assignments.accessor_id != #{person.id} AND role_assignments.resource_type = 'Profile' AND | ||
201 | + role_assignments.accessor_type = 'Profile') AS common_communities | ||
202 | + GROUP BY common_communities.resource_id" | ||
203 | + end | ||
204 | + | ||
205 | + def self.communities_with_common_tags(person) | ||
206 | + profile_tags = person.articles.select('tags.id').joins(:tags).map(&:id) | ||
207 | + rule = "communities_with_common_tags" | ||
208 | + return if profile_tags.blank? | ||
209 | + "SELECT results.profiles_id as #{profile_id(rule)}, | ||
210 | + array_agg(results.tags_id) as #{connections(rule)}, | ||
211 | + count(results.profiles_id) as #{counter(rule)} | ||
212 | + FROM | ||
213 | + (SELECT DISTINCT tags.id as tags_id, profiles.id AS profiles_id FROM profiles | ||
214 | + INNER JOIN articles ON articles.profile_id = profiles.id | ||
215 | + INNER JOIN taggings ON taggings.taggable_id = articles.id AND taggings.context = ('tags') AND taggings.taggable_type = 'Article' | ||
216 | + INNER JOIN tags ON tags.id = taggings.tag_id | ||
217 | + WHERE (tags.id IN (#{profile_tags.join(',')}) AND profiles.id != #{person.id})) AS results | ||
218 | + GROUP BY results.profiles_id" | ||
219 | + end | ||
220 | + | ||
221 | + def self.all_suggestions(person) | ||
222 | + select_string = ["profiles.*"] | ||
223 | + suggestions_join = [] | ||
224 | + where_string = [] | ||
225 | + valid_rules = [] | ||
226 | + previous_rule = nil | ||
227 | + join_column = nil | ||
228 | + RULES.each do |rule, options| | ||
229 | + rule_select = self.send(rule, person) | ||
230 | + next if !rule_select.present? | ||
231 | + | ||
232 | + valid_rules << rule | ||
233 | + select_string << "suggestions.#{counter(rule)} as #{counter(rule)}, suggestions.#{connections(rule)} as #{connections(rule)}" | ||
234 | + where_string << "#{counter(rule)} >= #{options[:threshold]}" | ||
235 | + rule_select = " | ||
236 | + (SELECT profiles.id as #{profile_id(rule)}, | ||
237 | + #{rule}_sub.#{counter(rule)} as #{counter(rule)}, | ||
238 | + #{rule}_sub.#{connections(rule)} as #{connections(rule)} | ||
239 | + FROM profiles | ||
240 | + LEFT OUTER JOIN (#{rule_select}) as #{rule}_sub | ||
241 | + ON profiles.id = #{rule}_sub.#{profile_id(rule)}) AS #{rule}" | ||
242 | + | ||
243 | + if previous_rule.nil? | ||
244 | + result = rule_select | ||
245 | + else | ||
246 | + result = "INNER JOIN #{rule_select} | ||
247 | + ON #{previous_rule}.#{profile_id(previous_rule)} = #{rule}.#{profile_id(rule)}" | ||
248 | + end | ||
249 | + previous_rule = rule | ||
250 | + suggestions_join << result | ||
251 | + end | ||
252 | + | ||
253 | + return if valid_rules.blank? | ||
254 | + | ||
255 | + select_string = select_string.compact.join(',') | ||
256 | + join_string = "INNER JOIN (SELECT * FROM #{suggestions_join.compact.join(' ')}) AS suggestions ON profiles.id = suggestions.#{profile_id(valid_rules.first)}" | ||
257 | + where_string = where_string.compact.join(' OR ') | ||
258 | + | ||
259 | + person.environment.profiles. | ||
260 | + select(select_string). | ||
261 | + joins(join_string). | ||
262 | + where(where_string) | ||
263 | + end | ||
264 | + | ||
265 | + def disable | ||
266 | + self.enabled = false | ||
267 | + self.save! | ||
268 | + self.class.generate_profile_suggestions(self.person) | ||
269 | + end | ||
270 | + | ||
271 | + def self.generate_all_profile_suggestions | ||
272 | + Delayed::Job.enqueue(ProfileSuggestion::GenerateAllJob.new) unless ProfileSuggestion::GenerateAllJob.exists? | ||
273 | + end | ||
274 | + | ||
275 | + def self.generate_profile_suggestions(person, force = false) | ||
276 | + return if person.profile_suggestions.enabled.count >= MIN_LIMIT && !force | ||
277 | + Delayed::Job.enqueue ProfileSuggestionsJob.new(person.id) unless ProfileSuggestionsJob.exists?(person.id) | ||
278 | + end | ||
279 | + | ||
280 | + class GenerateAllJob | ||
281 | + def self.exists? | ||
282 | + Delayed::Job.by_handler("--- !ruby/object:ProfileSuggestion::GenerateAllJob {}\n").count > 0 | ||
283 | + end | ||
284 | + | ||
285 | + def perform | ||
286 | + Person.find_each {|person| ProfileSuggestion.generate_profile_suggestions(person) } | ||
287 | + end | ||
288 | + end | ||
289 | + | ||
290 | +end |
app/models/qualifier.rb
@@ -3,7 +3,7 @@ class Qualifier < ActiveRecord::Base | @@ -3,7 +3,7 @@ class Qualifier < ActiveRecord::Base | ||
3 | attr_accessible :name, :environment | 3 | attr_accessible :name, :environment |
4 | 4 | ||
5 | SEARCHABLE_FIELDS = { | 5 | SEARCHABLE_FIELDS = { |
6 | - :name => 1, | 6 | + :name => {:label => _('Name'), :weight => 1}, |
7 | } | 7 | } |
8 | 8 | ||
9 | belongs_to :environment | 9 | belongs_to :environment |
app/models/scrap.rb
@@ -3,7 +3,7 @@ class Scrap < ActiveRecord::Base | @@ -3,7 +3,7 @@ class Scrap < ActiveRecord::Base | ||
3 | attr_accessible :content, :sender_id, :receiver_id, :scrap_id | 3 | attr_accessible :content, :sender_id, :receiver_id, :scrap_id |
4 | 4 | ||
5 | SEARCHABLE_FIELDS = { | 5 | SEARCHABLE_FIELDS = { |
6 | - :content => 1, | 6 | + :content => {:label => _('Content'), :weight => 1}, |
7 | } | 7 | } |
8 | validates_presence_of :content | 8 | validates_presence_of :content |
9 | validates_presence_of :sender_id, :receiver_id | 9 | validates_presence_of :sender_id, :receiver_id |
@@ -0,0 +1,63 @@ | @@ -0,0 +1,63 @@ | ||
1 | +class SearchTerm < ActiveRecord::Base | ||
2 | + validates_presence_of :term, :context | ||
3 | + validates_uniqueness_of :term, :scope => [:context_id, :context_type, :asset] | ||
4 | + | ||
5 | + belongs_to :context, :polymorphic => true | ||
6 | + has_many :occurrences, :class_name => 'SearchTermOccurrence' | ||
7 | + | ||
8 | + attr_accessible :term, :context, :asset | ||
9 | + | ||
10 | + def self.calculate_scores | ||
11 | + os = occurrences_scores | ||
12 | + find_each { |search_term| search_term.calculate_score(os) } | ||
13 | + end | ||
14 | + | ||
15 | + def self.find_or_create(term, context, asset='all') | ||
16 | + context.search_terms.where(:term => term, :asset => asset).first || context.search_terms.create!(:term => term, :asset=> asset) | ||
17 | + end | ||
18 | + | ||
19 | + # Fast way of getting the occurrences score for each search_term. Ugly but fast! | ||
20 | + # | ||
21 | + # Each occurrence of a search_term has a score that is smaller the older the | ||
22 | + # occurrence happened. We subtract the amount of time between now and the | ||
23 | + # moment it happened from the total time any occurrence is valid to happen. E.g.: | ||
24 | + # The expiration time is 100 days and an occurrence happened 3 days ago. | ||
25 | + # Therefore the score is 97. Them we sum every score to get the total score | ||
26 | + # for a search term. | ||
27 | + def self.occurrences_scores | ||
28 | + ActiveSupport::OrderedHash[*ActiveRecord::Base.connection.execute( | ||
29 | + joins(:occurrences). | ||
30 | + select("search_terms.id, sum(#{SearchTermOccurrence::EXPIRATION_TIME.to_i} - extract(epoch from (now() - search_term_occurrences.created_at))) as value"). | ||
31 | + where("search_term_occurrences.created_at > ?", DateTime.now - SearchTermOccurrence::EXPIRATION_TIME). | ||
32 | + group("search_terms.id"). | ||
33 | + order('value DESC'). | ||
34 | + to_sql | ||
35 | + ).map {|result| [result['id'].to_i, result['value'].to_i]}.flatten] | ||
36 | + end | ||
37 | + | ||
38 | + def calculate_occurrence(occurrences_scores) | ||
39 | + max_score = occurrences_scores.first[1] | ||
40 | + (occurrences_scores[id]/max_score.to_f)*100 | ||
41 | + end | ||
42 | + | ||
43 | + def calculate_relevance(valid_occurrences) | ||
44 | + indexed = valid_occurrences.last.indexed.to_f | ||
45 | + return 0 if indexed == 0 | ||
46 | + total = valid_occurrences.last.total.to_f | ||
47 | + (1 - indexed/total)*100 | ||
48 | + end | ||
49 | + | ||
50 | + def calculate_score(occurrences_scores) | ||
51 | + valid_occurrences = occurrences.valid | ||
52 | + if valid_occurrences.present? | ||
53 | + # These scores vary from 1~100 | ||
54 | + self.occurrence_score = calculate_occurrence(occurrences_scores) | ||
55 | + self.relevance_score = calculate_relevance(valid_occurrences) | ||
56 | + else | ||
57 | + self.occurrence_score = 0 | ||
58 | + self.relevance_score = 0 | ||
59 | + end | ||
60 | + self.score = (occurrence_score * relevance_score)/100.0 | ||
61 | + self.save! | ||
62 | + end | ||
63 | +end |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +class SearchTermOccurrence < ActiveRecord::Base | ||
2 | + belongs_to :search_term | ||
3 | + validates_presence_of :search_term | ||
4 | + attr_accessible :search_term, :created_at, :total, :indexed | ||
5 | + | ||
6 | + EXPIRATION_TIME = 1.year | ||
7 | + | ||
8 | + scope :valid, :conditions => ["search_term_occurrences.created_at > ?", DateTime.now - EXPIRATION_TIME] | ||
9 | +end |
@@ -0,0 +1,6 @@ | @@ -0,0 +1,6 @@ | ||
1 | +class SuggestionConnection < ActiveRecord::Base | ||
2 | + attr_accessible :suggestion, :connection_type, :connection_id | ||
3 | + | ||
4 | + belongs_to :suggestion, :class_name => 'ProfileSuggestion', :foreign_key => 'suggestion_id' | ||
5 | + belongs_to :connection, :polymorphic => true | ||
6 | +end |
app/models/user.rb
@@ -11,6 +11,10 @@ class User < ActiveRecord::Base | @@ -11,6 +11,10 @@ class User < ActiveRecord::Base | ||
11 | N_('Password confirmation') | 11 | N_('Password confirmation') |
12 | N_('Terms accepted') | 12 | N_('Terms accepted') |
13 | 13 | ||
14 | + SEARCHABLE_FIELDS = { | ||
15 | + :email => {:label => _('Email'), :weight => 5}, | ||
16 | + } | ||
17 | + | ||
14 | def self.[](login) | 18 | def self.[](login) |
15 | self.find_by_login(login) | 19 | self.find_by_login(login) |
16 | end | 20 | end |
app/views/account/signup.html.erb
1 | -<% if @register_pending %> | ||
2 | - <div id='thanks-for-signing'> | ||
3 | - <% if environment.has_custom_welcome_screen? %> | ||
4 | - <%= environment.settings[:signup_welcome_screen_body].html_safe %> | ||
5 | - <% elsif environment.enabled?('admin_must_approve_new_users')%> | ||
6 | - <h1><%= _("Welcome to %s!") % environment.name %></h1> | ||
7 | - <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3> | ||
8 | - <p><%= _("Firstly, some tips for getting started:") %></p> | ||
9 | - <% unless environment.enabled?('skip_new_user_email_confirmation') %> | ||
10 | - <h4><%= _("Confirm your account and wait for admin approvement!") %></h4> | ||
11 | - <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p> | ||
12 | - <p><%= _("You won't appear as %s until your account is confirmed and approved.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> | ||
13 | - <% else %> | ||
14 | - <h4><%= _("Wait for admin approvement!") %></h4> | ||
15 | - <p><%= _("The administrators will evaluate your signup request for approvement.") %></p> | ||
16 | - <p><%= _("You won't appear as %s until your account is approved.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> | ||
17 | - <% end %> | ||
18 | - <h4><%= _("What to do next?") %></h4> | ||
19 | - <p><%= _("%s. Upload an avatar and let your friends find you easily :)") % link_to(_('Customize your profile'), {:controller => 'doc', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank') %></p> | ||
20 | - <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p> | ||
21 | - <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p> | ||
22 | - <p><%= _("Start exploring and have fun!") %></p> | ||
23 | - <% else %> | ||
24 | - <h1><%= _("Welcome to %s!") % environment.name %></h1> | ||
25 | - <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3> | ||
26 | - <p><%= _("Firstly, some tips for getting started:") %></p> | ||
27 | - <h4><%= _("Confirm your account!") %></h4> | ||
28 | - <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p> | ||
29 | - <p><%= _("You won't appear as %s until your account is confirmed.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> | ||
30 | - <h4><%= _("What to do next?") %></h4> | ||
31 | - <p><%= _("%s. Upload an avatar and let your friends find you easily :)") % link_to(_('Customize your profile'), {:controller => 'doc', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank') %></p> | ||
32 | - <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p> | ||
33 | - <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p> | ||
34 | - <p><%= _("Start exploring and have fun!") %></p> | ||
35 | - <% end %> | ||
36 | - </div> | ||
37 | -<% else %> | ||
38 | - <h1><%= _('Sign up for %s!') % environment.name %></h1> | ||
39 | - <%= render :partial => 'signup_form' %> | ||
40 | -<% end %> | 1 | +<h1><%= _('Sign up for %s!') % environment.name %></h1> |
2 | +<%= render :partial => 'signup_form' %> |
app/views/admin_panel/_signup_welcome_screen.html.erb
1 | <div class='description'> | 1 | <div class='description'> |
2 | - <%= _('This text will be showed as a welcome message to users after signup') %><br/><br/> | 2 | + <%= _('If you enable this feature on the "Features" section of the Administration Panel, this text will be shown as a welcome message to users after signup.') %> |
3 | </div> | 3 | </div> |
4 | - | ||
5 | <%= labelled_form_field(_('Body'), text_area(:environment, :signup_welcome_screen_body, :cols => 40, :style => 'width: 100%', :class => 'mceEditor')) %> | 4 | <%= labelled_form_field(_('Body'), text_area(:environment, :signup_welcome_screen_body, :cols => 40, :style => 'width: 100%', :class => 'mceEditor')) %> |
5 | + | ||
6 | +<div class='description'> | ||
7 | + <%= _('If this content is left blank, the following page will be displayed to the user:') %> | ||
8 | +</div> | ||
9 | + | ||
10 | +<%= render :file => 'home/welcome', :locals => {:default_message => true} %> |
app/views/admin_panel/site_info.html.erb
@@ -10,9 +10,12 @@ | @@ -10,9 +10,12 @@ | ||
10 | :content => (render :partial => 'site_info', :locals => {:f => f})} %> | 10 | :content => (render :partial => 'site_info', :locals => {:f => f})} %> |
11 | <% tabs << {:title => _('Terms of use'), :id => 'terms-of-use', | 11 | <% tabs << {:title => _('Terms of use'), :id => 'terms-of-use', |
12 | :content => (render :partial => 'terms_of_use', :locals => {:f => f})} %> | 12 | :content => (render :partial => 'terms_of_use', :locals => {:f => f})} %> |
13 | - <% tabs << {:title => _('Signup welcome text'), :id => 'signup-welcome-text', | 13 | + <% #TODO I renamed the labels of signup-welcome-text and signup-welcome-page |
14 | + # so texts more meaningful but I'm not rewriting every variable or reference to | ||
15 | + # this. I leave this task to whoever thinks this is too annoying.%> | ||
16 | + <% tabs << {:title => _('Signup welcome email'), :id => 'signup-welcome-text', | ||
14 | :content => (render :partial => 'signup_welcome_text', :locals => {:f => f})} %> | 17 | :content => (render :partial => 'signup_welcome_text', :locals => {:f => f})} %> |
15 | - <% tabs << {:title => _('Signup welcome message'), :id => 'signup-welcome-message', | 18 | + <% tabs << {:title => _('Signup welcome page'), :id => 'signup-welcome-message', |
16 | :content => (render :partial => 'signup_welcome_screen', :locals => {:f => f}) }%> | 19 | :content => (render :partial => 'signup_welcome_screen', :locals => {:f => f}) }%> |
17 | <%= render_tabs(tabs) %> | 20 | <%= render_tabs(tabs) %> |
18 | <% button_bar do %> | 21 | <% button_bar do %> |
@@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
1 | +<% if owner.kind_of?(Profile) %> | ||
2 | + <%= link_to s_('communities|View all'), {:profile => owner.identifier, :controller => 'profile', :action => 'communities'}, :class => 'view-all' %> | ||
3 | +<% elsif owner.kind_of?(Environment) %> | ||
4 | + <%= link_to s_('communities|View all'), {:controller => 'search', :action => 'communities'}, :class => 'view-all' %> | ||
5 | +<% end %> | ||
6 | + | ||
7 | +<% if user && user == profile && suggestions && !suggestions.empty? %> | ||
8 | + <div class='suggestions-block common-profile-list-block'> | ||
9 | + <h4 class='block-subtitle'><%= _('Some suggestions for you') %></h4> | ||
10 | + <div class='profiles-suggestions'> | ||
11 | + <%= render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => suggestions, :collection => :communities_suggestions, :per_page => 3 } %> | ||
12 | + </div> | ||
13 | + <div class='more-suggestions'> | ||
14 | + <%= link_to _('See all suggestions'), profile.communities_suggestions_url %> | ||
15 | + </div> | ||
16 | + </div> | ||
17 | +<% end %> |
app/views/blocks/my_network.html.erb
1 | <%= block_title(title) %> | 1 | <%= block_title(title) %> |
2 | 2 | ||
3 | -<%= render_profile_actions owner.class %> | ||
4 | - | ||
5 | <ul> | 3 | <ul> |
6 | <li><%= link_to(_('Homepage'), owner.url, :class => 'url') %></li> | 4 | <li><%= link_to(_('Homepage'), owner.url, :class => 'url') %></li> |
7 | <li><%= link_to(_('View profile'), owner.public_profile_url) %></li> | 5 | <li><%= link_to(_('View profile'), owner.public_profile_url) %></li> |
@@ -11,5 +9,5 @@ | @@ -11,5 +9,5 @@ | ||
11 | </ul> | 9 | </ul> |
12 | 10 | ||
13 | <div class="my-network-actions"> | 11 | <div class="my-network-actions"> |
14 | - <%= render 'blocks/profile_info_actions/' + owner.class.name.underscore %> | 12 | + <%= render_profile_actions owner.class %> |
15 | </div> | 13 | </div> |
app/views/cms/_drag_and_drop_note.html.erb
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +<%= form_tag({:action => 'new', :profile => profile.identifier}, :id => 'new-folder-dialog', :title => _('Create new folder'), :style => 'display: none;') do %> | ||
2 | + <%= select_profile_folder( | ||
3 | + _('Choose parent folder:'), | ||
4 | + :parent_id, profile, default_folder, {}, {}, | ||
5 | + "type='Folder' or type='Gallery'") | ||
6 | + %> | ||
7 | + | ||
8 | + <%= labelled_radio_button _('Gallery'), :folder_type, 'Gallery', true %> | ||
9 | + <%= labelled_radio_button _('Folder'), :folder_type, 'Folder', false %> | ||
10 | + | ||
11 | + <%= labelled_form_field _('Name:'), text_field_tag(:new_folder, nil, 'data-url' => url_for({:action => 'new', :profile => profile.identifier})) %> | ||
12 | + <% button_bar do %> | ||
13 | + <%= submit_button(:newfolder, _('Create')) %> | ||
14 | + <% end %> | ||
15 | +<% end %> |
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<% file_types.each do |key, header| %> | ||
2 | + <% display = @recent_files[key].present? ? '' : 'none' %> | ||
3 | + <div class='<%= key.to_s %>' style='display: <%= display%>;'> | ||
4 | + <div class='section-title'> | ||
5 | + <h3><%= header %></h3> | ||
6 | + <% if @recent_files[key].total_pages > 1 %> | ||
7 | + <%= link_to(_('View all'), {:controller => 'cms', :action => 'view_all_media', :profile => profile.identifier, :key => key}, :class => 'view-all colorbox', 'data-key' => key) %> | ||
8 | + <% end %> | ||
9 | + </div> | ||
10 | + <%= render :partial => "cms/media_panel/list_published_media_items", :locals => { key: key, show_pagination_links: false } %> | ||
11 | + </div> | ||
12 | +<% end %> |
app/views/cms/_text_editor_sidebar.html.erb
1 | +<% default_folder = content_id_to_str default_folder_for_image_upload(profile) %> | ||
2 | + | ||
1 | <div class='text-editor-sidebar'> | 3 | <div class='text-editor-sidebar'> |
2 | <span class='button-add' data-value='<%= _('Add to the text') %>'></span> | 4 | <span class='button-add' data-value='<%= _('Add to the text') %>'></span> |
3 | <span class='button-zoom' data-value='<%= _('Zoom in') %>'></span> | 5 | <span class='button-zoom' data-value='<%= _('Zoom in') %>'></span> |
4 | <span class='button-close' data-value='<%= _('Close') %>'></span> | 6 | <span class='button-close' data-value='<%= _('Close') %>'></span> |
5 | 7 | ||
8 | + <div class='header'><strong><%= _('Insert media') %></strong><%= button('vertical-toggle', _('Show/Hide'), '#') %></div> | ||
9 | + | ||
6 | <%= render(:partial => 'textile_quick_reference') if @article.is_a?(TextileArticle) %> | 10 | <%= render(:partial => 'textile_quick_reference') if @article.is_a?(TextileArticle) %> |
7 | <div class='text-editor-sidebar-box' id='media-upload-box'> | 11 | <div class='text-editor-sidebar-box' id='media-upload-box'> |
8 | - <div class='header'><strong><%= _('Insert media') %></strong></div> | ||
9 | <div id='media-upload-form'> | 12 | <div id='media-upload-form'> |
10 | <%= form_tag({ :action => 'media_upload' }, :multipart => true) do %> | 13 | <%= form_tag({ :action => 'media_upload' }, :multipart => true) do %> |
11 | <div class='formfield'> | 14 | <div class='formfield'> |
12 | - <% default_folder = content_id_to_str default_folder_for_image_upload(profile) %> | ||
13 | <%= select_profile_folder( | 15 | <%= select_profile_folder( |
14 | _('Choose folder to upload files:'), | 16 | _('Choose folder to upload files:'), |
15 | :parent_id, profile, default_folder, {}, {}, | 17 | :parent_id, profile, default_folder, {}, {}, |
16 | "type='Folder' or type='Gallery'" | 18 | "type='Folder' or type='Gallery'" |
17 | ) %> | 19 | ) %> |
18 | </div> | 20 | </div> |
19 | - <p><%= file_field_tag('file1') %></p> | ||
20 | - <p><%= file_field_tag('file2') %></p> | ||
21 | - <p><%= file_field_tag('file3') %></p> | ||
22 | - <% button_bar do %> | ||
23 | - <%= submit_button(:save, _('Upload')) %> | ||
24 | - <% end %> | 21 | + <%= button(:newfolder, _('New folder'), '#', :id => 'new-folder-button') %> |
22 | + <p><%= file_field_tag('file', :multiple => true) %></p> | ||
25 | <% end %> | 23 | <% end %> |
26 | </div> | 24 | </div> |
27 | - <div id='media-upload-results' style='display: none'> | ||
28 | - <%= render :partial => 'drag_and_drop_note' %> | ||
29 | - <div class='items'> | ||
30 | - </div> | ||
31 | - <p><%= link_to(_('Upload more files ...'), '#', :id => 'media-upload-more-files')%></p> | 25 | + <div class='hide-and-show-uploads'> |
26 | + <%= link_to(_('Hide all uploads'), nil, :id => 'hide-uploads', :style => 'display: none;', 'data-bootstraped' => false) %> | ||
27 | + <%= link_to(_('Show all uploads'), nil, :id => 'show-uploads', :style => 'display: none;') %> | ||
32 | </div> | 28 | </div> |
33 | </div> | 29 | </div> |
34 | - <div id='media-search-box' class='text-editor-sidebar-box'> | ||
35 | - <div class='header'><strong><%= _('Media search') %></strong></div> | ||
36 | - <p> | ||
37 | - <%= form_tag({ :action => 'search' }) do %> | ||
38 | - <span class='formfield'> | ||
39 | - <input name='q' type='text' id='media-search-query' style='width: 250px;'/> | ||
40 | - </span> | ||
41 | - <%= submit_button :search, _('Search'), :id => 'media-search-button' %> | ||
42 | - <% end %> | ||
43 | - </p> | ||
44 | - <div id='media-search-results' style='display: none'> | ||
45 | - <%= render :partial => 'drag_and_drop_note' %> | ||
46 | - <div class='items'> | ||
47 | - </div> | 30 | + |
31 | + <div id='published-media' class='text-editor-sidebar-box' data-url='<%= url_for({:controller => 'cms', :action => 'published_media_items', :profile => profile.identifier}) %>'> | ||
32 | + <%= select_profile_folder(nil, :parent_id, profile, 'recent-media', {}, {}, | ||
33 | + "type='Folder' or type='Gallery'", {:root_label => _('Recent media')}) %> | ||
34 | + <%= labelled_form_field _('Search'), text_field_tag('q') %> | ||
35 | + <%= render :partial => 'drag_and_drop_note' %> | ||
36 | + <div class='items'> | ||
37 | + <%= render :partial => 'published_media_items' %> | ||
48 | </div> | 38 | </div> |
49 | </div> | 39 | </div> |
50 | </div> | 40 | </div> |
51 | 41 | ||
42 | +<script id="template-upload" type="text/x-tmpl"> | ||
43 | + <div id="file-{%= o.id %}" class="upload" title="{%= o.name %}"> | ||
44 | + <div class="file-name">{%=o.name%}</div> | ||
45 | + <div class="percentage"></div> | ||
46 | + <div class="progress"><div class="bar" style="width: 0%;"></div></div> | ||
47 | + </div> | ||
48 | +</script> | ||
52 | 49 | ||
50 | +<%= render :partial => 'media_new_folder', :locals => {:default_folder => default_folder} %> | ||
51 | +<%= javascript_include_tag 'jquery.fileupload.js', 'tmpl.js', 'media-panel.js' %> |
app/views/cms/_textile_quick_reference.html.erb
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | <pre># <%= _('first item') %> | 15 | <pre># <%= _('first item') %> |
16 | # <%= _('second item') %></pre> | 16 | # <%= _('second item') %></pre> |
17 | <p><%= h(_('For code, use HTML tags <pre> and <code>, and indent the code inside them:')) %> | 17 | <p><%= h(_('For code, use HTML tags <pre> and <code>, and indent the code inside them:')) %> |
18 | + </p> | ||
18 | <pre> | 19 | <pre> |
19 | <pre> | 20 | <pre> |
20 | <code> | 21 | <code> |
app/views/cms/edit.html.erb
1 | <%= error_messages_for 'article' %> | 1 | <%= error_messages_for 'article' %> |
2 | 2 | ||
3 | -<div class='<%= (environment.enabled?('media_panel') ? 'with_media_panel' : 'no_media_panel') %>'> | 3 | +<% show_media_panel = environment.enabled?('media_panel') && [TinyMceArticle, TextileArticle, Event, EnterpriseHomepage].any?{|klass| @article.kind_of?(klass)} %> |
4 | + | ||
5 | +<div class='<%= (show_media_panel ? 'with_media_panel' : 'no_media_panel') %>'> | ||
4 | <%= labelled_form_for 'article', :html => { :multipart => true, :class => @type } do |f| %> | 6 | <%= labelled_form_for 'article', :html => { :multipart => true, :class => @type } do |f| %> |
5 | 7 | ||
6 | <%= hidden_field_tag("type", @type) if @type %> | 8 | <%= hidden_field_tag("type", @type) if @type %> |
@@ -66,7 +68,7 @@ | @@ -66,7 +68,7 @@ | ||
66 | <% end %> | 68 | <% end %> |
67 | </div> | 69 | </div> |
68 | 70 | ||
69 | -<% if environment.enabled?('media_panel') && [TinyMceArticle, TextileArticle, Event, EnterpriseHomepage].any?{|klass| @article.kind_of?(klass)} %> | 71 | +<% if show_media_panel %> |
70 | <%= render :partial => 'text_editor_sidebar' %> | 72 | <%= render :partial => 'text_editor_sidebar' %> |
71 | <% end %> | 73 | <% end %> |
72 | 74 |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +<div class="item image" data-item="span" title="<%= @file.name %>"> | ||
2 | + <span> | ||
3 | + <img src="<%= @file.public_filename(:uploaded) %>"/> | ||
4 | + </span> | ||
5 | + <div class="controls image-controls"> | ||
6 | + <a class="button icon-add add-to-text" href="#"><span><%= _('Add to the text') %></span></a> | ||
7 | + <a class="button icon-zoom zoom" href="#" title="<%= _('Zoom in') %>"><span><%= _('Zoom in') %></span></a> | ||
8 | + </div> | ||
9 | +</div> |
app/views/cms/media_panel/_list_published_media_items.html.erb
0 → 100644
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +loadPublishedMedia(); |
app/views/cms/publish.html.erb
1 | -<h1><%= _('Select the groups where you want to publish your article') %></h1> | 1 | +<div class="select-publish-target"> |
2 | + | ||
3 | +<h2><%= _('Where do you want to publish this article?') %></h2> | ||
2 | 4 | ||
3 | <% if !@failed.blank? %> | 5 | <% if !@failed.blank? %> |
4 | <div class="errorExplanation" id="errorExplanation"> | 6 | <div class="errorExplanation" id="errorExplanation"> |
@@ -14,15 +16,54 @@ | @@ -14,15 +16,54 @@ | ||
14 | </div> | 16 | </div> |
15 | <% end %> | 17 | <% end %> |
16 | 18 | ||
17 | -<%= form_tag do%> | ||
18 | - <%= hidden_field_tag :back_to, @back_to %> | ||
19 | - <% @groups.each do |group| %> | ||
20 | - <%= labelled_check_box group.name, "marked_groups[#{group.id}][group_id]", group.id, @marked_groups.include?(group) %><br /> | ||
21 | - <%= labelled_text_field _('Title') + ': ', "marked_groups[#{group.id}][name]", @article.name, :style => 'width: 100%' %> | ||
22 | - <hr /> | 19 | +<ul class='publish-targets'> |
20 | + <% if profile != user %> | ||
21 | + <li onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | ||
22 | + <strong><%= _("Publish this article on your profile") %></strong> | ||
23 | + <div class='description'><%= _('You can publish this article on your profile where your friends and followers will see.') %></div> | ||
24 | + <%= form_tag do %> | ||
25 | + <%= hidden_field_tag :back_to, @back_to %> | ||
26 | + <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> | ||
27 | + | ||
28 | + <% button_bar do %> | ||
29 | + <%= submit_button 'spread', _('Spread this') %> | ||
30 | + <% end %> | ||
31 | + <% end %> | ||
32 | + </li> | ||
23 | <% end %> | 33 | <% end %> |
24 | 34 | ||
25 | - <% button_bar do %> | ||
26 | - <%= submit_button 'spread', _('Spread this'), :cancel => @back_to %> | 35 | + <% if user.communities.present? %> |
36 | + <li onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | ||
37 | + <strong><%= _("Publish this article on communities you are part of") %></strong> | ||
38 | + <div class='description'><%= _('You can submit this article to one or more communities you are a member of, just search for the community below.') %></div> | ||
39 | + <%= form_tag :action => 'publish_on_communities', :id => @article.id do %> | ||
40 | + <%= hidden_field_tag :back_to, @back_to %> | ||
41 | + <% search_action = url_for(:action => 'search_communities_to_publish') %> | ||
42 | + <%= token_input_field_tag(:q, 'search-communities-to-publish', search_action, { :hint_text => _('Type in a search for your community'), :zindex => 10000, :focus => false }) %> | ||
43 | + <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> | ||
44 | + <% button_bar do %> | ||
45 | + <%= submit_button 'spread', _('Spread this') %> | ||
46 | + <% end %> | ||
47 | + <% end %> | ||
48 | + </li> | ||
27 | <% end %> | 49 | <% end %> |
28 | -<% end %> | 50 | + |
51 | + | ||
52 | + <% if environment.portal_enabled %> | ||
53 | + <li onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | ||
54 | + <strong><%= _("Publish your article on portal community") %></strong> | ||
55 | + <div class='description'><%= _('You can suggest this article to the portal community, where it can show up on the homepage.') %></div> | ||
56 | + | ||
57 | + <%= form_tag :action => 'publish_on_portal_community', :id => @article.id do %> | ||
58 | + <%= hidden_field_tag :back_to, @back_to %> | ||
59 | + <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> | ||
60 | + | ||
61 | + <% button_bar do %> | ||
62 | + <%= submit_button 'spread', _('Spread this') %> | ||
63 | + <% end %> | ||
64 | + <% end %> | ||
65 | + </li> | ||
66 | + <% end %> | ||
67 | +</ul> | ||
68 | + | ||
69 | +</div> |
app/views/cms/view.html.erb
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | <%= _('Content management') %> | 2 | <%= _('Content management') %> |
3 | </h1> | 3 | </h1> |
4 | 4 | ||
5 | -<% if user.can_change_homepage? && !remove_content_button(:home) %> | 5 | +<% if user.can_change_homepage? && !remove_content_button(:home, profile.home_page) %> |
6 | <div class="cms-homepage"> | 6 | <div class="cms-homepage"> |
7 | <%= _('Profile homepage:') %> | 7 | <%= _('Profile homepage:') %> |
8 | <% if profile.home_page %> | 8 | <% if profile.home_page %> |
@@ -66,17 +66,17 @@ | @@ -66,17 +66,17 @@ | ||
66 | <%= short_description %> | 66 | <%= short_description %> |
67 | </td> | 67 | </td> |
68 | <td class="article-controls"> | 68 | <td class="article-controls"> |
69 | - <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> | 69 | + <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit, article) %> |
70 | <%= button_without_text :eyes, _('Public view'), article.view_url %> | 70 | <%= button_without_text :eyes, _('Public view'), article.view_url %> |
71 | - <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> | ||
72 | - <% if user.can_change_homepage? && !remove_content_button(:home) %> | 71 | + <%= display_spread_button(article) unless remove_content_button(:spread, article) %> |
72 | + <% if user.can_change_homepage? && !remove_content_button(:home, article) %> | ||
73 | <% if profile.home_page != article %> | 73 | <% if profile.home_page != article %> |
74 | <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | 74 | <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> |
75 | <% else %> | 75 | <% else %> |
76 | <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %> | 76 | <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %> |
77 | <% end %> | 77 | <% end %> |
78 | <% end %> | 78 | <% end %> |
79 | - <%= display_delete_button(article) if !remove_content_button(:delete) %> | 79 | + <%= display_delete_button(article) if !remove_content_button(:delete, article) %> |
80 | </td> | 80 | </td> |
81 | </tr> | 81 | </tr> |
82 | <% end %> | 82 | <% end %> |
@@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
1 | +<h1><%= file_types[@key] %></h1> | ||
2 | + | ||
3 | +<div class='view-all-media view-all-<%= @key %>'> | ||
4 | + <%= render :partial => "cms/media_panel/list_published_media_items", :locals => { key: @key, show_pagination_links: true } %> | ||
5 | +</div> | ||
6 | + | ||
7 | +<%= javascript_include_tag 'media-panel.js' %> |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +jQuery('.view-all-media').html('<%= escape_javascript(render :partial => "cms/media_panel/list_published_media_items", :locals => { key: @key, show_pagination_links: true }) %>'); |
app/views/content_viewer/_article_toolbar.html.erb
@@ -2,46 +2,40 @@ | @@ -2,46 +2,40 @@ | ||
2 | <div id="article-actions"> | 2 | <div id="article-actions"> |
3 | 3 | ||
4 | 4 | ||
5 | - <% if @page.allow_edit?(user) && !remove_content_button(:edit) %> | 5 | + <% if @page.allow_edit?(user) && !remove_content_button(:edit, @page) %> |
6 | <% content = content_tag('span', label_for_edit_article(@page)) %> | 6 | <% content = content_tag('span', label_for_edit_article(@page)) %> |
7 | <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }) %> | 7 | <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }) %> |
8 | <%= expirable_button @page, :edit, content, url %> | 8 | <%= expirable_button @page, :edit, content, url %> |
9 | <% end %> | 9 | <% end %> |
10 | 10 | ||
11 | - <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) && !remove_content_button(:delete)%> | 11 | + <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) && !remove_content_button(:delete, @page)%> |
12 | <% content = content_tag( 'span', _('Delete') ) %> | 12 | <% content = content_tag( 'span', _('Delete') ) %> |
13 | <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page.id}) %> | 13 | <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page.id}) %> |
14 | <% options = {:method => :post, :confirm => delete_article_message(@page)} %> | 14 | <% options = {:method => :post, :confirm => delete_article_message(@page)} %> |
15 | <%= expirable_button @page, :delete, content, url, options %> | 15 | <%= expirable_button @page, :delete, content, url, options %> |
16 | <% end %> | 16 | <% end %> |
17 | 17 | ||
18 | - <% if !@page.folder? && @page.allow_spread?(user) && !remove_content_button(:spread) %> | ||
19 | - <% content = content_tag( 'span', _('Spread this') ) %> | ||
20 | - <% url = nil %> | ||
21 | - <% if profile.kind_of?(Person) %> | ||
22 | - <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page.id }) %> | ||
23 | - <% elsif profile.kind_of?(Community) && environment.portal_community %> | ||
24 | - <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page.id }) %> | ||
25 | - <% end %> | ||
26 | - <%= expirable_button @page, :spread, content, url if url %> | 18 | + <% if @page.allow_spread?(user) && !remove_content_button(:spread, @page) %> |
19 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page.id }) %> | ||
20 | + <%= expirable_button @page, :spread, content_tag( 'span', _('Spread this') ), url, {:class => 'colorbox'} if url %> | ||
27 | <% end %> | 21 | <% end %> |
28 | 22 | ||
29 | <% if !@page.gallery? && (@page.allow_create?(user) || (@page.parent && @page.parent.allow_create?(user))) %> | 23 | <% if !@page.gallery? && (@page.allow_create?(user) || (@page.parent && @page.parent.allow_create?(user))) %> |
30 | - <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %> | 24 | + <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale, @page) %> |
31 | <% content = _('Add translation') %> | 25 | <% content = _('Add translation') %> |
32 | <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %> | 26 | <% 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 })%> | 27 | <% 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 %> | 28 | <%= expirable_button @page, :locale, content, url %> |
35 | <% end %> | 29 | <% end %> |
36 | 30 | ||
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)))) unless remove_content_button(:new) %> | 31 | + <%= 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)))) unless remove_content_button(:new, @page) %> |
38 | <% end %> | 32 | <% end %> |
39 | 33 | ||
40 | <% if @page.accept_uploads? && @page.allow_create?(user) %> | 34 | <% if @page.accept_uploads? && @page.allow_create?(user) %> |
41 | - <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:upload)%> | 35 | + <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:upload, @page)%> |
42 | <% end %> | 36 | <% end %> |
43 | 37 | ||
44 | - <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %> | 38 | + <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest, @page) %> |
45 | <% content = content_tag( 'span', _('Suggest an article') ) %> | 39 | <% content = content_tag( 'span', _('Suggest an article') ) %> |
46 | <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %> | 40 | <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %> |
47 | <% options = {:id => 'suggest-article-link'} %> | 41 | <% options = {:id => 'suggest-article-link'} %> |
app/views/content_viewer/versioned_article.html.erb
@@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
7 | <div id="article-actions"> | 7 | <div id="article-actions"> |
8 | <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> | 8 | <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> |
9 | 9 | ||
10 | - <% if @page.allow_edit?(user) && !remove_content_button(:undo) %> | 10 | + <% if @page.allow_edit?(user) && !remove_content_button(:undo, @page) %> |
11 | <% content = content_tag('span', _('Revert to this version')) %> | 11 | <% content = content_tag('span', _('Revert to this version')) %> |
12 | <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id, :version => @version }) %> | 12 | <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id, :version => @version }) %> |
13 | <%= expirable_button @page, :undo, content, url, :id => 'article-revert-version-link' %> | 13 | <%= expirable_button @page, :undo, content, url, :id => 'article-revert-version-link' %> |
app/views/enterprise_registration/creation.html.erb
1 | <h1><%= _('Enterprise registration completed') %></h1> | 1 | <h1><%= _('Enterprise registration completed') %></h1> |
2 | +<p><%= _("Your enterprise (%s) was successfully registered.") % @enterprise.name %></p> | ||
3 | +<p><%= link_to _('You can manage your enterprise now.'), @enterprise.admin_url %></p> | ||
2 | 4 | ||
3 | -<p> | ||
4 | -<%= _("Your enterprise (%s) was successfully registered.") % @enterprise.name %> | ||
5 | -</p> | 5 | +<%= render :partial => 'shared/template_welcome_page', :locals => {:template => @enterprise.template, :header => _("What can I do with a %s?")} %> |
6 | + | ||
7 | +<% button_bar do %> | ||
8 | + <%= button :back, _('Back'), {:controller => 'memberships', :action => 'index', :profile => user.identifier} %> | ||
9 | +<% end %> | ||
6 | 10 | ||
7 | -<p> | ||
8 | -<%= link_to _('You can manage your enterprise now.'), @enterprise.admin_url %> | ||
9 | -</p> |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +<ul class="profile-list"> | ||
2 | + <% profiles.each do |profile| %> | ||
3 | + <li> | ||
4 | + <%= link_to_profile profile_image(profile) + '<br/>' + profile.short_name, | ||
5 | + profile.identifier, :class => 'profile-link' %> | ||
6 | + <div class="controll"> | ||
7 | + <%= button_without_text :remove, content_tag('span',_('remove')), | ||
8 | + { :action => 'remove', :id => profile.id }, | ||
9 | + :title => _('remove') %> | ||
10 | + <%= button_without_text 'menu-mail', content_tag('span',_('contact')), | ||
11 | + profile.url.merge(:controller => 'contact', :action => 'new', :profile => profile.identifier), | ||
12 | + :title => _('contact') %> | ||
13 | + </div><!-- end class="controll" --> | ||
14 | + </li> | ||
15 | + <% end %> | ||
16 | +</ul> |
@@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
1 | +<h1><%= _("Connections with %s") % @suggestion.suggestion.name %></h1> | ||
2 | + | ||
3 | +<% button_bar do %> | ||
4 | + <%= button(:back, _('Go to friends list'), :controller => 'friends') %> | ||
5 | +<% end %> | ||
6 | + | ||
7 | +<%= render :partial => 'shared/profile_connections', :locals => { :suggestion => @suggestion, :tags => @tags, :profiles => @profiles } %> |
app/views/friends/index.html.erb
@@ -10,46 +10,28 @@ | @@ -10,46 +10,28 @@ | ||
10 | <%= link_to _('Do you want to see other people in this environment?'), :controller => 'search', :action => 'assets', :asset => 'people' %> | 10 | <%= link_to _('Do you want to see other people in this environment?'), :controller => 'search', :action => 'assets', :asset => 'people' %> |
11 | </em> | 11 | </em> |
12 | </p> | 12 | </p> |
13 | - <% else %> | ||
14 | - <% button_bar do %> | ||
15 | - <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> | ||
16 | - <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> | ||
17 | - <% unless @plugins.dispatch(:remove_invite_friends_button).include?(true) %> | ||
18 | - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %> | ||
19 | - <% end %> | ||
20 | - <% end %> | ||
21 | <% end %> | 13 | <% end %> |
22 | 14 | ||
23 | - <ul class="profile-list"> | ||
24 | - <% @friends.each do |friend| %> | ||
25 | - <li> | ||
26 | - <%= link_to_profile profile_image(friend) + '<br/>' + friend.short_name, | ||
27 | - friend.identifier, :class => 'profile-link' %> | ||
28 | - <div class="controll"> | ||
29 | - <%= link_to content_tag('span',_('remove')), | ||
30 | - { :action => 'remove', :id => friend.id }, | ||
31 | - :class => 'button icon-remove', | ||
32 | - :title => _('remove') %> | ||
33 | - <%= link_to content_tag('span',_('contact')), | ||
34 | - friend.url.merge(:controller => 'contact', :action => 'new', :profile => friend.identifier), | ||
35 | - :class => 'button icon-menu-mail', | ||
36 | - :title => _('contact') %> | ||
37 | - </div><!-- end class="controll" --> | ||
38 | - </li> | ||
39 | - <% end %> | ||
40 | - </ul> | ||
41 | - <div id='pagination-friends'> | ||
42 | - <%= pagination_links @friends, :param_name => 'npage' %> | ||
43 | - </div> | ||
44 | - | ||
45 | <% button_bar do %> | 15 | <% button_bar do %> |
46 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> | 16 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> |
47 | <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> | 17 | <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> |
48 | <% unless @plugins.dispatch(:remove_invite_friends_button).include?(true) %> | 18 | <% unless @plugins.dispatch(:remove_invite_friends_button).include?(true) %> |
49 | - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %> | 19 | + <%= button(:person, _('Invite people'), :controller => 'invite', :action => 'invite_friends') %> |
50 | <% end %> | 20 | <% end %> |
51 | <% end %> | 21 | <% end %> |
22 | + | ||
23 | + <%= render :partial => 'profile_list', :locals => { :profiles => @friends } %> | ||
24 | + | ||
25 | + <br style="clear:both" /> | ||
26 | + <%= pagination_links @friends, :param_name => 'npage' %> | ||
52 | <% end %> | 27 | <% end %> |
53 | 28 | ||
54 | -</div><!-- end id="manage_friends" --> | 29 | +<% unless @suggestions.empty? %> |
30 | + <br style="clear:both" /> | ||
31 | + <h2><%= _("Friends suggestions") %></h2> | ||
32 | + <div class="profiles-suggestions"> | ||
33 | + <%= render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => 12 } %> | ||
34 | + </div> | ||
35 | +<% end %> | ||
55 | 36 | ||
37 | +</div><!-- end id="manage_friends" --> |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +<h1><%= _("Friends suggestions for %s") % profile.name %></h1> | ||
2 | + | ||
3 | +<% button_bar do %> | ||
4 | + <%= button(:back, _('Go to friends list'), :controller => 'friends') %> | ||
5 | +<% end %> | ||
6 | + | ||
7 | +<div class="profiles-suggestions"> | ||
8 | + <%= render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => 12 } %> | ||
9 | +</div> |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +<% default_message = defined?(default_message) ? default_message : false %> | ||
2 | + | ||
3 | +<div id='thanks-for-signing'> | ||
4 | + <h1><%= _("Welcome to %s!") % environment.name %></h1> | ||
5 | + <% if environment.has_custom_welcome_screen? && !default_message %> | ||
6 | + <%= environment.settings[:signup_welcome_screen_body].html_safe %> | ||
7 | + <% else %> | ||
8 | + <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3> | ||
9 | + <% if @display_confirmation_tips %> | ||
10 | + <p><%= _("Firstly, some tips for getting started:") %></p> | ||
11 | + <h4><%= _("Confirm your account!") %></h4> | ||
12 | + <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p> | ||
13 | + <p><%= _("You won't appear as %s until your account is confirmed.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> | ||
14 | + <% else %> | ||
15 | + <h4><%= _("Wait for admin approvement!") %></h4> | ||
16 | + <p><%= _("The administrators will evaluate your signup request for approvement.") %></p> | ||
17 | + <p><%= _("You won't appear as %s until your account is approved.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> | ||
18 | + <% end %> | ||
19 | + <h4><%= _("What to do next?") %></h4> | ||
20 | + <p><%= _("Access your %s and see your face on the network!") % | ||
21 | + (user.present? ? link_to(_('Profile'), {:controller => 'profile', :profile => user.identifier}, :target => '_blank') : 'Profile') %> | ||
22 | + <%= _("You can also explore your %s to customize your profile. Here are some %s on what you can do there.") % | ||
23 | + [user.present? ? link_to(_('Control Panel'), {:controller => 'profile_editor', :profile => user.identifier}, :target => '_blank') : 'Control Panel', | ||
24 | + link_to(_('tips'), {:controller => 'doc', :action => 'topic', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank')] %></p> | ||
25 | + <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :action => 'topic', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p> | ||
26 | + <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p> | ||
27 | + <p><%= _("Start exploring and have fun!") %></p> | ||
28 | + <% end %> | ||
29 | + <%= render :partial => 'shared/template_welcome_page', :locals => {:template => @person_template, :header => _("What can I do as a %s?")} %> | ||
30 | +</div> |
@@ -0,0 +1,8 @@ | @@ -0,0 +1,8 @@ | ||
1 | +<br/> | ||
2 | + | ||
3 | +<%= link_to ('Personalize invitation mail'), nil, :onclick => "jQuery('#invitation-mail_template').show(); return false;" %> | ||
4 | + | ||
5 | +<div id='invitation-mail_template' style='display:none'> | ||
6 | + <%= h _("Now enter an invitation message. You must keep the <url> code in your invitation text. When your friends receive the invitation e-mail, <url> will be replaced by a link that they need to click to activate their account. <user> and <friend> codes will be replaced by your name and friend name, but they are optional.") %> | ||
7 | + <%= labelled_form_field(_('Invitation text:'), text_area_tag(:mail_template, mail_template, :cols => 72, :rows => 8)) %> | ||
8 | +</div> |
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +<% header ||='h2' %> | ||
2 | +<<%= header %>><%= _('Step 1 of 2: Select address book') %></<%= header %>> | ||
3 | + | ||
4 | +<%= form_tag do %> | ||
5 | + | ||
6 | + <%= [ | ||
7 | + radio_button_tag(:import_from, "manual", @import_from == "manual", :onclick => 'hide_invite_friend_login_password()') + content_tag('label', _('Manually (empty field)'), :for => "import_from_manual"), | ||
8 | + radio_button_tag(:import_from, "gmail", @import_from == "gmail", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Gmail', :for => 'import_from_gmail'), | ||
9 | + radio_button_tag(:import_from, "yahoo", @import_from == "yahoo", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Yahoo', :for => "import_from_yahoo"), | ||
10 | + radio_button_tag(:import_from, "hotmail", @import_from == "hotmail", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Hotmail', :for => "import_from_hotmail") | ||
11 | + ].join("\n<br/>\n") %> | ||
12 | + | ||
13 | + <script type="text/javascript"> | ||
14 | + function hide_invite_friend_login_password() { | ||
15 | + $('invite-friends-login-password').hide(); | ||
16 | + } | ||
17 | + function show_invite_friend_login_password(option) { | ||
18 | + if (option == 'hotmail') { | ||
19 | + $('hotmail_username_tip').show(); | ||
20 | + } else { | ||
21 | + $('hotmail_username_tip').hide(); | ||
22 | + } | ||
23 | + $('invite-friends-login-password').show(); | ||
24 | + $('login').focus(); | ||
25 | + } | ||
26 | + </script> | ||
27 | + <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>> | ||
28 | + <div id='hotmail_username_tip'> | ||
29 | + <%= ui_icon('ui-icon-alert') %> | ||
30 | + <%= _('Please type your username in the format yourname@example.com') %> | ||
31 | + </div> | ||
32 | + | ||
33 | + <%= labelled_form_field(_("Username") + ":", text_field_tag(:login, @login)) %> | ||
34 | + <%= labelled_form_field(_("Password") + ":", password_field_tag(:password)) %> | ||
35 | + </div> | ||
36 | + | ||
37 | + <% button_bar do %> | ||
38 | + <%= submit_button(:forward, _("Next")) %> | ||
39 | + <% end %> | ||
40 | + <p><%= _("We won't store your password or contact anyone without your permission.") %></p> | ||
41 | +<% end %> |
@@ -0,0 +1,42 @@ | @@ -0,0 +1,42 @@ | ||
1 | +<% if profile.person? %> | ||
2 | + <h1><%= _('Ask for friendship') %></h1> | ||
3 | + <% description = _('You can search for user profiles and ask them to become your friends.') %> | ||
4 | +<% else %> | ||
5 | + <h1><%= _('Invite people to join') %></h1> | ||
6 | + <% description = _('You can search for user profiles and invite them to join this group.') %> | ||
7 | +<% end %> | ||
8 | + | ||
9 | +<h3> | ||
10 | + <%= _("Choose person by:") %> | ||
11 | +</h3> | ||
12 | + | ||
13 | +<p> | ||
14 | + <%= labelled_radio_button _("Name"), :invite_friend_by, 1, true, :id => "invite_friend_by_name", :class => "invite_friend_by" %> | ||
15 | + <%= labelled_radio_button _("Email"), :invite_friend_by, 2, false, :id => "invite_friend_by_email", :class => "invite_friend_by" %> | ||
16 | +</p> | ||
17 | + | ||
18 | +<div class='invite_by_name'> | ||
19 | + <p><%= description %></p> | ||
20 | + <%= form_tag :action => 'invite_registered_friend' do %> | ||
21 | + <% search_action = url_for(:action => 'search') %> | ||
22 | + <%= token_input_field_tag( | ||
23 | + :q, 'search-people', search_action, | ||
24 | + { :hint_text => _('Type in the person\'s %{search_fields}') % {:search_fields => @search_fields}, | ||
25 | + :focus => false }) %> | ||
26 | + | ||
27 | + <% button_bar do %> | ||
28 | + <%= submit_button('save', _('Invite'))%> | ||
29 | + <%= button('cancel', _('Cancel'), profile.url)%> | ||
30 | + <% end %> | ||
31 | + <% end %> | ||
32 | +</div> | ||
33 | + | ||
34 | +<div class='invite_by_email' style="display: none;"> | ||
35 | + <h2><%= _('Invite people from my e-mail contacts') %></h2> | ||
36 | + <% header = 'h3' %> | ||
37 | + | ||
38 | +<%= render :partial => 'invite/select_address_book', :locals => {:header => header} %> | ||
39 | +</div> | ||
40 | + | ||
41 | +<div id="loadingScreen"></div> | ||
42 | +<%= javascript_include_tag 'invite' %> |
app/views/invite/select_address_book.html.erb
@@ -1,51 +0,0 @@ | @@ -1,51 +0,0 @@ | ||
1 | -<% if profile.person? %> | ||
2 | - <h1><%= _('Invite your friends') %></h1> | ||
3 | -<% else %> | ||
4 | - <h1><%= _('Invite your friends to join %s') % profile.name %></h1> | ||
5 | -<% end %> | ||
6 | - | ||
7 | -<h2><%= _('Step 1 of 2: Select address book') %></h2> | ||
8 | - | ||
9 | -<%= form_tag do %> | ||
10 | - | ||
11 | - <%= [ | ||
12 | - radio_button_tag(:import_from, "manual", @import_from == "manual", :onclick => 'hide_invite_friend_login_password()') + content_tag('label', _('Manually (empty field)'), :for => "import_from_manual"), | ||
13 | - radio_button_tag(:import_from, "gmail", @import_from == "gmail", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Gmail', :for => 'import_from_gmail'), | ||
14 | - radio_button_tag(:import_from, "yahoo", @import_from == "yahoo", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Yahoo', :for => "import_from_yahoo"), | ||
15 | - radio_button_tag(:import_from, "hotmail", @import_from == "hotmail", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Hotmail', :for => "import_from_hotmail") | ||
16 | - ].join("\n<br/>\n") %> | ||
17 | - | ||
18 | - <script type="text/javascript"> | ||
19 | - function hide_invite_friend_login_password() { | ||
20 | - $('invite-friends-login-password').hide(); | ||
21 | - } | ||
22 | - function show_invite_friend_login_password(option) { | ||
23 | - if (option == 'hotmail') { | ||
24 | - $('hotmail_username_tip').show(); | ||
25 | - } else { | ||
26 | - $('hotmail_username_tip').hide(); | ||
27 | - } | ||
28 | - $('invite-friends-login-password').show(); | ||
29 | - $('login').focus(); | ||
30 | - } | ||
31 | - </script> | ||
32 | - <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>> | ||
33 | - <div id='hotmail_username_tip'> | ||
34 | - <%= ui_icon('ui-icon-alert') %> | ||
35 | - <%= _('Please type your username in the format yourname@example.com') %> | ||
36 | - </div> | ||
37 | - | ||
38 | - <%= labelled_form_field(_("Username") + ":", text_field_tag(:login, @login)) %> | ||
39 | - <%= labelled_form_field(_("Password") + ":", password_field_tag(:password)) %> | ||
40 | - </div> | ||
41 | - | ||
42 | - <% button_bar do %> | ||
43 | - <%= submit_button(:forward, _("Next")) %> | ||
44 | - <% end %> | ||
45 | - <p><%= _("We won't store your password or contact anyone without your permission.") %></p> | ||
46 | -<% end %> | ||
47 | - | ||
48 | -<div id="loadingScreen"></div> | ||
49 | - | ||
50 | - | ||
51 | - |
app/views/invite/select_friends.html.erb
1 | <%= render :partial => 'invite/dialog_wait_loading', :locals => {:contact_list => @contact_list.id } if @import_from != 'manual' %> | 1 | <%= render :partial => 'invite/dialog_wait_loading', :locals => {:contact_list => @contact_list.id } if @import_from != 'manual' %> |
2 | 2 | ||
3 | <% if profile.person? %> | 3 | <% if profile.person? %> |
4 | - <h1><%= _('Invite your friends') %></h1> | 4 | + <h1><%= _('Invite people') %></h1> |
5 | <% else %> | 5 | <% else %> |
6 | - <h1><%= _('Invite your friends to join %s') % profile.name %></h1> | 6 | + <h1><%= _('Invite people to join') %></h1> |
7 | <% end %> | 7 | <% end %> |
8 | 8 | ||
9 | 9 | ||
10 | -<h2><%= _('Step 2 of 2: Selecting Friends') %></h2> | 10 | +<h2><%= _('Step 2 of 2: Selecting People') %></h2> |
11 | 11 | ||
12 | -<%= button(:back, _('Back'), { :action => 'select_address_book' }, :id => 'invitation_back_button') %> | 12 | +<%= button(:back, _('Back'), { :action => 'invite_friends' }, :id => 'invitation_back_button') %> |
13 | 13 | ||
14 | <p> | 14 | <p> |
15 | -<%= _('Indicate which friends you want to invite.') %> | 15 | +<%= _('Indicate which people you want to invite.') %> |
16 | </p> | 16 | </p> |
17 | 17 | ||
18 | <%= form_tag do %> | 18 | <%= form_tag do %> |
@@ -30,16 +30,9 @@ | @@ -30,16 +30,9 @@ | ||
30 | </div> | 30 | </div> |
31 | <% end -%> | 31 | <% end -%> |
32 | 32 | ||
33 | - <br/> | ||
34 | - | ||
35 | - <%= link_to ('Personalize invitation mail'), nil, :onclick => "jQuery('#invitation-mail_template').show(); return false;" %> | ||
36 | - | ||
37 | - <div id='invitation-mail_template' style='display:none'> | ||
38 | - <%= h _("Now enter an invitation message. You must keep the <url> code in your invitation text. When your friends receive the invitation e-mail, <url> will be replaced by a link that they need to click to activate their account. <user> and <friend> codes will be replaced by your name and friend name, but they are optional.") %> | ||
39 | - <%= labelled_form_field(_('Invitation text:'), text_area_tag(:mail_template, @mail_template, :cols => 72, :rows => 8)) %> | ||
40 | - </div> | 33 | + <%= render :partial => 'invite/personalize_invitation_mail', :locals => {:mail_template => @mail_template } %> |
41 | 34 | ||
42 | <% button_bar do %> | 35 | <% button_bar do %> |
43 | - <%= submit_button(:ok, _("Invite my friends!")) %> | 36 | + <%= submit_button(:ok, _("Invite!")) %> |
44 | <% end %> | 37 | <% end %> |
45 | <% end %> | 38 | <% end %> |
app/views/layouts/_javascript.html.erb
@@ -2,8 +2,8 @@ | @@ -2,8 +2,8 @@ | ||
2 | 'jquery-2.1.1.min', 'jquery-migrate-1.2.1', | 2 | 'jquery-2.1.1.min', 'jquery-migrate-1.2.1', |
3 | 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox', | 3 | 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox', |
4 | 'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate', | 4 | 'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate', |
5 | -'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', | ||
6 | -'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow', | 5 | +'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', 'jquery.typewatch', 'jquery.textchange', |
6 | +'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow', 'select-or-die/_src/selectordie', | ||
7 | 'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'application.js', 'rails.js', 'inputosaurus.js', :cache => 'cache/application' %> | 7 | 'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'application.js', 'rails.js', 'inputosaurus.js', :cache => 'cache/application' %> |
8 | 8 | ||
9 | <% language = FastGettext.locale %> | 9 | <% language = FastGettext.locale %> |
app/views/layouts/_user.html.erb
@@ -10,16 +10,17 @@ | @@ -10,16 +10,17 @@ | ||
10 | <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %> | 10 | <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %> |
11 | <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_exec(&content) }.join("") %> | 11 | <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_exec(&content) }.join("") %> |
12 | 12 | ||
13 | - <div id='inlineLoginBox' style='display: none;'> | ||
14 | - <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> | ||
15 | - </div> | 13 | + <div id='inlineLoginBox' style='display: none;'> |
14 | + <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> | ||
15 | + </div> | ||
16 | 16 | ||
17 | - <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> | ||
18 | - <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%> | ||
19 | - <% end %> | ||
20 | - </span> | 17 | + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> |
18 | + <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%> | ||
19 | + <% end %> | ||
20 | + | ||
21 | + </span> | ||
21 | <% end %> | 22 | <% end %> |
22 | - <form action="/search" id="top-search" class="search_form clean" method="get"> | 23 | + <form action="/search/articles" id="top-search" class="search_form clean" method="get"> |
23 | <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> | 24 | <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> |
24 | <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div> | 25 | <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div> |
25 | <%= javascript_tag 'jQuery("#user form input").hint();' %> | 26 | <%= javascript_tag 'jQuery("#user form input").hint();' %> |
@@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
1 | +<h1><%= _("Connections with %s") % @suggestion.suggestion.name %></h1> | ||
2 | + | ||
3 | +<% button_bar do %> | ||
4 | + <%= button(:back, _('Go to groups list'), :controller => 'memberships') %> | ||
5 | +<% end %> | ||
6 | + | ||
7 | +<%= render :partial => 'shared/profile_connections', :locals => { :suggestion => @suggestion, :tags => @tags, :profiles => @profiles } %> |
app/views/memberships/index.html.erb
@@ -16,6 +16,8 @@ | @@ -16,6 +16,8 @@ | ||
16 | <%= labelled_select(_('Filter')+': ', :filter_type, :first, :last, @filter, type_collection, :id => 'memberships_filter')%> | 16 | <%= labelled_select(_('Filter')+': ', :filter_type, :first, :last, @filter, type_collection, :id => 'memberships_filter')%> |
17 | </p> | 17 | </p> |
18 | 18 | ||
19 | +<p><%= link_to _('See some suggestions of communities...'), :action => 'suggest' %></p> | ||
20 | + | ||
19 | <% if @memberships.empty? %> | 21 | <% if @memberships.empty? %> |
20 | <p> | 22 | <p> |
21 | <em><%= _('No groups to list') %></em> | 23 | <em><%= _('No groups to list') %></em> |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +<h1><%= _("Communities suggestions for %s") % profile.name %></h1> | ||
2 | + | ||
3 | +<% button_bar do %> | ||
4 | + <%= button(:back, _('Go to groups list'), :controller => 'memberships') %> | ||
5 | +<% end %> | ||
6 | + | ||
7 | +<div class="profiles-suggestions"> | ||
8 | + <%= render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => 12 } %> | ||
9 | +</div> |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +<h1><%= _('Community created') %></h1> | ||
2 | +<p><%= _("Your community (%s) was successfully created.") % @community.name %></p> | ||
3 | +<p><%= link_to _('You can manage your community now.'), @community.admin_url %></p> | ||
4 | + | ||
5 | +<%= render :partial => 'shared/template_welcome_page', :locals => {:template => @community.template, :header => _("What can I do with a %s?")} %> | ||
6 | + | ||
7 | +<% button_bar do %> | ||
8 | + <%= button :back, _('Back'), @back_to %> | ||
9 | +<% end %> |
app/views/profile/_upload_image.html.erb
@@ -10,5 +10,5 @@ | @@ -10,5 +10,5 @@ | ||
10 | </div> | 10 | </div> |
11 | </div> | 11 | </div> |
12 | </div> | 12 | </div> |
13 | -<div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div> | 13 | +<div title='<%#= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div> |
14 | <br/> | 14 | <br/> |
app/views/profile/friends.html.erb
@@ -18,7 +18,7 @@ | @@ -18,7 +18,7 @@ | ||
18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> | 18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> |
19 | <% if user == profile %> | 19 | <% if user == profile %> |
20 | <%= button :edit, _('Manage my friends'), :controller => 'friends', :action => 'index', :profile => profile.identifier %> | 20 | <%= button :edit, _('Manage my friends'), :controller => 'friends', :action => 'index', :profile => profile.identifier %> |
21 | - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %> | 21 | + <%= button(:person, _('Invite people'), :controller => 'invite', :action => 'invite_friends') %> |
22 | <% end %> | 22 | <% end %> |
23 | <% end %> | 23 | <% end %> |
24 | 24 |
app/views/profile/members.html.erb
@@ -18,7 +18,7 @@ | @@ -18,7 +18,7 @@ | ||
18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> | 18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> |
19 | <% if profile.community? and user %> | 19 | <% if profile.community? and user %> |
20 | <% if user.has_permission?(:invite_members, profile) %> | 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' %> | 21 | + <%= button :person, _('Invite people to join'), :controller => 'invite', :action => 'invite_friends' %> |
22 | <% end %> | 22 | <% end %> |
23 | <% if user.has_permission?(:send_mail_to_members, profile) %> | 23 | <% if user.has_permission?(:send_mail_to_members, profile) %> |
24 | <%= button :send, _('Send e-mail to members'), :controller => 'profile', :action => 'send_mail' %> | 24 | <%= button :send, _('Send e-mail to members'), :controller => 'profile', :action => 'send_mail' %> |
app/views/profile_editor/_moderation.html.erb
1 | <h2><%= _('Moderation options') %></h2> | 1 | <h2><%= _('Moderation options') %></h2> |
2 | <% if profile.community? %> | 2 | <% if profile.community? %> |
3 | <div style='margin-bottom: 1em'> | 3 | <div style='margin-bottom: 1em'> |
4 | + <h4><%= _('Invitation moderation:')%></h4> | ||
5 | + </div> | ||
6 | + <div style='margin-bottom: 0.5em'> | ||
7 | + <%= check_box(:profile_data, :allow_members_to_invite, :style => 'float: left') %> | ||
8 | + <div style='margin-left: 30px'> | ||
9 | + <%= _('Allow all members to send invitation (Default: only administrator)') %> | ||
10 | + </div> | ||
11 | + <br> | ||
12 | + <div class = 'invite_friends_only' > | ||
13 | + <%= check_box(:profile_data, :invite_friends_only, :style => 'float: left') %> | ||
14 | + <div style='margin-left: 30px'> | ||
15 | + <%= _('Allow members to invite only friends (Default: all users)') %> | ||
16 | + </div> | ||
17 | + </div> | ||
18 | + </div> | ||
19 | + <br> | ||
20 | + | ||
21 | + <div style='margin-bottom: 1em'> | ||
4 | <%= _('New members must be approved:')%> | 22 | <%= _('New members must be approved:')%> |
5 | </div> | 23 | </div> |
6 | <div style='margin-bottom: 0.5em'> | 24 | <div style='margin-bottom: 0.5em'> |
@@ -33,3 +51,5 @@ | @@ -33,3 +51,5 @@ | ||
33 | <%= _('<strong>After</strong> being published in this group (a moderator can always remove publicated articles later).') %> | 51 | <%= _('<strong>After</strong> being published in this group (a moderator can always remove publicated articles later).') %> |
34 | </div> | 52 | </div> |
35 | </div> | 53 | </div> |
54 | + | ||
55 | +<%= javascript_include_tag('invite') %> |
app/views/profile_editor/edit.html.erb
@@ -52,6 +52,12 @@ | @@ -52,6 +52,12 @@ | ||
52 | 'profile_data[redirect_l10n]', true, @profile.redirect_l10n | 52 | 'profile_data[redirect_l10n]', true, @profile.redirect_l10n |
53 | )%> | 53 | )%> |
54 | 54 | ||
55 | + <h2><%= _('Suggestions') %></h2> | ||
56 | + <%= labelled_check_box( | ||
57 | + _('Send me relationship suggestions by email'), | ||
58 | + 'profile_data[email_suggestions]', true, @profile.email_suggestions | ||
59 | + )%> | ||
60 | + | ||
55 | <%= | 61 | <%= |
56 | @plugins.dispatch(:profile_editor_extras).map do |content| | 62 | @plugins.dispatch(:profile_editor_extras).map do |content| |
57 | content.kind_of?(Proc) ? self.instance_exec(&content) : content | 63 | content.kind_of?(Proc) ? self.instance_exec(&content) : content |
app/views/profile_editor/index.html.erb
@@ -68,6 +68,8 @@ | @@ -68,6 +68,8 @@ | ||
68 | 68 | ||
69 | <%= control_panel_button(_('Manage SPAM'), 'manage-spam', :controller => 'spam', :action => 'index') %> | 69 | <%= control_panel_button(_('Manage SPAM'), 'manage-spam', :controller => 'spam', :action => 'index') %> |
70 | 70 | ||
71 | + <%= control_panel_button(_('Edit welcome page'), 'welcome-page', :action => 'welcome_page') if has_welcome_page %> | ||
72 | + | ||
71 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> | 73 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> |
72 | <%= control_panel_button(button[:title], button[:icon], button[:url]) %> | 74 | <%= control_panel_button(button[:title], button[:icon], button[:url]) %> |
73 | <% end %> | 75 | <% end %> |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +<h1><%= _('Edit welcome page') %></h1> | ||
2 | + | ||
3 | +<%= labelled_form_for :welcome_page do |f| %> | ||
4 | + <%= error_messages_for :welcome_page %> | ||
5 | + | ||
6 | + <%= f.check_box(:published) %> | ||
7 | + <div class='explanation'> | ||
8 | + <%= _('Your welcome page will only be displayed if this options is selected.') %> | ||
9 | + </div> | ||
10 | + | ||
11 | + <%= f.text_area(:body, :cols => 40, :style => 'width: 100%', :class => 'mceEditor') %> | ||
12 | + <div class='explanation'> | ||
13 | + <%= _('This page will be displayed to the user after his signup with this template.') %> | ||
14 | + </div> | ||
15 | + | ||
16 | + <% button_bar do%> | ||
17 | + <%= submit_button('save', _('Save'), :cancel => @back_to) %> | ||
18 | + <% end %> | ||
19 | +<% end %> | ||
20 | + | ||
21 | +<%= render :file => 'shared/tiny_mce' %> |
app/views/profile_members/_index_buttons.html.erb
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | <%= button :back, _('Back'), :controller => 'profile_editor' %> | 2 | <%= button :back, _('Back'), :controller => 'profile_editor' %> |
3 | <%= button :add, _('Add members'), :action => 'add_members' if profile.enterprise? %> | 3 | <%= button :add, _('Add members'), :action => 'add_members' if profile.enterprise? %> |
4 | <% if profile.community? and user.has_permission?(:invite_members, profile) %> | 4 | <% if profile.community? and user.has_permission?(:invite_members, profile) %> |
5 | - <%= button :search, _('Invite your friends to join %s') % profile.short_name, :controller => 'invite', :action => 'select_address_book' %> | 5 | + <%= button :person, _('Invite people to join'), :controller => 'invite', :action => 'invite_friends' %> |
6 | <% end %> | 6 | <% end %> |
7 | <% if profile.community? and user.has_permission?(:send_mail_to_members, profile) %> | 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' %> | 8 | <%= button :send, _('Send e-mail to members'), :controller => 'profile', :action => 'send_mail' %> |
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +<div id='search-content'> | ||
2 | + <% if @results %> | ||
3 | + <div class='results-found-message'> | ||
4 | + <%= _("%s results found") % @results.total_entries %> | ||
5 | + </div> | ||
6 | + | ||
7 | + <ul class='results-list'> | ||
8 | + <% @results.sort_by { |r| r.is_image? ? 0 : 1}.each do |result| %> | ||
9 | + <%= render :partial => partial_for_class(result.class), :locals => { :article => result } %> | ||
10 | + <% end %> | ||
11 | + </ul> | ||
12 | + | ||
13 | + <%= pagination_links @results %> | ||
14 | + <% end %> | ||
15 | +</div> |
app/views/profile_search/index.html.erb
@@ -3,17 +3,7 @@ | @@ -3,17 +3,7 @@ | ||
3 | 3 | ||
4 | <%= render :partial => 'shared/profile_search_form' %> | 4 | <%= render :partial => 'shared/profile_search_form' %> |
5 | 5 | ||
6 | - <% if @results %> | ||
7 | - <div class='results-found-message'> | ||
8 | - <%= _("%s results found") % @results.total_entries %> | ||
9 | - </div> | 6 | + <%= render :partial => 'results-list' %> |
10 | 7 | ||
11 | - <ul class='results-list'> | ||
12 | - <% @results.sort_by { |r| r.is_image? ? 0 : 1}.each do |result| %> | ||
13 | - <%= render :partial => partial_for_class(result.class), :locals => { :article => result } %> | ||
14 | - <% end %> | ||
15 | - </ul> | ||
16 | - | ||
17 | - <%= pagination_links @results %> | ||
18 | - <% end %> | ||
19 | </div> | 8 | </div> |
9 | +<%= javascript_include_tag 'search' %> |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +jQuery('#search-content').html('<%= escape_javascript(render :partial => "results-list") %>'); |
app/views/search/_compact_profile.html.erb
1 | -<% filter_label = profile.send(@filter + '_label') %> | ||
2 | -<% filter_label += show_date(profile.created_at) if @filter == 'more_recent' %> | 1 | +<% filter_label = profile.send(@order + '_label') %> |
2 | +<% filter_label += show_date(profile.created_at) if @order == 'more_recent' %> | ||
3 | <li class="search-profile-item"> | 3 | <li class="search-profile-item"> |
4 | <%= profile_image_link profile, :portrait, 'div', filter_label %> | 4 | <%= profile_image_link profile, :portrait, 'div', filter_label %> |
5 | </li> | 5 | </li> |