Commit 38b43fc7d5121ed574018483b468bb7f8a2ebef8

Authored by Leandro Santos
2 parents 921031b3 54c2e243

fixing conflict

Showing 527 changed files with 25348 additions and 8883 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 527 files displayed.

AUTHORS.md
... ... @@ -92,6 +92,7 @@ Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
92 92 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
93 93 Daniel Bucher <daniel.bucher88@gmail.com>
94 94 Daniel Cunha <daniel@colivre.coop.br>
  95 +daniel <dtygel@eita.org.br>
95 96 David Carlos <ddavidcarlos1392@gmail.com>
96 97 diegoamc <diegoamc90@gmail.com>
97 98 Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>
... ... @@ -120,6 +121,7 @@ Diego Araujo + Rodrigo Souto + Rafael Manzo &lt;rr.manzo@gmail.com&gt;
120 121 Diego + Jefferson <diegoamc90@gmail.com>
121 122 Diego Martinez <diegoamc90@gmail.com>
122 123 Diego + Renan <renanteruoc@gmail.com>
  124 +dtygel <dtygel@gmail.com>
123 125 DylanGuedes <djmgguedes@gmail.com>
124 126 Eduardo Passos <eduardo@risa.localdomain.localhost>
125 127 Eduardo Passos <eduardosteps@gmail.com>
... ... @@ -144,6 +146,7 @@ Italo Valcy &lt;italo@dcc.ufba.br&gt;
144 146 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>
145 147 Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>
146 148 Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com>
  149 +Jérôme Jutteau <j.jutteau@gmail.com>
147 150 João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com>
148 151 João da Silva <jaodsilv@linux.ime.usp.br>
149 152 João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>
... ... @@ -247,8 +250,10 @@ Tallys Martins &lt;tallysmartins@gmail.com&gt;
247 250 Tallys Martins <tallysmartins@yahoo.com.br>
248 251 tallys <tallys@tallys>
249 252 tallys <tallys@tallys.(none)>
  253 +Thiago Casotti <thiago.casotti@uol.com.br>
250 254 Thiago Zoroastro <thiago.zoroastro@bol.com.br>
251 255 Tuux <tuxa@galaxie.eu.org>
  256 +TWS <tablettws@gmail.com>
252 257 Valessio Brito <contato@valessiobrito.com.br>
253 258 Valessio Brito <contato@valessiobrito.info>
254 259 Valessio Brito <valessio@gmail.com>
... ...
Gemfile
... ... @@ -20,18 +20,17 @@ gem &#39;locale&#39;, &#39;~&gt; 2.0.5&#39;
20 20 gem 'whenever', :require => false
21 21 gem 'eita-jrails', '>= 0.9.5', :require => 'jrails'
22 22  
23   -group :assets do
24   - gem 'uglifier', '>= 1.0.3'
25   - gem 'sass-rails'
26   -end
  23 +# asset pipeline
  24 +gem 'uglifier', '>= 1.0.3'
  25 +gem 'sass-rails'
27 26  
28 27 group :production do
29 28 gem 'dalli', '~> 2.7.0'
30 29 end
31 30  
32 31 group :test do
33   - gem 'rspec', '~> 2.10.0'
34   - gem 'rspec-rails', '~> 2.10.1'
  32 + gem 'rspec', '~> 2.14.0'
  33 + gem 'rspec-rails', '~> 2.14.1'
35 34 gem 'mocha', '~> 1.1.0', :require => false
36 35 end
37 36  
... ...
INSTALL.chat.md
1   -XMPP/Chat Setup
2   -===============
  1 +Automatic XMPP/Chat Setup
  2 +=========================
  3 +
  4 +Since Noosfero 1.2, the XMPP/Chat can be installed via `noosfero-chat` Debian
  5 +package. So you don't need to follow the manual instructions here if you
  6 +already have it installed on your system.
  7 +
  8 +But if you are going to install the `noosfero-chat` package on a system that
  9 +already has `noosfero` older 1.2 installed then you need to check if apache's
  10 +configuration file `/etc/apache2/sites-available/noosfero` has this line below:
  11 +
  12 + Include /usr/share/noosfero/util/chat/apache/xmpp.conf
  13 +
  14 +Manual XMPP/Chat Setup
  15 +======================
3 16  
4 17 The samples of config file to configure a XMPP/BOSH server with ejabberd,
5 18 postgresql and apache2 can be found at util/chat directory.
... ... @@ -8,7 +21,7 @@ This setup supposes that you are using Noosfero installed via Debian package
8 21 in a production environment.
9 22  
10 23 Steps
11   -=====
  24 +-----
12 25  
13 26 This is a step-by-step guide to get a XMPP service working, in a Debian system.
14 27  
... ... @@ -144,15 +157,8 @@ You should see a page with a message like that:
144 157  
145 158 ## 9. Test chat session
146 159  
147   -Open Noosfero console and execute:
148   -
149   ->> environment = Environment.default
150   ->> user = Person['guest']
151   ->> password = user.user.crypted_password
152   ->> login = user.jid
153   ->> RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind", :wait => 30, :hold => 1, :window => 5
154   -
155   -If you have luck, should see something like that:
  160 +Run `./script/noosfero-test-chat-session`. If you have luck, should see
  161 +something like that:
156 162  
157 163 Ruby-BOSH - SEND
158 164 <body window="5" rid="60265" xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" to="vagrant-debian-squeeze.vagrantup.com" wait="30" xmpp:version="1.0" hold="1"/>
... ...
INSTALL.https.md
... ... @@ -11,8 +11,8 @@ as below:
11 11  
12 12 # mkdir /etc/noosfero/ssl
13 13 # cd /etc/noosfero/ssl
14   - # openssl genrsa 1024 > noosfero.key
15   - # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert
  14 + # openssl genrsa 2048 > noosfero.key
  15 + # openssl req -new -x509 -sha256 -nodes -days $[10*365] -key noosfero.key > noosfero.cert
16 16 # cat noosfero.key noosfero.cert > noosfero.pem
17 17  
18 18 ## Web server configuration
... ...
INSTALL.md
... ... @@ -74,7 +74,7 @@ downloading from git
74 74  
75 75 Here we are cloning the noosfero repository from git. Note: you will need to install git before.
76 76  
77   - $ git clone git://gitorious.org/noosfero/noosfero.git current
  77 + $ git clone https://gitlab.com/noosfero/noosfero.git current
78 78 $ cd current
79 79 $ git checkout -b stable origin/stable
80 80  
... ...
app/controllers/admin/admin_panel_controller.rb
... ... @@ -71,22 +71,4 @@ class AdminPanelController &lt; AdminController
71 71 end
72 72 end
73 73 end
74   -
75   - def manage_organizations_status
76   - scope = environment.organizations
77   - @filter = params[:filter] || 'any'
78   - @title = "Organization profiles"
79   - @title = @title+" - "+@filter if @filter != 'any'
80   -
81   - if @filter == 'enabled'
82   - scope = scope.visible
83   - elsif @filter == 'disabled'
84   - scope = scope.disabled
85   - end
86   -
87   - scope = scope.order('name ASC')
88   -
89   - @q = params[:q]
90   - @collection = find_by_contents(:organizations, environment, scope, @q, {:per_page => 10, :page => params[:npage]})[:results]
91   - end
92 74 end
... ...
app/controllers/admin/organizations_controller.rb 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +class OrganizationsController < AdminController
  2 +
  3 + protect 'manage_environment_organizations', :environment
  4 +
  5 + def index
  6 + @filter = params[:filter] || 'any'
  7 + @title = _('Organization profiles')
  8 + @type = params[:type] || "any"
  9 + @types_filter = [[_('All'), 'any'], [_('Community'), 'Community'], [_('Enterprise'), 'Enterprise']]
  10 + @types_filter = @types_filter | @plugins.dispatch(:organization_types_filter_options)
  11 +
  12 + scope = @plugins.dispatch_first(:filter_manage_organization_scope, @type)
  13 + if scope.blank?
  14 + scope = environment.organizations
  15 + scope = scope.where(:type => @type) if @type != 'any'
  16 + end
  17 +
  18 + if @filter == 'enabled'
  19 + scope = scope.visible
  20 + elsif @filter == 'disabled'
  21 + scope = scope.disabled
  22 + end
  23 +
  24 + scope = scope.order('name ASC')
  25 +
  26 + @q = params[:q]
  27 + @collection = find_by_contents(:organizations, environment, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results]
  28 + end
  29 +
  30 + def activate
  31 + organization = environment.organizations.find(params[:id])
  32 + if organization.enable
  33 + render :text => (_('%s enabled') % organization.name).to_json
  34 + else
  35 + render :text => (_('%s could not be enabled') % organization.name).to_json
  36 + end
  37 + end
  38 +
  39 + def deactivate
  40 + organization = environment.organizations.find(params[:id])
  41 + if organization.disable
  42 + render :text => (_('%s disabled') % organization.name).to_json
  43 + else
  44 + render :text => (_('%s could not be disable') % organization.name).to_json
  45 + end
  46 + end
  47 +
  48 + def destroy
  49 + if request.post?
  50 + organization = environment.organizations.find(params[:id])
  51 + if organization && organization.destroy
  52 + render :text => (_('%s removed') % organization.name).to_json
  53 + else
  54 + render :text => (_('%s could not be removed') % organization.name).to_json
  55 + end
  56 + else
  57 + render :nothing => true
  58 + end
  59 + end
  60 +
  61 + private
  62 +
  63 + def per_page
  64 + 10
  65 + end
  66 +end
... ...
app/controllers/admin/role_controller.rb
... ... @@ -2,7 +2,7 @@ class RoleController &lt; AdminController
2 2 protect 'manage_environment_roles', :environment
3 3  
4 4 def index
5   - @roles = environment.roles.find(:all)
  5 + @roles = environment.roles.find(:all, :conditions => {:profile_id => nil})
6 6 end
7 7  
8 8 def new
... ...
app/controllers/application_controller.rb
... ... @@ -9,6 +9,7 @@ class ApplicationController &lt; ActionController::Base
9 9 before_filter :allow_cross_domain_access
10 10 before_filter :login_required, :if => :private_environment?
11 11 before_filter :verify_members_whitelist, :if => [:private_environment?, :user]
  12 + before_filter :redirect_to_current_user
12 13  
13 14 def verify_members_whitelist
14 15 render_access_denied unless user.is_admin? || environment.in_whitelist?(user)
... ... @@ -192,4 +193,15 @@ class ApplicationController &lt; ActionController::Base
192 193 def private_environment?
193 194 @environment.enabled?(:restrict_to_members)
194 195 end
  196 +
  197 + def redirect_to_current_user
  198 + if params[:profile] == '~'
  199 + if logged_in?
  200 + redirect_to params.merge(:profile => user.identifier)
  201 + else
  202 + render_not_found
  203 + end
  204 + end
  205 + end
  206 +
195 207 end
... ...
app/controllers/my_profile/cms_controller.rb
... ... @@ -112,6 +112,11 @@ class CmsController &lt; MyProfileController
112 112 end
113 113 end
114 114 end
  115 +
  116 + unless @article.kind_of?(RssFeed)
  117 + @escaped_body = CGI::escapeHTML(@article.body || '')
  118 + @escaped_abstract = CGI::escapeHTML(@article.abstract || '')
  119 + end
115 120 end
116 121  
117 122 def new
... ... @@ -143,7 +148,14 @@ class CmsController &lt; MyProfileController
143 148 klass = @type.constantize
144 149 article_data = environment.enabled?('articles_dont_accept_comments_by_default') ? { :accept_comments => false } : {}
145 150 article_data.merge!(params[:article]) if params[:article]
146   - @article = klass.new(article_data)
  151 + article_data.merge!(:profile => profile) if profile
  152 +
  153 + @article = if params[:clone]
  154 + current_article = profile.articles.find(params[:id])
  155 + current_article.copy_without_save
  156 + else
  157 + klass.new(article_data)
  158 + end
147 159  
148 160 parent = check_parent(params[:parent_id])
149 161 if parent
... ... @@ -220,7 +232,7 @@ class CmsController &lt; MyProfileController
220 232 if @errors.any?
221 233 render :action => 'upload_files', :parent_id => @parent_id
222 234 else
223   - session[:notice] = _('File(s) successfully uploaded')
  235 + session[:notice] = _('File(s) successfully uploaded')
224 236 if @back_to
225 237 redirect_to @back_to
226 238 elsif @parent
... ... @@ -357,7 +369,8 @@ class CmsController &lt; MyProfileController
357 369 @task.ip_address = request.remote_ip
358 370 @task.user_agent = request.user_agent
359 371 @task.referrer = request.referrer
360   - if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save
  372 + @task.requestor = current_person if logged_in?
  373 + if (logged_in? || verify_recaptcha(:model => @task, :message => _('Please type the words correctly'))) && @task.save
361 374 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.')
362 375 redirect_to @back_to
363 376 end
... ...
app/controllers/my_profile/friends_controller.rb
1 1 class FriendsController < MyProfileController
2   -
  2 +
3 3 protect 'manage_friends', :profile
4   -
  4 +
5 5 def index
6   - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page)
  6 + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page)
7 7 if is_cache_expired?(profile.manage_friends_cache_key(params))
8 8 @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage])
9 9 end
... ... @@ -18,7 +18,7 @@ class FriendsController &lt; MyProfileController
18 18 end
19 19  
20 20 def suggest
21   - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page)
  21 + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page)
22 22 end
23 23  
24 24 def remove_suggestion
... ... @@ -26,13 +26,13 @@ class FriendsController &lt; MyProfileController
26 26 redirect_to :action => 'suggest' unless @person
27 27 if @person && request.post?
28 28 profile.remove_suggestion(@person)
29   - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page)
  29 + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page)
30 30 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page }
31 31 end
32 32 end
33 33  
34 34 def connections
35   - @suggestion = profile.profile_suggestions.of_person.enabled.find_by_suggestion_id(params[:id])
  35 + @suggestion = profile.suggested_profiles.of_person.enabled.find_by_suggestion_id(params[:id])
36 36 if @suggestion
37 37 @tags = @suggestion.tag_connections
38 38 @profiles = @suggestion.profile_connections
... ...
app/controllers/my_profile/manage_products_controller.rb
... ... @@ -35,7 +35,7 @@ class ManageProductsController &lt; ApplicationController
35 35 end
36 36  
37 37 def categories_for_selection
38   - @category = Category.find(params[:category_id]) if params[:category_id]
  38 + @category = environment.categories.find_by_id params[:category_id]
39 39 @object_name = params[:object_name]
40 40 if @category
41 41 @categories = @category.children
... ... @@ -95,6 +95,20 @@ class ManageProductsController &lt; ApplicationController
95 95 end
96 96 end
97 97  
  98 + def show_category_tree
  99 + @category = environment.categories.find params[:category_id]
  100 + render :partial => 'selected_category_tree'
  101 + end
  102 +
  103 + def search_categories
  104 + @term = params[:term].downcase
  105 + conditions = ['LOWER(name) LIKE ? OR LOWER(name) LIKE ?', "#{@term}%", "% #{@term}%"]
  106 + @categories = ProductCategory.all :conditions => conditions, :limit => 10
  107 + render :json => (@categories.map do |category|
  108 + {:label => category.name, :value => category.id}
  109 + end)
  110 + end
  111 +
98 112 def add_input
99 113 @product = @profile.products.find(params[:id])
100 114 @input = @product.inputs.build
... ...
app/controllers/my_profile/maps_controller.rb
... ... @@ -16,6 +16,7 @@ class MapsController &lt; MyProfileController
16 16  
17 17 Profile.transaction do
18 18 if profile.update_attributes!(params[:profile_data])
  19 + BlockSweeper.expire_blocks profile.blocks.select{ |b| b.class == LocationBlock }
19 20 session[:notice] = _('Address was updated successfully!')
20 21 redirect_to :action => 'edit_location'
21 22 end
... ...
app/controllers/my_profile/memberships_controller.rb
... ... @@ -40,7 +40,7 @@ class MembershipsController &lt; MyProfileController
40 40 end
41 41  
42 42 def suggest
43   - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(per_page)
  43 + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(per_page)
44 44 end
45 45  
46 46 def remove_suggestion
... ... @@ -49,13 +49,13 @@ class MembershipsController &lt; MyProfileController
49 49 redirect_to :action => 'suggest' unless @community
50 50 if @community && request.post?
51 51 profile.remove_suggestion(@community)
52   - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(custom_per_page)
  52 + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(custom_per_page)
53 53 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page}
54 54 end
55 55 end
56 56  
57 57 def connections
58   - @suggestion = profile.profile_suggestions.of_community.enabled.find_by_suggestion_id(params[:id])
  58 + @suggestion = profile.suggested_profiles.of_community.enabled.find_by_suggestion_id(params[:id])
59 59 if @suggestion
60 60 @tags = @suggestion.tag_connections
61 61 @profiles = @suggestion.profile_connections
... ...
app/controllers/my_profile/profile_design_controller.rb
... ... @@ -4,11 +4,19 @@ class ProfileDesignController &lt; BoxOrganizerController
4 4  
5 5 protect 'edit_profile_design', :profile
6 6  
7   - before_filter :protect_fixed_block, :only => [:save, :move_block]
  7 + before_filter :protect_uneditable_block, :only => [:save]
  8 + before_filter :protect_fixed_block, :only => [:move_block]
  9 +
  10 + def protect_uneditable_block
  11 + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
  12 + if !current_person.is_admin? && !block.editable?
  13 + render_access_denied
  14 + end
  15 + end
8 16  
9 17 def protect_fixed_block
10 18 block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
11   - if block.fixed && !current_person.is_admin?
  19 + if !current_person.is_admin? && !block.movable?
12 20 render_access_denied
13 21 end
14 22 end
... ...
app/controllers/my_profile/profile_members_controller.rb
... ... @@ -58,6 +58,7 @@ class ProfileMembersController &lt; MyProfileController
58 58  
59 59 def change_role
60 60 @roles = Profile::Roles.organization_member_roles(environment.id)
  61 + @custom_roles = profile.custom_roles
61 62 begin
62 63 @member = profile.members.find(params[:id])
63 64 rescue ActiveRecord::RecordNotFound
... ...
app/controllers/my_profile/profile_roles_controller.rb 0 → 100644
... ... @@ -0,0 +1,116 @@
  1 +class ProfileRolesController < MyProfileController
  2 +
  3 + protect 'manage_custom_roles', :profile
  4 +
  5 + def index
  6 + @roles = profile.custom_roles
  7 + end
  8 +
  9 + def new
  10 + @role = Role.new
  11 + end
  12 +
  13 + def create
  14 + @role = Role.new({:name => params[:role][:name], :permissions => params[:role][:permissions], :environment => environment }, :without_protection => true)
  15 + if @role.save
  16 + profile.custom_roles << @role
  17 + redirect_to :action => 'show', :id => @role
  18 + else
  19 + session[:notice] = _('Failed to create role')
  20 + render :action => 'new'
  21 + end
  22 + end
  23 +
  24 + def show
  25 + @role = environment.roles.find(params[:id])
  26 + end
  27 +
  28 + def edit
  29 + @role = environment.roles.find(params[:id])
  30 + end
  31 +
  32 + def assign_role_by_members
  33 + return redirect_to "/" if params[:q].nil? or !request.xhr?
  34 + arg = params[:q].downcase
  35 + result = find_by_contents(:people, environment, profile.members, params[:q])[:results]
  36 + render :text => prepare_to_token_input(result).to_json
  37 + end
  38 +
  39 + def destroy
  40 + @role = environment.roles.find(params[:id])
  41 + @members = profile.members_by_role(@role)
  42 + @roles_list = all_roles(environment, profile)
  43 + @roles_list.delete(@role)
  44 + end
  45 +
  46 + def remove
  47 + @role = environment.roles.find(params[:id])
  48 + @members = profile.members_by_role(@role)
  49 + member_roles = params[:roles] ? environment.roles.find(params[:roles].select{|r|!r.to_i.zero?}) : []
  50 + append_roles(@members, member_roles, profile)
  51 + if @role.destroy
  52 + session[:notice] = _('Role successfuly removed!')
  53 + else
  54 + session[:notice] = _('Failed to remove role!')
  55 + end
  56 + redirect_to :action => 'index'
  57 + end
  58 +
  59 + def update
  60 + @role = environment.roles.find(params[:id])
  61 + if @role.update_attributes(params[:role])
  62 + redirect_to :action => 'show', :id => @role
  63 + else
  64 + session[:notice] = _('Failed to edit role')
  65 + render :action => 'edit'
  66 + end
  67 + end
  68 +
  69 + def assign
  70 + @role = environment.roles.find(params[:id])
  71 + @roles_list = all_roles(environment, profile)
  72 + @roles_list.delete(@role)
  73 + end
  74 +
  75 + def define
  76 + @role = environment.roles.find(params[:id])
  77 + selected_role = params[:selected_role] ? environment.roles.find(params[:selected_role].to_i) : nil
  78 + if params[:assign_role_by].eql? "members"
  79 + members_list = params[:person_id].split(',').collect {|id| environment.profiles.find(id.to_i)}
  80 + members_list.collect{|person| person.add_role(@role, profile)}
  81 + elsif params[:assign_role_by].eql? "roles"
  82 + members = profile.members_by_role(selected_role)
  83 + replace_role(members, selected_role, @role, profile)
  84 + else
  85 + session[:notice] = _("Error")
  86 + end
  87 + redirect_to :action => 'index'
  88 + end
  89 +
  90 + protected
  91 +
  92 + def append_roles(members, roles, profile)
  93 + members.each do |person|
  94 + all_roles = person.find_roles(profile).map(&:role) + roles
  95 + person.define_roles(all_roles, profile)
  96 + end
  97 + end
  98 +
  99 + def all_roles(environment, profile)
  100 + Profile::Roles.organization_member_roles(environment.id) + profile.custom_roles
  101 + end
  102 +
  103 + def replace_roles(members, roles, profile)
  104 + members.each do |person|
  105 + person.define_roles(roles, profile)
  106 + end
  107 + end
  108 +
  109 + def replace_role(members, role, new_role, profile)
  110 + members.each do |person|
  111 + person.remove_role(role, profile)
  112 + person.add_role(new_role, profile)
  113 + end
  114 + end
  115 +
  116 +end
... ...
app/controllers/my_profile/tasks_controller.rb
1 1 class TasksController < MyProfileController
2 2  
3   - protect 'perform_task', :profile
4   -
  3 + protect [:perform_task, :view_tasks], :profile, :only => [:index]
  4 + protect :perform_task, :profile, :except => [:index]
  5 +
5 6 def index
6   - @filter = params[:filter_type].blank? ? nil : params[:filter_type]
  7 + @filter_type = params[:filter_type].presence
  8 + @filter_text = params[:filter_text].presence
  9 + @filter_responsible = params[:filter_responsible]
7 10 @task_types = Task.pending_types_for(profile)
8   - @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page])
  11 +
  12 + @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc')
  13 + @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present?
  14 + @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page])
  15 +
9 16 @failed = params ? params[:failed] : {}
  17 +
  18 + @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) if profile.organization?
  19 +
  20 + @view_only = !current_person.has_permission?(:perform_task, profile)
10 21 end
11 22  
12 23 def processed
13 24 @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at)
14 25 end
15 26  
  27 + def change_responsible
  28 + task = profile.tasks.find(params[:task_id])
  29 +
  30 + if task.responsible.present? && task.responsible.id != params[:old_responsible_id].to_i
  31 + return render :json => {:notice => _('Task already assigned!'), :success => false, :current_responsible => task.responsible.id}
  32 + end
  33 +
  34 + responsible = profile.members.find(params[:responsible_id]) if params[:responsible_id].present?
  35 + task.responsible = responsible
  36 + task.save!
  37 + render :json => {:notice => _('Task responsible successfully updated!'), :success => true, :new_responsible => {:id => responsible.present? ? responsible.id : nil}}
  38 + end
  39 +
16 40 VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ]
17 41  
18 42 def close
... ... @@ -25,7 +49,7 @@ class TasksController &lt; MyProfileController
25 49 task = profile.find_in_all_tasks(id)
26 50 begin
27 51 task.update_attributes(value[:task])
28   - task.send(decision)
  52 + task.send(decision, current_person)
29 53 rescue Exception => ex
30 54 message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"
31 55 failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message]
... ...
app/controllers/public/chat_controller.rb
... ... @@ -2,6 +2,7 @@ class ChatController &lt; PublicController
2 2  
3 3 before_filter :login_required
4 4 before_filter :check_environment_feature
  5 + before_filter :can_send_message, :only => :register_message
5 6  
6 7 def start_session
7 8 login = user.jid
... ... @@ -54,6 +55,16 @@ class ChatController &lt; PublicController
54 55 end
55 56 end
56 57  
  58 + def avatars
  59 + profiles = environment.profiles.where(:identifier => params[:profiles])
  60 + avatar_map = profiles.inject({}) do |result, profile|
  61 + result[profile.identifier] = profile_icon(profile, :minor)
  62 + result
  63 + end
  64 +
  65 + render_json avatar_map
  66 + end
  67 +
57 68 def update_presence_status
58 69 if request.xhr?
59 70 current_user.update_attributes({:chat_status_at => DateTime.now}.merge(params[:status] || {}))
... ... @@ -62,11 +73,17 @@ class ChatController &lt; PublicController
62 73 end
63 74  
64 75 def save_message
65   - to = environment.profiles.find_by_identifier(params[:to])
66   - body = params[:body]
67   -
68   - ChatMessage.create!(:to => to, :from => user, :body => body)
69   - render :text => 'ok'
  76 + if request.post?
  77 + to = environment.profiles.where(:identifier => params[:to]).first
  78 + body = params[:body]
  79 +
  80 + begin
  81 + ChatMessage.create!(:to => to, :from => user, :body => body)
  82 + return render_json({:status => 0})
  83 + rescue Exception => exception
  84 + return render_json({:status => 3, :message => exception.to_s, :backtrace => exception.backtrace})
  85 + end
  86 + end
70 87 end
71 88  
72 89 def recent_messages
... ... @@ -90,8 +107,9 @@ class ChatController &lt; PublicController
90 107 end
91 108  
92 109 def recent_conversations
93   - conversations_order = ActiveRecord::Base.connection.execute("select profiles.identifier from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc").entries.map {|e| e['identifier']}
94   - render :json => {:order => conversations_order.reverse, :domain => environment.default_hostname.gsub('.','-')}.to_json
  110 + profiles = Profile.find_by_sql("select profiles.* from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc")
  111 + jids = profiles.map(&:jid).reverse
  112 + render :json => jids.to_json
95 113 end
96 114  
97 115 #TODO Ideally this is done through roster table on ejabberd.
... ... @@ -108,4 +126,14 @@ class ChatController &lt; PublicController
108 126 end
109 127 end
110 128  
  129 + def can_send_message
  130 + return render_json({:status => 1, :message => 'Missing parameters!'}) if params[:from].nil? || params[:to].nil? || params[:message].nil?
  131 + return render_json({:status => 2, :message => 'You can not send message as another user!'}) if params[:from] != user.jid
  132 + # TODO Maybe register the jid in a table someday to avoid this below
  133 + return render_json({:status => 3, :messsage => 'You can not send messages to strangers!'}) if user.friends.where(:identifier => params[:to].split('@').first).blank?
  134 + end
  135 +
  136 + def render_json(result)
  137 + render :text => result.to_json
  138 + end
111 139 end
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -11,9 +11,10 @@ class ContentViewerController &lt; ApplicationController
11 11 path = get_path(params[:page], params[:format])
12 12  
13 13 @version = params[:version].to_i
  14 + @npage = params[:npage] || '1'
14 15  
15 16 if path.blank?
16   - @page = profile.home_page
  17 + @page = profile.home_page
17 18 return if redirected_to_profile_index
18 19 else
19 20 @page = profile.articles.find_by_path(path)
... ... @@ -107,10 +108,12 @@ class ContentViewerController &lt; ApplicationController
107 108 if translation.language == locale
108 109 @page = translation
109 110 redirect_to :profile => @page.profile.identifier, :page => @page.explode_path
  111 + return true
110 112 end
111 113 end
112 114 end
113 115 end
  116 + false
114 117 end
115 118  
116 119 def pass_without_comment_captcha?
... ... @@ -119,21 +122,23 @@ class ContentViewerController &lt; ApplicationController
119 122 helper_method :pass_without_comment_captcha?
120 123  
121 124 def allow_access_to_page(path)
122   - allowed = true
123 125 if @page.nil? # page not found, give error
124 126 render_not_found(path)
125   - allowed = false
126   - elsif !@page.display_to?(user)
127   - if !profile.public?
  127 + return false
  128 + end
  129 +
  130 + unless @page.display_to?(user)
  131 + if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank?
  132 + render_access_denied
  133 + else #!profile.public?
128 134 private_profile_partial_parameters
129 135 render :template => 'profile/_private_profile', :status => 403, :formats => [:html]
130   - allowed = false
131   - else #if !profile.visible?
132   - render_access_denied
133   - allowed = false
134 136 end
  137 +
  138 + return false
135 139 end
136   - allowed
  140 +
  141 + return true
137 142 end
138 143  
139 144 def user_is_a_bot?
... ... @@ -178,7 +183,7 @@ class ContentViewerController &lt; ApplicationController
178 183 if @page.forum? && @page.has_terms_of_use && terms_accepted == "true"
179 184 @page.add_agreed_user(user)
180 185 end
181   - end
  186 + end
182 187  
183 188 def is_a_forum_topic? (page)
184 189 return (!@page.parent.nil? && @page.parent.forum?)
... ...
app/controllers/public/events_controller.rb
... ... @@ -5,7 +5,11 @@ class EventsController &lt; PublicController
5 5  
6 6 def events
7 7 @events = []
8   - @date = build_date(params[:year], params[:month], params[:day])
  8 + begin
  9 + @date = build_date params[:year], params[:month], params[:day]
  10 + rescue ArgumentError # invalid date
  11 + return render_not_found
  12 + end
9 13  
10 14 if !params[:year] && !params[:month] && !params[:day]
11 15 @events = profile.events.next_events_from_month(@date).paginate(:per_page => per_page, :page => params[:page])
... ...
app/controllers/public/search_controller.rb
... ... @@ -62,7 +62,7 @@ class SearchController &lt; PublicController
62 62 end
63 63  
64 64 def articles
65   - @scope = @environment.articles.public.paginate(paginate_options)
  65 + @scope = @environment.articles.public
66 66 full_text_search
67 67 end
68 68  
... ... @@ -76,7 +76,7 @@ class SearchController &lt; PublicController
76 76 end
77 77  
78 78 def products
79   - @scope = @environment.products.paginate(paginate_options)
  79 + @scope = @environment.products
80 80 full_text_search
81 81 end
82 82  
... ... @@ -244,7 +244,7 @@ class SearchController &lt; PublicController
244 244 def visible_profiles(klass, *extra_relations)
245 245 relations = [:image, :domains, :environment, :preferred_domain]
246 246 relations += extra_relations
247   - @environment.send(klass.name.underscore.pluralize).visible.includes(relations).paginate(paginate_options)
  247 + @environment.send(klass.name.underscore.pluralize).visible.includes(relations)
248 248 end
249 249  
250 250 def per_page
... ...
app/controllers/public_controller.rb
... ... @@ -3,7 +3,7 @@ class PublicController &lt; ApplicationController
3 3  
4 4 def allow_access_to_page
5 5 unless profile.display_info_to?(user)
6   - if profile.visible?
  6 + if profile.visible? && !profile.secret
7 7 private_profile
8 8 else
9 9 invisible_profile
... ...
app/helpers/application_helper.rb
... ... @@ -707,6 +707,24 @@ module ApplicationHelper
707 707 javascript_include_tag script if script
708 708 end
709 709  
  710 + def template_path
  711 + if profile.nil?
  712 + "/designs/templates/#{environment.layout_template}"
  713 + else
  714 + "/designs/templates/#{profile.layout_template}"
  715 + end
  716 + end
  717 +
  718 + def template_javascript_src
  719 + script = File.join template_path, '/javascripts/template.js'
  720 + script if File.exists? File.join(Rails.root, 'public', script)
  721 + end
  722 +
  723 + def templete_javascript_ng
  724 + script = template_javascript_src
  725 + javascript_include_tag script if script
  726 + end
  727 +
710 728 def file_field_or_thumbnail(label, image, i)
711 729 display_form_field label, (
712 730 render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'),
... ... @@ -853,7 +871,7 @@ module ApplicationHelper
853 871 field_html += capture(&block)
854 872 end
855 873  
856   - if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index')
  874 + if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') || (controller.controller_name == 'home' && controller.action_name == 'index' && user.nil?)
857 875 if profile.signup_fields.include?(name)
858 876 result = field_html
859 877 end
... ... @@ -913,6 +931,19 @@ module ApplicationHelper
913 931 article_helper.cms_label_for_edit
914 932 end
915 933  
  934 + def label_for_clone_article(article)
  935 + translated_types = {
  936 + Folder => _('Folder'),
  937 + Blog => _('Blog'),
  938 + Event => _('Event'),
  939 + Forum => _('Forum')
  940 + }
  941 +
  942 + translated_type = translated_types[article.class] || _('Article')
  943 +
  944 + _('Clone %s') % translated_type
  945 + end
  946 +
916 947 def add_rss_feed_to_head(title, url)
917 948 content_for :feeds do
918 949 tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url))
... ... @@ -1184,35 +1215,6 @@ module ApplicationHelper
1184 1215 list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort
1185 1216 end
1186 1217  
1187   - #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+
1188   - def time_ago_as_sentence(from_time, include_seconds = false)
1189   - to_time = Time.now
1190   - from_time = Time.parse(from_time.to_s)
1191   - from_time = from_time.to_time if from_time.respond_to?(:to_time)
1192   - to_time = to_time.to_time if to_time.respond_to?(:to_time)
1193   - distance_in_minutes = (((to_time - from_time).abs)/60).round
1194   - distance_in_seconds = ((to_time - from_time).abs).round
1195   - case distance_in_minutes
1196   - when 0..1
1197   - return (distance_in_minutes == 0) ? _('less than a minute') : _('1 minute') unless include_seconds
1198   - case distance_in_seconds
1199   - when 0..4 then _('less than 5 seconds')
1200   - when 5..9 then _('less than 10 seconds')
1201   - when 10..19 then _('less than 20 seconds')
1202   - when 20..39 then _('half a minute')
1203   - when 40..59 then _('less than a minute')
1204   - else _('1 minute')
1205   - end
1206   -
1207   - when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes }
1208   - when 45..89 then _('about 1 hour ago')
1209   - when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round }
1210   - when 1440..2879 then _('1 day ago')
1211   - when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round }
1212   - else show_time(from_time)
1213   - end
1214   - end
1215   -
1216 1218 def comment_balloon(options = {}, &block)
1217 1219 wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content')
1218 1220 (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") }
... ... @@ -1480,4 +1482,26 @@ module ApplicationHelper
1480 1482 text_field(object_name, method, options.merge(:class => 'colorpicker_field'))
1481 1483 end
1482 1484  
  1485 + def fullscreen_buttons(itemId)
  1486 + content="
  1487 + <script>fullscreenPageLoad('#{itemId}')</script>
  1488 + "
  1489 + content+=content_tag('a', content_tag('span',_("Full screen")),
  1490 + { :id=>"fullscreen-btn",
  1491 + :onClick=>"toggle_fullwidth('#{itemId}')",
  1492 + :class=>"button with-text icon-fullscreen",
  1493 + :href=>"#",
  1494 + :title=>_("Go to full screen mode")
  1495 + })
  1496 +
  1497 + content+=content_tag('a', content_tag('span',_("Exit full screen")),
  1498 + { :style=>"display: none;",
  1499 + :id=>"exit-fullscreen-btn",
  1500 + :onClick=>"toggle_fullwidth('#{itemId}')",
  1501 + :class=>"button with-text icon-fullscreen",
  1502 + :href=>"#",
  1503 + :title=>_("Exit full screen mode")
  1504 + })
  1505 + end
  1506 +
1483 1507 end
... ...
app/helpers/article_helper.rb
... ... @@ -12,6 +12,7 @@ module ArticleHelper
12 12 @article = article
13 13  
14 14 visibility_options(@article, tokenized_children) +
  15 + topic_creation(@article) +
15 16 content_tag('h4', _('Options')) +
16 17 content_tag('div',
17 18 (article.profile.has_members? ?
... ... @@ -55,14 +56,7 @@ module ArticleHelper
55 56 'div',
56 57 check_box(:article, :display_versions) +
57 58 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions')
58   - ) : '') +
59   -
60   - (article.forum? && article.profile.community? ?
61   - content_tag(
62   - 'div',
63   - check_box(:article, :allows_members_to_create_topics) +
64   - content_tag('label', _('Allow members to create topics'), :for => 'article_allows_members_to_create_topics')
65   - ) : '')
  59 + ) : '')
66 60 )
67 61 end
68 62  
... ... @@ -81,6 +75,22 @@ module ArticleHelper
81 75 )
82 76 end
83 77  
  78 + def topic_creation(article)
  79 + return '' unless article.forum?
  80 +
  81 + general_options = Forum::TopicCreation.general_options(article)
  82 + slider_options = {:id => 'topic-creation-slider'}
  83 + slider_options = general_options.keys.inject(slider_options) do |result, option|
  84 + result.merge!({'data-'+option => general_options[option]})
  85 + end
  86 +
  87 + content_tag('h4', _('Topic creation')) +
  88 + content_tag( 'small', _('Who will be able to create new topics on this forum?')) +
  89 + content_tag('div', '', slider_options) +
  90 + hidden_field_tag('article[topic_creation]', article.topic_creation) +
  91 + javascript_include_tag('topic-creation-config')
  92 + end
  93 +
84 94 def privacity_exceptions(article, tokenized_children)
85 95 content_tag('div',
86 96 content_tag('div',
... ...
app/helpers/blog_helper.rb
... ... @@ -17,37 +17,52 @@ module BlogHelper
17 17 _('Configure blog')
18 18 end
19 19  
20   - def list_posts(articles, format = 'full', paginate = true)
  20 + def list_posts(articles, conf = { format: 'full', paginate: true })
21 21 pagination = will_paginate(articles, {
22 22 :param_name => 'npage',
23 23 :previous_label => _('&laquo; Newer posts'),
24 24 :next_label => _('Older posts &raquo;'),
25   - :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"}
26   - }) if articles.present? && paginate
  25 + :params => {:action=>"view_page",
  26 + :page=>articles.first.parent.path.split('/'),
  27 + :controller=>"content_viewer"}
  28 + }) if articles.present? && conf[:paginate]
27 29 content = []
28 30 artic_len = articles.length
29 31 articles.each_with_index{ |art,i|
30   - css_add = [ 'position-'+(i+1).to_s() ]
  32 + css_add = [ 'blog-post', 'position-'+(i+1).to_s() ]
31 33 position = (i%2 == 0) ? 'odd-post' : 'even-post'
32 34 css_add << 'first' if i == 0
33 35 css_add << 'last' if i == (artic_len-1)
34 36 css_add << 'not-published' if !art.published?
35   - css_add << position + '-inner'
36   - content << content_tag('div',
37   - content_tag('div',
38   - display_post(art, format).html_safe + '<br style="clear:both"/>'.html_safe,
39   - :class => 'blog-post ' + css_add.join(' '),
40   - :id => "post-#{art.id}"), :class => position
41   - )
  37 + css_add << position
  38 + content << (content_tag 'div', id: "post-#{art.id}", class: css_add do
  39 + content_tag 'div', class: position + '-inner blog-post-inner' do
  40 + display_post(art, conf[:format]).html_safe +
  41 + '<br style="clear:both"/>'.html_safe
  42 + end
  43 + end)
42 44 }
43 45 content.join("\n<hr class='sep-posts'/>\n") + (pagination or '')
44 46 end
45 47  
46 48 def display_post(article, format = 'full')
47   - no_comments = (format == 'full') ? false : true
  49 + no_comments = (format == 'full' || format == 'compact' ) ? false : true
48 50 title = article_title(article, :no_comments => no_comments)
49   - html = send("display_#{format}_format", FilePresenter.for(article)).html_safe
50   - title + html
  51 + method = "display_#{format.split('+')[0]}_format"
  52 + html = send(method, FilePresenter.for(article)).html_safe
  53 + if format.split('+')[1] == 'pic'
  54 + img = article.first_image
  55 + if img.blank?
  56 + '<div class="post-pic empty"></div>'
  57 + else
  58 + '<div class="post-pic" style="background-image:url('+img+')"></div>'
  59 + end
  60 + end.to_s + title + html
  61 + end
  62 +
  63 + def display_compact_format(article)
  64 + render :file => 'content_viewer/_display_compact_format',
  65 + :locals => { :article => article, :format => "compact" }
51 66 end
52 67  
53 68 def display_full_format(article)
... ...
app/helpers/boxes_helper.rb
... ... @@ -122,7 +122,7 @@ module BoxesHelper
122 122 end
123 123  
124 124 def wrap_main_content(content)
125   - (1..8).to_a.reverse.inject(content) { |acc,n| content_tag('div', acc, :id => 'main-content-wrapper-' + n.to_s) }
  125 + content_tag('div', content, :class => 'main-content')
126 126 end
127 127  
128 128 def extract_block_content(content)
... ... @@ -190,7 +190,7 @@ module BoxesHelper
190 190 else
191 191 "before-block-#{block.id}"
192 192 end
193   - if block.nil? or modifiable?(block)
  193 + if block.nil? || movable?(block)
194 194 content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
195 195 else
196 196 ""
... ... @@ -199,14 +199,14 @@ module BoxesHelper
199 199  
200 200 # makes the given block draggable so it can be moved away.
201 201 def block_handle(block)
202   - modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : ""
  202 + movable?(block) ? draggable_element("block-#{block.id}", :revert => true) : ""
203 203 end
204 204  
205 205 def block_edit_buttons(block)
206 206 buttons = []
207 207 nowhere = 'javascript: return false;'
208 208  
209   - if modifiable?(block)
  209 + if movable?(block)
210 210 if block.first?
211 211 buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
212 212 else
... ... @@ -229,15 +229,15 @@ module BoxesHelper
229 229 buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
230 230 end
231 231 end
  232 + end
232 233  
233   - if block.editable?
234   - buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
235   - end
  234 + if editable?(block)
  235 + buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
  236 + end
236 237  
237   - if !block.main?
238   - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
239   - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
240   - end
  238 + if movable?(block) && !block.main?
  239 + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
  240 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
241 241 end
242 242  
243 243 if block.respond_to?(:help)
... ... @@ -251,8 +251,8 @@ module BoxesHelper
251 251 content_tag('h2', _('Embed block code')) +
252 252 content_tag('div', _('Below, you''ll see a field containing embed code for the block. Just copy the code and paste it into your website or blogging software.'), :style => 'margin-bottom: 1em;') +
253 253 content_tag('textarea', embed_code, :style => 'margin-bottom: 1em; width:100%; height:40%;', :readonly => 'readonly') +
254   - thickbox_close_button(_('Close')), :style => 'display: none;', :id => "embed-code-box-#{block.id}")
255   - buttons << thickbox_inline_popup_icon(:embed, _('Embed code'), {}, "embed-code-box-#{block.id}") << html
  254 + modal_close_button(_('Close')), :style => 'display: none;', :id => "embed-code-box-#{block.id}")
  255 + buttons << modal_inline_icon(:embed, _('Embed code'), {}, "#embed-code-box-#{block.id}") << html
256 256 end
257 257  
258 258 content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar')
... ... @@ -273,7 +273,11 @@ module BoxesHelper
273 273 classes
274 274 end
275 275  
276   - def modifiable?(block)
277   - return !block.fixed || environment.admins.include?(user)
  276 + def movable?(block)
  277 + return block.movable? || user.is_admin?
  278 + end
  279 +
  280 + def editable?(block)
  281 + return block.editable? || user.is_admin?
278 282 end
279 283 end
... ...
app/helpers/chat_helper.rb
... ... @@ -9,12 +9,12 @@ module ChatHelper
9 9 avatar = profile_image(user, :portrait, :class => 'avatar')
10 10 content_tag('span',
11 11 link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'),
12   - '#',
  12 + '',
13 13 :onclick => 'toggleMenu(this); return false',
14 14 :class => icon_class + ' simplemenu-trigger'
15 15 ) +
16 16 content_tag('ul',
17   - links.map{|link| content_tag('li', link_to(link[1], '#', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"),
  17 + links.map{|link| content_tag('li', link_to(link[1], '', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"),
18 18 :style => 'display: none; z-index: 100',
19 19 :class => 'simplemenu-submenu'
20 20 ),
... ...
app/helpers/comment_helper.rb
1 1 module CommentHelper
  2 + include DatesHelper
2 3  
3 4 def article_title(article, args = {})
4 5 title = article.title
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -2,6 +2,7 @@ module ContentViewerHelper
2 2  
3 3 include BlogHelper
4 4 include ForumHelper
  5 + include DatesHelper
5 6  
6 7 def display_number_of_comments(n)
7 8 base_str = "<span class='comment-count hide'>#{n}</span>"
... ... @@ -24,8 +25,9 @@ module ContentViewerHelper
24 25 unless args[:no_comments] || !article.accept_comments
25 26 comments = (" - %s") % link_to_comments(article)
26 27 end
  28 + date_format = show_with_right_format_date article
27 29 title << content_tag('span',
28   - content_tag('span', show_date(article.published_at), :class => 'date') +
  30 + date_format +
29 31 content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') +
30 32 content_tag('span', comments, :class => 'comments'),
31 33 :class => 'created-at'
... ... @@ -34,6 +36,24 @@ module ContentViewerHelper
34 36 title
35 37 end
36 38  
  39 + def show_with_right_format_date article
  40 + date_format = article.environment.date_format
  41 + use_numbers = false
  42 + year = true
  43 + left_time = false
  44 + if date_format == 'numbers_with_year'
  45 + use_numbers = true
  46 + elsif date_format == 'numbers'
  47 + use_numbers = true
  48 + year = false
  49 + elsif date_format == 'month_name'
  50 + year = false
  51 + elsif date_format == 'past_time'
  52 + left_time = true
  53 + end
  54 + content_tag('span', show_date(article.published_at, use_numbers , year, left_time), :class => 'date')
  55 + end
  56 +
37 57 def link_to_comments(article, args = {})
38 58 return '' unless article.accept_comments?
39 59 reference_to_article number_of_comments(article), article, 'comments_list'
... ...
app/helpers/dates_helper.rb
... ... @@ -2,6 +2,7 @@ require &#39;noosfero/i18n&#39;
2 2  
3 3 module DatesHelper
4 4  
  5 + include ActionView::Helpers::DateHelper
5 6 def months
6 7 I18n.t('date.month_names')
7 8 end
... ... @@ -15,10 +16,12 @@ module DatesHelper
15 16 end
16 17  
17 18 # formats a date for displaying.
18   - def show_date(date, use_numbers = false, year=true)
  19 + def show_date(date, use_numbers = false, year = true, left_time = false)
19 20 if date && use_numbers
20 21 date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}')
21 22 date_format % { :day => date.day, :month => date.month, :year => date.year }
  23 + elsif date && left_time
  24 + date_format = time_ago_in_words(date)
22 25 elsif date
23 26 date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}')
24 27 date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year }
... ...
app/helpers/events_helper.rb
1 1 module EventsHelper
2 2  
  3 + include DatesHelper
3 4 def list_events(date, events)
4 5 title = _('Events for %s') % show_date_month(date)
5 6 content_tag('h2', title) +
... ...
app/helpers/folder_helper.rb
1   -require 'short_filename'
2   -
3 1 module FolderHelper
4 2  
5   - include ShortFilename
6 3 include ArticleHelper
7 4  
8 5 def list_contents(configure={})
... ... @@ -10,8 +7,8 @@ module FolderHelper
10 7 configure[:list_type] ||= :folder
11 8 if !configure[:contents].blank?
12 9 configure[:contents] = configure[:contents].paginate(
13   - :order => "updated_at DESC",
14   - :per_page => 10,
  10 + :order => "name ASC",
  11 + :per_page => 30,
15 12 :page => params[:npage]
16 13 )
17 14  
... ... @@ -25,49 +22,32 @@ module FolderHelper
25 22 articles.select {|article| article.display_to?(user)}
26 23 end
27 24  
28   - def display_content_in_listing(configure={})
29   - recursive = configure[:recursive] || false
30   - list_type = configure[:list_type] || :folder
31   - level = configure[:level] || 0
32   - content = FilePresenter.for configure[:content]
  25 + def display_content_icon(content_item)
  26 + content = FilePresenter.for content_item
33 27 content_link = if content.image?
34   - link_to('&nbsp;' * (level * 4) +
35   - image_tag(icon_for_article(content)) + short_filename(content.name),
  28 + link_to(
  29 + image_tag(icon_for_article(content, :bigicon)),
36 30 content.url.merge(:view => true)
37 31 )
38 32 else
39   - link_to('&nbsp;' * (level * 4) +
40   - short_filename(content.name),
41   - content.url.merge(:view => true), :class => icon_for_article(content)
  33 + link_to('',
  34 + content.url.merge(:view => true),
  35 + :class => icon_for_article(content, :bigicon)
42 36 )
43 37 end
44   - result = content_tag(
45   - 'tr',
46   - content_tag('td', content_link ) +
47   - content_tag('td', show_date(content.updated_at), :class => 'last-update'),
48   - :class => "#{list_type}-item"
49   - )
50   - if recursive
51   - result + content.children.map {|item|
52   - display_content_in_listing :content=>item, :recursive=>recursive,
53   - :list_type=>list_type, :level=>level+1
54   - }.join("\n")
55   - else
56   - result
57   - end
58 38 end
59 39  
60   - def icon_for_article(article)
  40 + def icon_for_article(article, size = 'icon')
61 41 article = FilePresenter.for article
62   - icon = article.respond_to?(:icon_name) ?
63   - article.icon_name :
64   - article.class.icon_name(article)
65   - if (icon =~ /\//)
66   - icon
  42 + if article.respond_to?(:sized_icon)
  43 + article.sized_icon(size)
67 44 else
68   - klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ')
  45 + icon = article.respond_to?(:icon_name) ?
  46 + article.icon_name :
  47 + article.class.icon_name(article)
  48 + klasses = "#{size} " + [icon].flatten.map{|name| "#{size}-"+name}.join(' ')
69 49 if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter)
70   - klasses += ' icon-upload-file'
  50 + klasses += " #{size}-upload-file"
71 51 end
72 52 klasses
73 53 end
... ...
app/helpers/forum_helper.rb
1 1 module ForumHelper
  2 + include ActionView::Helpers::DateHelper
2 3  
3 4 def cms_label_for_new_children
4 5 _('New discussion topic')
... ... @@ -42,9 +43,9 @@ module ForumHelper
42 43 def last_topic_update(article)
43 44 info = article.info_from_last_update
44 45 if info[:author_url]
45   - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url])
  46 + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url])
46 47 else
47   - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + info[:author_name]
  48 + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + info[:author_name]
48 49 end
49 50 end
50 51  
... ...
app/helpers/layout_helper.rb
... ... @@ -28,7 +28,7 @@ module LayoutHelper
28 28 end
29 29  
30 30 def noosfero_javascript
31   - plugins_javascripts = @plugins.flat_map{ |plugin| plugin.js_files.map{ |js| plugin.class.public_path(js, true) } }.flatten
  31 + plugins_javascripts = @plugins.flat_map{ |plugin| Array.wrap(plugin.js_files).map{ |js| plugin.class.public_path(js, true) } }.flatten
32 32  
33 33 output = ''
34 34 output += render 'layouts/javascript'
... ... @@ -38,6 +38,8 @@ module LayoutHelper
38 38 output += theme_javascript_ng.to_s
39 39 output += javascript_tag 'render_all_jquery_ui_widgets()'
40 40  
  41 + output += templete_javascript_ng.to_s
  42 +
41 43 output
42 44 end
43 45  
... ... @@ -70,11 +72,7 @@ module LayoutHelper
70 72 end
71 73  
72 74 def template_stylesheet_path
73   - if profile.nil?
74   - "/designs/templates/#{environment.layout_template}/stylesheets/style.css"
75   - else
76   - "/designs/templates/#{profile.layout_template}/stylesheets/style.css"
77   - end
  75 + File.join template_path, "/stylesheets/style.css"
78 76 end
79 77  
80 78  
... ...
app/helpers/manage_products_helper.rb
... ... @@ -75,9 +75,12 @@ module ManageProductsHelper
75 75 end
76 76  
77 77 def categories_container(categories_selection_html, hierarchy_html = '')
78   - hidden_field_tag('selected_category_id') +
79   - content_tag('div', hierarchy_html, :id => 'hierarchy_navigation') +
80   - content_tag('div', categories_selection_html, :id => 'categories_container_wrapper')
  78 + content_tag 'div',
  79 + render('categories_autocomplete') +
  80 + hidden_field_tag('selected_category_id') +
  81 + content_tag('div', hierarchy_html, :id => 'hierarchy_navigation') +
  82 + content_tag('div', categories_selection_html, :id => 'categories_container_wrapper'),
  83 + :id => 'categories-container'
81 84 end
82 85  
83 86 def select_for_categories(categories, level = 0)
... ...
app/helpers/profile_editor_helper.rb
... ... @@ -141,8 +141,9 @@ module ProfileEditorHelper
141 141 )
142 142 end
143 143  
144   - def control_panel_button(title, icon, url)
145   - link_to title, url, :class => 'control-panel-%s' % icon
  144 + def control_panel_button(title, icon, url, html_options = {})
  145 + html_options ||= {}
  146 + link_to title, url, html_options.merge(:class => 'control-panel-%s' % icon)
146 147 end
147 148  
148 149 def unchangeable_privacy_field(profile)
... ...
app/helpers/search_helper.rb
... ... @@ -106,6 +106,10 @@ module SearchHelper
106 106 end
107 107 end
108 108  
  109 + def city_with_state_for_profile(p)
  110 + city_with_state(p.region) || [p.city, p.state].compact.reject(&:blank?).join(', ')
  111 + end
  112 +
109 113 def display_selector(asset, display, float = 'right')
110 114 display = nil if display.blank?
111 115 display ||= asset_class(asset).default_search_display
... ...
app/helpers/tinymce_helper.rb
... ... @@ -17,9 +17,10 @@ module TinymceHelper
17 17 searchreplace wordcount visualblocks visualchars code fullscreen
18 18 insertdatetime media nonbreaking save table contextmenu directionality
19 19 emoticons template paste textcolor colorpicker textpattern],
  20 + :image_advtab => true,
20 21 :language => tinymce_language
21 22  
22   - options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
  23 + options[:toolbar1] = "fullscreen | insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
23 24 if options[:mode] == 'simple'
24 25 options[:menubar] = false
25 26 else
... ...
app/helpers/users_helper.rb
... ... @@ -14,7 +14,7 @@ module UsersHelper
14 14 select_field = select_tag(:filter, options, :onchange => onchange)
15 15 content_tag('div',
16 16 content_tag('strong', _('Filter')) + ': ' + select_field,
17   - :class => "environment-users-customize-search"
  17 + :class => "environment-profiles-customize-search"
18 18 )
19 19 end
20 20  
... ...
app/mailers/task_mailer.rb
... ... @@ -5,7 +5,7 @@ class TaskMailer &lt; ActionMailer::Base
5 5 @target = task.target.name
6 6 @environment = task.environment.name
7 7 @url = generate_environment_url(task, :controller => 'home')
8   - url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url)
  8 + url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url.merge(:script_name => Noosfero.root('/')))
9 9 @tasks_url = url_for_tasks_list
10 10  
11 11 mail(
... ... @@ -56,7 +56,7 @@ class TaskMailer &lt; ActionMailer::Base
56 56 end
57 57  
58 58 def generate_environment_url(task, url = {})
59   - url_for(Noosfero.url_options.merge(:host => task.environment.default_hostname).merge(url))
  59 + url_for(Noosfero.url_options.merge(:host => task.environment.default_hostname).merge(url).merge(:script_name => Noosfero.root('/')))
60 60 end
61 61  
62 62 end
... ...
app/models/add_friend.rb
... ... @@ -54,7 +54,7 @@ class AddFriend &lt; Task
54 54 end
55 55  
56 56 def remove_from_suggestion_list(task)
57   - suggestion = task.requestor.profile_suggestions.find_by_suggestion_id task.target.id
  57 + suggestion = task.requestor.suggested_profiles.find_by_suggestion_id task.target.id
58 58 suggestion.disable if suggestion
59 59 end
60 60 end
... ...
app/models/article.rb
... ... @@ -5,7 +5,7 @@ class Article &lt; ActiveRecord::Base
5 5 :allow_members_to_edit, :translation_of_id, :language,
6 6 :license_id, :parent_id, :display_posts_in_current_language,
7 7 :category_ids, :posts_per_page, :moderate_comments,
8   - :accept_comments, :feed, :published, :source,
  8 + :accept_comments, :feed, :published, :source, :source_name,
9 9 :highlighted, :notify_comments, :display_hits, :slug,
10 10 :external_feed_builder, :display_versions, :external_link,
11 11 :image_builder, :show_to_followers
... ... @@ -25,6 +25,16 @@ class Article &lt; ActiveRecord::Base
25 25 :display => %w[full]
26 26 }
27 27  
  28 + def initialize(*params)
  29 + super
  30 +
  31 + if !params.blank? && params.first.has_key?(:profile) && !params.first[:profile].blank?
  32 + profile = params.first[:profile]
  33 + self.published = false unless profile.public?
  34 + end
  35 +
  36 + end
  37 +
28 38 def self.default_search_display
29 39 'full'
30 40 end
... ... @@ -86,6 +96,8 @@ class Article &lt; ActiveRecord::Base
86 96 belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id
87 97 before_destroy :rotate_translations
88 98  
  99 + acts_as_voteable
  100 +
89 101 before_create do |article|
90 102 article.published_at ||= Time.now
91 103 if article.reference_article && !article.parent
... ... @@ -491,11 +503,11 @@ class Article &lt; ActiveRecord::Base
491 503 return [] if user.nil? || (profile && !profile.public? && !user.follows?(profile))
492 504 where(
493 505 [
494   - "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ?
495   - OR (show_to_followers = ? AND ?)", true, user.id, user.id,
  506 + "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ?
  507 + OR (show_to_followers = ? AND ? AND profile_id = ?)", true, user.id, user.id,
496 508 profile.nil? ? false : user.has_permission?(:view_private_content, profile),
497   - true, user.follows?(profile)
498   - ]
  509 + true, user.follows?(profile), (profile.nil? ? nil : profile.id)
  510 + ]
499 511 )
500 512 }
501 513  
... ... @@ -509,7 +521,7 @@ class Article &lt; ActiveRecord::Base
509 521  
510 522 def display_to?(user = nil)
511 523 if published?
512   - profile.display_info_to?(user)
  524 + (profile.secret? || !profile.visible?) ? profile.display_info_to?(user) : true
513 525 else
514 526 if !user
515 527 false
... ... @@ -567,25 +579,24 @@ class Article &lt; ActiveRecord::Base
567 579 profile.visible? && profile.public? && published?
568 580 end
569 581  
570   -
571   - def copy(options = {})
  582 + def copy_without_save(options = {})
572 583 attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) }
573 584 attrs.merge!(options)
574 585 object = self.class.new
575 586 attrs.each do |key, value|
576 587 object.send(key.to_s+'=', value)
577 588 end
  589 + object
  590 + end
  591 +
  592 + def copy(options = {})
  593 + object = copy_without_save(options)
578 594 object.save
579 595 object
580 596 end
581 597  
582 598 def copy!(options = {})
583   - attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) }
584   - attrs.merge!(options)
585   - object = self.class.new
586   - attrs.each do |key, value|
587   - object.send(key.to_s+'=', value)
588   - end
  599 + object = copy_without_save(options)
589 600 object.save!
590 601 object
591 602 end
... ... @@ -769,7 +780,9 @@ class Article &lt; ActiveRecord::Base
769 780 end
770 781  
771 782 def first_image
772   - img = Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first
  783 + img = ( image.present? && { 'src' => image.public_filename } ) ||
  784 + Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first ||
  785 + Nokogiri::HTML.fragment(self.body.to_s).search('img').first
773 786 img.nil? ? '' : img['src']
774 787 end
775 788  
... ...
app/models/block.rb
1 1 class Block < ActiveRecord::Base
2 2  
3   - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed
  3 + attr_accessible :title, :display, :limit, :box_id, :posts_per_page,
  4 + :visualization_format, :language, :display_user,
  5 + :box, :edit_modes, :move_modes, :mirror
4 6  
5 7 # to be able to generate HTML
6 8 include ActionView::Helpers::UrlHelper
... ... @@ -13,17 +15,29 @@ class Block &lt; ActiveRecord::Base
13 15  
14 16 acts_as_list :scope => :box
15 17 belongs_to :box
  18 + belongs_to :mirror_block, :class_name => "Block"
  19 + has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id"
16 20  
17 21 acts_as_having_settings
18 22  
19 23 scope :enabled, :conditions => { :enabled => true }
20 24  
  25 + after_save do |block|
  26 + if block.owner.kind_of?(Profile) && block.owner.is_template? && block.mirror?
  27 + block.observers.each do |observer|
  28 + observer.copy_from(block)
  29 + observer.title = block.title
  30 + observer.save
  31 + end
  32 + end
  33 + end
  34 +
21 35 def embedable?
22 36 false
23 37 end
24 38  
25 39 def get_limit
26   - [0,limit].max
  40 + [0,limit.to_i].max
27 41 end
28 42  
29 43 def embed_code
... ... @@ -110,8 +124,13 @@ class Block &lt; ActiveRecord::Base
110 124 # * <tt>'all'</tt>: the block is always displayed
111 125 settings_items :language, :type => :string, :default => 'all'
112 126  
113   - # The block can be configured to be fixed. Only can be edited by environment admins
114   - settings_items :fixed, :type => :boolean, :default => false
  127 + # The block can be configured to define the edition modes options. Only can be edited by environment admins
  128 + # It can assume the following values:
  129 + #
  130 + # * <tt>'all'</tt>: the block owner has all edit options for this block
  131 + # * <tt>'none'</tt>: the block owner can't do anything with the block
  132 + settings_items :edit_modes, :type => :string, :default => 'all'
  133 + settings_items :move_modes, :type => :string, :default => 'all'
115 134  
116 135 # returns the description of the block, used when the user sees a list of
117 136 # blocks to choose one to include in the design.
... ... @@ -148,7 +167,11 @@ class Block &lt; ActiveRecord::Base
148 167  
149 168 # Is this block editable? (Default to <tt>false</tt>)
150 169 def editable?
151   - true
  170 + self.edit_modes == "all"
  171 + end
  172 +
  173 + def movable?
  174 + self.move_modes == "all"
152 175 end
153 176  
154 177 # must always return false, except on MainBlock clas.
... ... @@ -228,6 +251,21 @@ class Block &lt; ActiveRecord::Base
228 251 }
229 252 end
230 253  
  254 + def edit_block_options
  255 + @edit_options ||= {
  256 + 'all' => _('Can be modified'),
  257 + 'none' => _('Cannot be modified')
  258 + }
  259 + end
  260 +
  261 + def move_block_options
  262 + @move_options ||= {
  263 + 'all' => _('Can be moved'),
  264 + 'none' => _('Cannot be moved')
  265 + }
  266 + end
  267 +
  268 +
231 269 def duplicate
232 270 duplicated_block = self.dup
233 271 duplicated_block.display = 'never'
... ... @@ -243,6 +281,10 @@ class Block &lt; ActiveRecord::Base
243 281 self.position = block.position
244 282 end
245 283  
  284 + def add_observer(block)
  285 + self.observers << block
  286 + end
  287 +
246 288 private
247 289  
248 290 def home_page_path
... ...
app/models/blog.rb
... ... @@ -76,9 +76,12 @@ class Blog &lt; Folder
76 76 end
77 77  
78 78 settings_items :visualization_format, :type => :string, :default => 'full'
79   - validates_inclusion_of :visualization_format, :in => [ 'full', 'short' ], :if => :visualization_format
  79 + validates_inclusion_of :visualization_format,
  80 + :in => [ 'full', 'short', 'short+pic', 'compact'],
  81 + :if => :visualization_format
80 82  
81   - settings_items :display_posts_in_current_language, :type => :boolean, :default => false
  83 + settings_items :display_posts_in_current_language,
  84 + :type => :boolean, :default => false
82 85  
83 86 alias :display_posts_in_current_language? :display_posts_in_current_language
84 87  
... ...
app/models/chat_message.rb
... ... @@ -4,4 +4,5 @@ class ChatMessage &lt; ActiveRecord::Base
4 4 belongs_to :to, :class_name => 'Profile'
5 5 belongs_to :from, :class_name => 'Profile'
6 6  
  7 + validates_presence_of :from, :to
7 8 end
... ...
app/models/comment.rb
... ... @@ -37,6 +37,8 @@ class Comment &lt; ActiveRecord::Base
37 37  
38 38 xss_terminate :only => [ :body, :title, :name ], :on => 'validation'
39 39  
  40 + acts_as_voteable
  41 +
40 42 def comment_root
41 43 (reply_of && reply_of.comment_root) || self
42 44 end
... ...
app/models/environment.rb
... ... @@ -3,7 +3,17 @@
3 3 # domains.
4 4 class Environment < ActiveRecord::Base
5 5  
6   - attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :members_whitelist_enabled, :members_whitelist, :highlighted_news_amount, :portal_news_amount
  6 + attr_accessible :name, :is_default, :signup_welcome_text_subject,
  7 + :signup_welcome_text_body, :terms_of_use,
  8 + :message_for_disabled_enterprise, :news_amount_by_folder,
  9 + :default_language, :languages, :description,
  10 + :organization_approval_method, :enabled_plugins,
  11 + :enabled_features, :redirection_after_login,
  12 + :redirection_after_signup, :contact_email, :theme,
  13 + :reports_lower_bound, :noreply_email,
  14 + :signup_welcome_screen_body, :members_whitelist_enabled,
  15 + :members_whitelist, :highlighted_news_amount,
  16 + :portal_news_amount, :date_format
7 17  
8 18 has_many :users
9 19  
... ... @@ -14,11 +24,19 @@ class Environment &lt; ActiveRecord::Base
14 24  
15 25 IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/
16 26  
  27 + validates_inclusion_of :date_format,
  28 + :in => [ 'numbers_with_year', 'numbers',
  29 + 'month_name_with_year', 'month_name',
  30 + 'past_time'],
  31 + :if => :date_format
  32 +
17 33 def self.verify_filename(filename)
18 34 filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS
19 35 filename
20 36 end
21 37  
  38 + NUMBER_OF_BOXES = 4
  39 +
22 40 PERMISSIONS['Environment'] = {
23 41 'view_environment_admin_panel' => N_('View environment admin panel'),
24 42 'edit_environment_features' => N_('Edit environment features'),
... ... @@ -27,6 +45,7 @@ class Environment &lt; ActiveRecord::Base
27 45 'manage_environment_roles' => N_('Manage environment roles'),
28 46 'manage_environment_validators' => N_('Manage environment validators'),
29 47 'manage_environment_users' => N_('Manage environment users'),
  48 + 'manage_environment_organizations' => N_('Manage environment organizations'),
30 49 'manage_environment_templates' => N_('Manage environment templates'),
31 50 'manage_environment_licenses' => N_('Manage environment licenses'),
32 51 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'),
... ... @@ -72,7 +91,8 @@ class Environment &lt; ActiveRecord::Base
72 91 'edit_profile_design',
73 92 'manage_products',
74 93 'manage_friends',
75   - 'perform_task'
  94 + 'perform_task',
  95 + 'view_tasks'
76 96 ]
77 97 )
78 98 end
... ... @@ -172,7 +192,7 @@ class Environment &lt; ActiveRecord::Base
172 192 acts_as_having_boxes
173 193  
174 194 after_create do |env|
175   - 3.times do
  195 + NUMBER_OF_BOXES.times do
176 196 env.boxes << Box.new
177 197 end
178 198  
... ... @@ -337,6 +357,16 @@ class Environment &lt; ActiveRecord::Base
337 357 self.save!
338 358 end
339 359  
  360 + def enable_all_plugins
  361 + Noosfero::Plugin.available_plugin_names.each do |plugin|
  362 + plugin_name = plugin.to_s + "Plugin"
  363 + unless self.enabled_plugins.include?(plugin_name)
  364 + self.enabled_plugins += [plugin_name]
  365 + end
  366 + end
  367 + self.save!
  368 + end
  369 +
340 370 # Disables a feature identified by its name
341 371 def disable(feature, must_save=true)
342 372 self.settings["#{feature}_enabled".to_sym] = false
... ... @@ -737,8 +767,8 @@ class Environment &lt; ActiveRecord::Base
737 767 end
738 768  
739 769 def is_default_template?(template)
740   - is_default = template == community_default_template
741   - is_default = is_default || template == person_default_template
  770 + is_default = template == community_default_template
  771 + is_default = is_default || template == person_default_template
742 772 is_default = is_default || template == enterprise_default_template
743 773 is_default
744 774 end
... ...
app/models/forum.rb
... ... @@ -3,11 +3,11 @@ class Forum &lt; Folder
3 3 acts_as_having_posts :order => 'updated_at DESC'
4 4 include PostsLimit
5 5  
6   - attr_accessible :has_terms_of_use, :terms_of_use, :allows_members_to_create_topics
  6 + attr_accessible :has_terms_of_use, :terms_of_use, :topic_creation
7 7  
8 8 settings_items :terms_of_use, :type => :string, :default => ""
9 9 settings_items :has_terms_of_use, :type => :boolean, :default => false
10   - settings_items :allows_members_to_create_topics, :type => :boolean, :default => false
  10 + settings_items :topic_creation, :type => :string, :default => 'self'
11 11 has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people'
12 12  
13 13 before_save do |forum|
... ... @@ -33,6 +33,23 @@ class Forum &lt; Folder
33 33 _('An internet forum, also called message board, where discussions can be held.')
34 34 end
35 35  
  36 + module TopicCreation
  37 + BASE = ActiveSupport::OrderedHash.new
  38 + BASE['users'] = _('Logged users')
  39 +
  40 + PERSON = ActiveSupport::OrderedHash.new
  41 + PERSON['self'] = _('Me')
  42 + PERSON['related'] = _('Friends')
  43 +
  44 + GROUP = ActiveSupport::OrderedHash.new
  45 + GROUP['self'] = _('Administrators')
  46 + GROUP['related'] = _('Members')
  47 +
  48 + def self.general_options(forum)
  49 + forum.profile.person? ? PERSON.merge(BASE) : GROUP.merge(BASE)
  50 + end
  51 + end
  52 +
36 53 include ActionView::Helpers::TagHelper
37 54 def to_html(options = {})
38 55 proc do
... ... @@ -69,11 +86,17 @@ class Forum &lt; Folder
69 86 self.users_with_agreement.exists? user
70 87 end
71 88  
72   - def can_create_topic?(user, profile)
73   - return profile.community? && profile.members.include?(user) && self.allows_members_to_create_topics
  89 + def can_create_topic?(user)
  90 + return true if user == profile || profile.admins.include?(user) || profile.environment.admins.include?(user)
  91 + case topic_creation
  92 + when 'related'
  93 + profile.person? ? profile.friends.include?(user) : profile.members.include?(user)
  94 + when 'users'
  95 + user.present?
  96 + end
74 97 end
75 98  
76 99 def allow_create?(user)
77   - super || can_create_topic?(user, profile)
  100 + super || can_create_topic?(user)
78 101 end
79 102 end
... ...
app/models/highlights_block.rb
... ... @@ -26,8 +26,16 @@ class HighlightsBlock &lt; Block
26 26 end
27 27  
28 28 def featured_images
29   - block_images = images.select{|i| !i[:image_src].nil? }.sort { |x, y| x[:position] <=> y[:position] }
30   - shuffle ? block_images.shuffle : block_images
  29 + images = get_images
  30 + shuffle ? images.shuffle : images
  31 + end
  32 +
  33 + def get_images
  34 + images.select do |i|
  35 + !i[:image_src].nil?
  36 + end.sort do |x, y|
  37 + x[:position] <=> y[:position]
  38 + end
31 39 end
32 40  
33 41 def content(args={})
... ...
app/models/organization.rb
... ... @@ -29,6 +29,8 @@ class Organization &lt; Profile
29 29  
30 30 has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source'
31 31  
  32 + has_many :custom_roles, :class_name => 'Role', :foreign_key => :profile_id
  33 +
32 34 scope :more_popular, :order => 'members_count DESC'
33 35  
34 36 validate :presence_of_required_fieds, :unless => :is_template
... ...
app/models/person.rb
... ... @@ -84,9 +84,9 @@ roles] }
84 84 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people'
85 85 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions'
86 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]
  87 + has_many :suggested_profiles, :class_name => 'ProfileSuggestion', :foreign_key => :person_id, :order => 'score DESC', :dependent => :destroy
  88 + has_many :suggested_people, :through => :suggested_profiles, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Person', true]
  89 + has_many :suggested_communities, :through => :suggested_profiles, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true]
90 90  
91 91 scope :more_popular, :order => 'friends_count DESC'
92 92  
... ... @@ -103,6 +103,8 @@ roles] }
103 103  
104 104 belongs_to :user, :dependent => :delete
105 105  
  106 + acts_as_voter
  107 +
106 108 def can_change_homepage?
107 109 !environment.enabled?('cant_change_homepage') || is_admin?
108 110 end
... ... @@ -522,7 +524,7 @@ roles] }
522 524 end
523 525  
524 526 def remove_suggestion(profile)
525   - suggestion = profile_suggestions.find_by_suggestion_id profile.id
  527 + suggestion = suggested_profiles.find_by_suggestion_id profile.id
526 528 suggestion.disable if suggestion
527 529 end
528 530  
... ...
app/models/product_category.rb
... ... @@ -10,6 +10,9 @@ class ProductCategory &lt; Category
10 10 :joins => :products,
11 11 :conditions => ['products.profile_id = ?', enterprise.id]
12 12 }}
  13 + scope :by_environment, lambda { |environment| {
  14 + :conditions => ['environment_id = ?', environment.id]
  15 + }}
13 16 scope :unique_by_level, lambda { |level| {
14 17 :select => "DISTINCT ON (filtered_category) split_part(path, '/', #{level}) AS filtered_category, categories.*"
15 18 }}
... ...
app/models/profile.rb
... ... @@ -22,6 +22,8 @@ class Profile &lt; ActiveRecord::Base
22 22 :display => %w[compact]
23 23 }
24 24  
  25 + NUMBER_OF_BOXES = 4
  26 +
25 27 def self.default_search_display
26 28 'compact'
27 29 end
... ... @@ -43,7 +45,7 @@ class Profile &lt; ActiveRecord::Base
43 45 find_role('editor', env_id)
44 46 end
45 47 def self.organization_member_roles(env_id)
46   - all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? }
  48 + all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? || !r.profile_id.nil?}
47 49 end
48 50 def self.all_roles(env_id)
49 51 Role.all :conditions => { :environment_id => env_id }
... ... @@ -69,12 +71,14 @@ class Profile &lt; ActiveRecord::Base
69 71 'manage_friends' => N_('Manage friends'),
70 72 'validate_enterprise' => N_('Validate enterprise'),
71 73 'perform_task' => N_('Perform task'),
  74 + 'view_tasks' => N_('View tasks'),
72 75 'moderate_comments' => N_('Moderate comments'),
73 76 'edit_appearance' => N_('Edit appearance'),
74 77 'view_private_content' => N_('View private content'),
75 78 'publish_content' => N_('Publish content'),
76 79 'invite_members' => N_('Invite members'),
77 80 'send_mail_to_members' => N_('Send e-Mail to members'),
  81 + 'manage_custom_roles' => N_('Manage custom roles'),
78 82 }
79 83  
80 84 acts_as_accessible
... ... @@ -317,16 +321,25 @@ class Profile &lt; ActiveRecord::Base
317 321 @top_level_articles ||= Article.top_level_for(self)
318 322 end
319 323  
320   - def self.is_available?(identifier, environment)
321   - !(identifier =~ IDENTIFIER_FORMAT).nil? && !RESERVED_IDENTIFIERS.include?(identifier) && Profile.find(:first, :conditions => ['environment_id = ? and identifier = ?', environment.id, identifier]).nil?
  324 + def self.is_available?(identifier, environment, profile_id=nil)
  325 + return false unless identifier =~ IDENTIFIER_FORMAT &&
  326 + !RESERVED_IDENTIFIERS.include?(identifier) &&
  327 + (NOOSFERO_CONF['exclude_profile_identifier_pattern'].blank? || identifier !~ /#{NOOSFERO_CONF['exclude_profile_identifier_pattern']}/)
  328 + return true if environment.nil?
  329 +
  330 + profiles = environment.profiles.where(:identifier => identifier)
  331 + profiles = profiles.where(['id != ?', profile_id]) if profile_id.present?
  332 + !profiles.exists?
322 333 end
323 334  
324 335 validates_presence_of :identifier, :name
325   - validates_format_of :identifier, :with => IDENTIFIER_FORMAT, :if => lambda { |profile| !profile.identifier.blank? }
326   - validates_exclusion_of :identifier, :in => RESERVED_IDENTIFIERS
327   - validates_uniqueness_of :identifier, :scope => :environment_id
328 336 validates_length_of :nickname, :maximum => 16, :allow_nil => true
329 337 validate :valid_template
  338 + validate :valid_identifier
  339 +
  340 + def valid_identifier
  341 + errors.add(:identifier, _('is not available.')) unless Profile.is_available?(identifier, environment, id)
  342 + end
330 343  
331 344 def valid_template
332 345 if template_id.present? && template && !template.is_template
... ... @@ -352,7 +365,7 @@ class Profile &lt; ActiveRecord::Base
352 365 if template
353 366 apply_template(template, :copy_articles => false)
354 367 else
355   - 3.times do
  368 + NUMBER_OF_BOXES.times do
356 369 self.boxes << Box.new
357 370 end
358 371  
... ... @@ -380,6 +393,9 @@ class Profile &lt; ActiveRecord::Base
380 393 new_block = block.class.new(:title => block[:title])
381 394 new_block.copy_from(block)
382 395 new_box.blocks << new_block
  396 + if block.mirror?
  397 + block.add_observer(new_block)
  398 + end
383 399 end
384 400 end
385 401 end
... ... @@ -395,6 +411,7 @@ class Profile &lt; ActiveRecord::Base
395 411 alias_method_chain :template, :default
396 412  
397 413 def apply_template(template, options = {:copy_articles => true})
  414 + self.template = template
398 415 copy_blocks_from(template)
399 416 copy_articles_from(template) if options[:copy_articles]
400 417 self.apply_type_specific_template(template)
... ... @@ -1008,7 +1025,7 @@ private :generate_url, :url_options
1008 1025 end
1009 1026  
1010 1027 def remove_from_suggestion_list(person)
1011   - suggestion = person.profile_suggestions.find_by_suggestion_id self.id
  1028 + suggestion = person.suggested_profiles.find_by_suggestion_id self.id
1012 1029 suggestion.disable if suggestion
1013 1030 end
1014 1031  
... ...
app/models/profile_suggestion.rb
... ... @@ -113,14 +113,14 @@ class ProfileSuggestion &lt; ActiveRecord::Base
113 113 suggested_profiles = all_suggestions(person)
114 114 return if suggested_profiles.nil?
115 115  
116   - already_suggested_profiles = person.profile_suggestions.map(&:suggestion_id).join(',')
  116 + already_suggested_profiles = person.suggested_profiles.map(&:suggestion_id).join(',')
117 117 suggested_profiles = suggested_profiles.where("profiles.id NOT IN (#{already_suggested_profiles})") if already_suggested_profiles.present?
118 118 #TODO suggested_profiles = suggested_profiles.order('score DESC')
119 119 suggested_profiles = suggested_profiles.limit(N_SUGGESTIONS)
120 120 return if suggested_profiles.blank?
121 121  
122 122 suggested_profiles.each do |suggested_profile|
123   - suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(suggested_profile.id)
  123 + suggestion = person.suggested_profiles.find_or_initialize_by_suggestion_id(suggested_profile.id)
124 124 RULES.each do |rule, options|
125 125 begin
126 126 value = suggested_profile.send("#{rule}_count").to_i
... ... @@ -273,7 +273,7 @@ class ProfileSuggestion &lt; ActiveRecord::Base
273 273 end
274 274  
275 275 def self.generate_profile_suggestions(person, force = false)
276   - return if person.profile_suggestions.enabled.count >= MIN_LIMIT && !force
  276 + return if person.suggested_profiles.enabled.count >= MIN_LIMIT && !force
277 277 Delayed::Job.enqueue ProfileSuggestionsJob.new(person.id) unless ProfileSuggestionsJob.exists?(person.id)
278 278 end
279 279  
... ...
app/models/suggest_article.rb
1 1 class SuggestArticle < Task
2 2  
3   - validates_presence_of :target_id, :article_name, :email, :name, :article_body
  3 + validates_presence_of :target_id
  4 + validates_presence_of :email, :name, :if => Proc.new { |task| task.requestor.blank? }
  5 + validates_associated :article_object
4 6  
5 7 settings_items :email, :type => String
6 8 settings_items :name, :type => String
7   - settings_items :article_name, :type => String
8   - settings_items :article_body, :type => String
9   - settings_items :article_abstract, :type => String
10   - settings_items :article_parent_id, :type => String
11   - settings_items :source, :type => String
12   - settings_items :source_name, :type => String
13   - settings_items :highlighted, :type => :boolean, :default => false
14 9 settings_items :ip_address, :type => String
15 10 settings_items :user_agent, :type => String
16 11 settings_items :referrer, :type => String
  12 + settings_items :article, :type => Hash, :default => {}
17 13  
18 14 after_create :schedule_spam_checking
19 15  
... ... @@ -24,34 +20,49 @@ class SuggestArticle &lt; Task
24 20 include Noosfero::Plugin::HotSpot
25 21  
26 22 def sender
27   - "#{name} (#{email})"
  23 + requestor ? "#{requestor.name}" : "#{name} (#{email})"
  24 + end
  25 +
  26 + def article_object
  27 + if @article_object.nil?
  28 + @article_object = article_type.new(article.merge(target.present? ? {:profile => target} : {}).except(:type))
  29 + if requestor.present?
  30 + @article_object.author = requestor
  31 + else
  32 + @article_object.author_name = name
  33 + end
  34 + end
  35 + @article_object
  36 + end
  37 +
  38 + def article_type
  39 + if article[:type].present?
  40 + type = article[:type].constantize
  41 + return type if type < Article
  42 + end
  43 + TinyMceArticle
28 44 end
29 45  
30 46 def perform
31   - task = TinyMceArticle.new
32   - task.profile = target
33   - task.name = article_name
34   - task.author_name = name
35   - task.body = article_body
36   - task.abstract = article_abstract
37   - task.parent_id = article_parent_id
38   - task.source = source
39   - task.source_name = source_name
40   - task.highlighted = highlighted
41   - task.save!
  47 + article_object.save!
42 48 end
43 49  
44 50 def title
45 51 _("Article suggestion")
46 52 end
47 53  
  54 + def article_name
  55 + article[:name]
  56 + end
  57 +
48 58 def subject
49 59 article_name
50 60 end
51 61  
52 62 def information
53   - { :message => _('%{sender} suggested the publication of the article: %{subject}.'),
54   - :variables => {:sender => sender} }
  63 + variables = requestor.blank? ? {:requestor => sender} : {}
  64 + { :message => _('%{requestor} suggested the publication of the article: %{subject}.'),
  65 + :variables => variables }
55 66 end
56 67  
57 68 def accept_details
... ... @@ -63,8 +74,8 @@ class SuggestArticle &lt; Task
63 74 end
64 75  
65 76 def target_notification_description
66   - _('%{sender} suggested the publication of the article: %{article}.') %
67   - {:sender => sender, :article => article_name}
  77 + _('%{requestor} suggested the publication of the article: %{article}.') %
  78 + {:requestor => sender, :article => article_name}
68 79 end
69 80  
70 81 def target_notification_message
... ...
app/models/task.rb
... ... @@ -33,6 +33,8 @@ class Task &lt; ActiveRecord::Base
33 33  
34 34 belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id
35 35 belongs_to :target, :foreign_key => :target_id, :polymorphic => true
  36 + belongs_to :responsible, :class_name => 'Person', :foreign_key => :responsible_id
  37 + belongs_to :closed_by, :class_name => 'Person', :foreign_key => :closed_by_id
36 38  
37 39 validates_uniqueness_of :code, :on => :create
38 40 validates_presence_of :code
... ... @@ -76,11 +78,9 @@ class Task &lt; ActiveRecord::Base
76 78 # this method finished the task. It calls #perform, which must be overriden
77 79 # by subclasses. At the end a message (as returned by #finish_message) is
78 80 # sent to the requestor with #notify_requestor.
79   - def finish
  81 + def finish(closed_by=nil)
80 82 transaction do
81   - self.status = Task::Status::FINISHED
82   - self.end_date = Time.now
83   - self.save!
  83 + close(Task::Status::FINISHED, closed_by)
84 84 self.perform
85 85 begin
86 86 send_notification(:finished)
... ... @@ -105,11 +105,9 @@ class Task &lt; ActiveRecord::Base
105 105  
106 106 # this method cancels the task. At the end a message (as returned by
107 107 # #cancel_message) is sent to the requestor with #notify_requestor.
108   - def cancel
  108 + def cancel(closed_by=nil)
109 109 transaction do
110   - self.status = Task::Status::CANCELLED
111   - self.end_date = Time.now
112   - self.save!
  110 + close(Task::Status::CANCELLED, closed_by)
113 111 begin
114 112 send_notification(:cancelled)
115 113 rescue NotImplementedError => ex
... ... @@ -118,6 +116,13 @@ class Task &lt; ActiveRecord::Base
118 116 end
119 117 end
120 118  
  119 + def close(status, closed_by)
  120 + self.status = status
  121 + self.end_date = Time.now
  122 + self.closed_by = closed_by
  123 + self.save!
  124 + end
  125 +
121 126 # Here are the tasks customizable options.
122 127  
123 128 def title
... ... @@ -239,6 +244,10 @@ class Task &lt; ActiveRecord::Base
239 244 scope :opened, :conditions => { :status => [Task::Status::ACTIVE, Task::Status::HIDDEN] }
240 245 scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} }
241 246 scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} }
  247 + scope :like, lambda { |field, value| where("LOWER(#{field}) LIKE ?", "%#{value.downcase}%") if value}
  248 + scope :pending_all, lambda { |profile, filter_type, filter_text|
  249 + self.to(profile).without_spam.pending.of(filter_type).like('data', filter_text)
  250 + }
242 251  
243 252 scope :to, lambda { |profile|
244 253 environment_condition = nil
... ...
app/models/uploaded_file.rb
1   -require 'short_filename'
2   -
3 1 # Article type that handles uploaded files.
4 2 #
5 3 # Limitation: only file metadata are versioned. Only the latest version
... ... @@ -14,8 +12,6 @@ class UploadedFile &lt; Article
14 12  
15 13 track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? }, :custom_target => :parent
16 14  
17   - include ShortFilename
18   -
19 15 def title
20 16 if self.name.present? then self.name else self.filename end
21 17 end
... ... @@ -65,7 +61,7 @@ class UploadedFile &lt; Article
65 61 # :min_size => 2.megabytes
66 62 # :max_size => 5.megabytes
67 63 has_attachment :storage => :file_system,
68   - :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' },
  64 + :thumbnails => { :icon => [24,24], :bigicon => [50,50], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' },
69 65 :thumbnail_class => Thumbnail,
70 66 :max_size => self.max_size
71 67  
... ...
app/models/user.rb
... ... @@ -45,7 +45,7 @@ class User &lt; ActiveRecord::Base
45 45 p = Person.new
46 46  
47 47 p.attributes = user.person_data
48   - p.identifier = user.login
  48 + p.identifier = user.login if p.identifier.blank?
49 49 p.user = user
50 50 p.environment = user.environment
51 51 p.name ||= user.name || user.login
... ...
app/presenters/image.rb
... ... @@ -4,6 +4,10 @@ class FilePresenter::Image &lt; FilePresenter
4 4 f.image? ? 10 : nil
5 5 end
6 6  
  7 + def sized_icon(size)
  8 + public_filename size
  9 + end
  10 +
7 11 def icon_name
8 12 public_filename :icon
9 13 end
... ...
app/views/admin_panel/_site_info.html.erb
... ... @@ -3,6 +3,21 @@
3 3 <%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %>
4 4 <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %>
5 5 <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %>
  6 +
  7 +<%= labelled_form_field(
  8 + _("Article's date format"),
  9 + select(:environment, :date_format,
  10 + options_for_select([
  11 + [ _('mm/dd/yyyy'), 'numbers_with_year'],
  12 + [ _('mm/dd'), 'numbers'],
  13 + [ _('Month dd, yyyy'), 'month_name_with_year'],
  14 + [ _('Month dd'), 'month_name'],
  15 + [ _('X minutes/hours/days/months/years ago'), 'past_time']
  16 + ], environment.date_format
  17 + )
  18 + )
  19 +) %>
  20 +
6 21 <%= required f.text_field(:reports_lower_bound, :size => 3) %>
7 22 <%= labelled_form_field(_('Default language'), select(:environment, :default_language, environment.locales.invert, { :selected => environment.default_locale, :include_blank => true })) %>
8 23 <%= label_tag :languages, _('Available languages') %>
... ...
app/views/admin_panel/index.html.erb
... ... @@ -18,9 +18,9 @@
18 18 <table>
19 19 <tr><td><%= link_to _('User roles'), :controller => 'role' %></td></tr>
20 20 <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr>
  21 + <tr><td><%= link_to _('Organizations'), :controller => 'organizations' %></td></tr>
21 22 <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr>
22 23 <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr>
23   - <tr><td><%= link_to _('Manage organizations status'), :action => 'manage_organizations_status' %></td></tr>
24 24 </table>
25 25  
26 26  
... ...
app/views/admin_panel/manage_organizations_status.html.erb
... ... @@ -1,69 +0,0 @@
1   -<h1><%= _('Manage organizations') %></h1>
2   -
3   -<%= form_tag( { :action => 'manage_organizations_status' }, :method => 'get', :class => 'users-search' ) do %>
4   -
5   - <div class="search-field">
6   - <span class="formfield">
7   - <%= text_field_tag 'q', @q, :title => _("Find profiles"), :style=>"width:85%" %>
8   - </span>
9   -
10   - <%= submit_button(:search, _('Search')) %>
11   - </div>
12   -
13   - <div class="environment-users-results-header">
14   - <div id='environment-users-filter-title'><%= @title %></div>
15   -
16   - <div id="environment-users-filter-filter">
17   - <strong><%= _("Filter by: ") %></strong>
18   -
19   - <select id="profile_filter_select">
20   - <%= options_for_select([['Any', 'any'],["Disabled profiles", "disabled"], ["Enabled profiles", "enabled"]], @filter) %>
21   - </select>
22   - </div>
23   - <div style="clear: both"></div>
24   - </div>
25   -
26   - <table>
27   - <colgroup>
28   - <col width="80%">
29   - <col width="20%">
30   - </colgroup>
31   -
32   - <tr>
33   - <th><%= _('Member') %></th>
34   - <th><%= _('Actions') %></th>
35   - </tr>
36   -
37   - <% @collection.each do |p| %>
38   - <tr title="<%= p.name %>">
39   - <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td>
40   -
41   - <td class='actions'>
42   - <div class="members-buttons-cell">
43   - <% if p.visible %>
44   - <%= button_without_text :'deactivate-user', _('Deactivate'), {:controller => "profile_editor", :action => 'deactivate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to deactivate this profile ?") %>
45   - <% else %>
46   - <%= button_without_text :'activate-user', _('Activate'), {:controller => "profile_editor", :action => 'activate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to activate this profile ?") %>
47   - <% end %>
48   - <%= button_without_text :'delete', _('Remove'), {:controller => "profile_editor", :action => 'destroy_profile', :profile => p.identifier, :id => p.id, :return_to => "/admin/admin_panel/manage_organizations_status"}, :method => :post, :confirm => _("Do you want to deactivate this profile ?") %>
49   - </div>
50   - </td>
51   - </tr>
52   - <% end %>
53   - </table>
54   -
55   -<% end %>
56   -
57   -<%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %>
58   -
59   -<% button_bar do %>
60   - <%= button :back, _('Back'), :controller => 'admin_panel' %>
61   -<% end %>
62   -
63   -<script type="text/javascript">
64   - jQuery(document).ready(function(){
65   - jQuery("#profile_filter_select").change(function(){
66   - document.location.href = '/admin/admin_panel/manage_organizations_status?filter='+this.value;
67   - });
68   - });
69   -</script>
70 0 \ No newline at end of file
app/views/blocks/profile_info_actions/_common.html.erb 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +<li><%= report_abuse(profile, :button) %></li>
  2 +<%= render_environment_features(:profile_actions) %>
... ...
app/views/blocks/profile_info_actions/_community.html.erb
... ... @@ -13,8 +13,6 @@
13 13 </li>
14 14 <% end %>
15 15  
16   - <li><%= report_abuse(profile, :button) %></li>
17   -
18   - <%= render_environment_features(:profile_actions) %>
  16 + <%= render :partial => 'blocks/profile_info_actions/common' %>
19 17 <% end %>
20 18 </ul>
... ...
app/views/blocks/profile_info_actions/_enterprise.html.erb
... ... @@ -8,5 +8,5 @@
8 8 <li><%= button(:'menu-mail', _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button'} ) %></li>
9 9 <% end %>
10 10  
11   - <li><%= report_abuse(profile, :button) %></li>
  11 + <%= render :partial => 'blocks/profile_info_actions/common' %>
12 12 </ul>
... ...
app/views/blocks/profile_info_actions/_join_leave_community.html.erb
1   -<div class='join-leave-button'>
  1 +<div class='join-leave-button require-login-popup'>
2 2 <% if logged_in? %>
3 3 <% if profile.members.include?(user) %>
4 4 <%= button(:delete, content_tag('span', _('Leave community')), profile.leave_url,
... ...
app/views/blocks/profile_info_actions/_person.html.erb
... ... @@ -11,6 +11,6 @@
11 11 <li><%= button(:back, _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}) %></li>
12 12 <% end %>
13 13  
14   - <li><%= report_abuse(profile, :button) %></li>
  14 + <%= render :partial => 'blocks/profile_info_actions/common' %>
15 15 <% end %>
16 16 </ul>
... ...
app/views/box_organizer/edit.html.erb
... ... @@ -5,12 +5,6 @@
5 5  
6 6 <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %>
7 7  
8   - <% if environment.admins.include?(user) %>
9   - <div class="fixed_block">
10   - <%= labelled_check_box(_("Fixed"), "block[fixed]", value = "1", checked = @block.fixed) %>
11   - </div>
12   - <% end %>
13   -
14 8 <%= render :partial => partial_for_class(@block.class) %>
15 9  
16 10 <div class="display">
... ... @@ -25,6 +19,21 @@
25 19  
26 20 <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %>
27 21  
  22 + <% if user.is_admin? %>
  23 + <div class="edit-modes">
  24 + <%= labelled_form_field _('Edit options:'), select_tag('block[edit_modes]', options_from_collection_for_select(@block.edit_block_options, :first, :last, @block.edit_modes)) %>
  25 + </div>
  26 + <div class="move-modes">
  27 + <%= labelled_form_field _('Move options:'), select_tag('block[move_modes]', options_from_collection_for_select(@block.move_block_options, :first, :last, @block.move_modes)) %>
  28 + </div>
  29 + <% end %>
  30 +
  31 + <% if @block.owner.kind_of?(Profile) && @block.owner.is_template? %>
  32 + <div class="mirror_block">
  33 + <%= labelled_check_box(_("Mirror"), "block[mirror]", value = "1", checked = @block.mirror) %>
  34 + </div>
  35 + <% end %>
  36 +
28 37 <% button_bar do %>
29 38 <%= submit_button(:save, _('Save')) %>
30 39 <%= modal_close_button(_('Cancel')) %>
... ...
app/views/chat/start_session_error.html.erb
1 1 <p>
2 2 <%= ui_icon('ui-icon-alert') %>
3   -<%= _('Could not connect to chat') %>, <a id='chat-retry' href='#' data-jid='<%= user.jid %>'><%= _('try again') %></a>.
  3 +<%= _('Could not connect to chat') %>, <a id='chat-retry' href='' data-jid='<%= user.jid %>'><%= _('try again') %></a>.
4 4 </p>
... ...
app/views/cms/_blog.html.erb
... ... @@ -64,7 +64,12 @@
64 64 <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%>
65 65 <% end %>
66 66  
67   -<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %>
  67 +<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [
  68 + [ _('Full post'), 'full'],
  69 + [ _('First paragraph'), 'short'],
  70 + [ _('First paragraph, with post picture'), 'short+pic'],
  71 + [ _("Title, Image, Lead"), 'compact']
  72 +])) %>
68 73  
69 74 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %>
70 75  
... ...
app/views/cms/_forum.html.erb
... ... @@ -2,6 +2,8 @@
2 2  
3 3 <h1><%= _('My Forum') %></h1>
4 4  
  5 +<%= required_fields_message %>
  6 +
5 7 <%= render :file => 'shared/tiny_mce' %>
6 8  
7 9 <%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %>
... ...
app/views/cms/_view_items.html.erb 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +<% @articles.each do |article| article = FilePresenter.for article %>
  2 + <tr title="<%= article.title%>" >
  3 + <td class="article-name">
  4 + <%= link_to_article(article) %>
  5 + </td>
  6 + <% short_description = article.respond_to?(:short_description) ?
  7 + article.short_description :
  8 + article.class.short_description %>
  9 + <td class="article-mime" title=<%= short_description.to_json %>>
  10 + <%= short_description %>
  11 + </td>
  12 + <td class="last-update">
  13 + <%= time_ago_in_words article.updated_at %>
  14 + </td>
  15 + <td class="article-controls">
  16 + <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit, article) %>
  17 + <%= button_without_text :eyes, _('Public view'), article.view_url %>
  18 + <%= display_spread_button(article) unless remove_content_button(:spread, article) %>
  19 + <% if user.can_change_homepage? && !remove_content_button(:home, article) %>
  20 + <% if profile.home_page != article %>
  21 + <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>
  22 + <% else %>
  23 + <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %>
  24 + <% end %>
  25 + <% end %>
  26 + <%= display_delete_button(article) if !remove_content_button(:delete, article) %>
  27 + </td>
  28 + </tr>
  29 +<% end %>
... ...
app/views/cms/suggest_an_article.html.erb
... ... @@ -6,21 +6,22 @@
6 6  
7 7 <%= labelled_form_for 'task' do |f| %>
8 8  
9   - <%= required labelled_form_field(_('Title'), text_field(:task, 'article_name', :size => 50)) %>
  9 + <%= required labelled_form_field(_('Title'), text_field('task[article]', 'name', :size => 50)) %>
10 10  
11   - <%= labelled_form_field(_('Source'), text_field(:task, 'source_name')) %>
  11 + <%= labelled_form_field(_('Source'), text_field('task[article]', 'source_name')) %>
12 12  
13   - <%= labelled_form_field(_('Source URL'), text_field(:task, 'source')) %>
  13 + <%= labelled_form_field(_('Source URL'), text_field('task[article]', 'source')) %>
14 14  
15   - <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %>
16   -
17   - <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %>
  15 + <% unless logged_in? %>
  16 + <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %>
  17 + <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %>
  18 + <% end %>
18 19  
19   - <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => :task, :abstract_method => 'article_abstract', :body_method => 'article_body'} %>
  20 + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => 'task[article]'} %>
20 21  
21 22 <%= hidden_field_tag('back_to', @back_to) %>
22 23  
23   - <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %>
  24 + <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %>
24 25  
25 26 <% button_bar do %>
26 27 <%= submit_button :save, _('Save') %>
... ...
app/views/cms/view.html.erb
... ... @@ -37,6 +37,7 @@
37 37 <tr>
38 38 <th><%= _('Name') %></th>
39 39 <th><%= _('Type') %></th>
  40 + <th><%= _('Last update') %></th>
40 41 <th><%= _('Actions') %></th>
41 42 </tr>
42 43  
... ... @@ -54,32 +55,7 @@
54 55 </tr>
55 56 <% end %>
56 57  
57   - <% @articles.each do |article| article = FilePresenter.for article %>
58   - <tr title="<%= article.title%>" >
59   - <td class="article-name">
60   - <%= link_to_article(article) %>
61   - </td>
62   - <% short_description = article.respond_to?(:short_description) ?
63   - article.short_description :
64   - article.class.short_description %>
65   - <td class="article-mime" title=<%= short_description.to_json %>>
66   - <%= short_description %>
67   - </td>
68   - <td class="article-controls">
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 %>
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 %>
74   - <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>
75   - <% else %>
76   - <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %>
77   - <% end %>
78   - <% end %>
79   - <%= display_delete_button(article) if !remove_content_button(:delete, article) %>
80   - </td>
81   - </tr>
82   - <% end %>
  58 + <%= render 'view_items' %>
83 59  
84 60 </table>
85 61  
... ...
app/views/content_viewer/_article_toolbar.html.erb
1 1 <div<%= user && " class='logged-in'" %>>
2 2 <div id="article-actions">
3 3  
  4 + <%= fullscreen_buttons('#article') %>
4 5  
5 6 <% if @page.allow_edit?(user) && !remove_content_button(:edit, @page) %>
6 7 <% content = content_tag('span', label_for_edit_article(@page)) %>
... ... @@ -29,6 +30,10 @@
29 30 <% end %>
30 31  
31 32 <%= modal_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) %>
  33 +
  34 + <% content = content_tag('span', label_for_clone_article(@page)) %>
  35 + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'new', :id => @page.id, :clone => true, :type => @page.class }) %>
  36 + <%= expirable_button @page, :clone, content, url %>
32 37 <% end %>
33 38  
34 39 <% if @page.accept_uploads? && @page.allow_create?(user) %>
... ... @@ -57,7 +62,7 @@
57 62 <% if @page.blog? and !@page.image.nil? %>
58 63 <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div>
59 64 <% end %>
60   - <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %>
  65 + <%= link_to(image_tag('/images/icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %>
61 66 <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
62 67 <%= article_title(@page, :no_link => true) %>
63 68 <%= article_translations(@page) %>
... ...
app/views/content_viewer/_display_compact_format.html.erb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +<% if article.image %>
  2 + <% className = "article-compact-abstract-with-image" %>
  3 + <% if article.image.thumbnails_processed? %>
  4 + <% image_file = article.image.public_filename(:big) %>
  5 + <% else %>
  6 + <% image_file = "/images/icons-app/image-loading-thumb.png" %>
  7 + <% end %>
  8 +<% else %>
  9 + <% className = "article-compact-abstract" %>
  10 +<% end %>
  11 +
  12 +<div>
  13 + <% if article.image %>
  14 + <div class = "article-compact-image">
  15 + <%= image_tag(image_file) %>
  16 + </div>
  17 + <% end %>
  18 + <div class = <%= className %> >
  19 + <%= article.abstract.truncate(400) %>
  20 + </div>
  21 +</div>
... ...
app/views/content_viewer/blog_page.html.erb
... ... @@ -8,7 +8,7 @@
8 8 </div>
9 9 </div>
10 10 <hr class="pre-posts"/>
11   -<div class="blog-posts">
  11 +<div class="blog-posts page-<%= @npage %>">
12 12 <% paginate = true %>
13 13 <%=
14 14 posts = @posts
... ... @@ -18,6 +18,9 @@
18 18 format = inside_block.visualization_format
19 19 paginate = false
20 20 end
21   - (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format, paginate))
  21 + (blog.empty? ?
  22 + content_tag('em', _('(no posts)')) :
  23 + list_posts(posts, format: format, paginate: paginate)
  24 + )
22 25 %>
23 26 </div>
... ...
app/views/content_viewer/folder.html.erb
1 1 <% unless folder.body.blank? %>
2   - <div>
  2 + <div class="folder-description">
3 3 <%= folder.body %>
4 4 </div>
5   - <hr/>
6 5 <% end %>
7 6  
8 7 <% if folder.children.empty? %>
... ...
app/views/features/manage_fields.html.erb
1 1 <h1><%= _('Manage fields displayed for profiles') %></h1>
2 2  
  3 +<%= javascript_include_tag "manage-fields.js" %>
  4 +
3 5 <% tabs = [] %>
4 6 <% tabs << {:title => _("Person's fields"), :id => 'person-fields',
5 7 :content => (render :partial => 'manage_person_fields')} %>
... ... @@ -11,5 +13,3 @@
11 13 <% end %>
12 14  
13 15 <%= render_tabs(tabs) %>
14   -
15   -<%= javascript_include_tag "manage-fields.js" %>
... ...
app/views/manage_products/_categories_autocomplete.html.erb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +<%= text_field_tag 'product_category_id', '', :placeholder => _('type a category for the product') %>
  2 +
  3 +<%= javascript_include_tag '/javascripts/product_categories.js' %>
  4 +<% javascript_tag do %>
  5 + product_categories.autocomplete.search_url = <%= url_for(:controller => :manage_products, :action => :search_categories).to_json %>
  6 + product_categories.autocomplete.select_url = <%= url_for(:controller => :manage_products, :action => :show_category_tree).to_json %>
  7 + product_categories.autocomplete.load('#product_category_id')
  8 +<% end %>
... ...
app/views/manage_products/_selected_category_tree.html.erb 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +<%= categories_container selects_for_all_ancestors(@category), hierarchy_category_navigation(@category, :make_links => true) %>
  2 +
... ...
app/views/manage_products/edit_category.html.erb
... ... @@ -16,7 +16,7 @@
16 16  
17 17 <h3><%= _('Edit category of this product:') %></h3>
18 18  
19   - <%= categories_container(selects_for_all_ancestors(@category), hierarchy_category_navigation(@category, :make_links => true)) %>
  19 + <%= render 'manage_products/selected_category_tree' %>
20 20  
21 21 <div id='categories_selection_actionbar'>
22 22 <%= button(:back, _('Back to product'), :action => 'show', :id => @product) %>
... ...
app/views/organizations/_results.html.erb 0 → 100644
... ... @@ -0,0 +1,41 @@
  1 +<div class='results'>
  2 + <table id='organizations-list'>
  3 + <colgroup>
  4 + <col width="60%">
  5 + <col width="20%">
  6 + <col width="20%">
  7 + </colgroup>
  8 +
  9 + <tr>
  10 + <th><%= _('Profile') %></th>
  11 + <th><%= _('Actions') %></th>
  12 + <th><%= _('Type') %>
  13 +
  14 + <%= select_tag(:type, options_for_select(@types_filter, @type)) %>
  15 + </th>
  16 + </tr>
  17 +
  18 + <% @collection.each do |p| %>
  19 + <tr title="<%= p.name %>">
  20 + <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td>
  21 +
  22 + <td class='actions'>
  23 + <div class="members-buttons-cell">
  24 + <% if p.visible %>
  25 + <%= button_without_text :'deactivate-user', _('Deactivate'), {:action => 'deactivate', :id => p.id}, :class => 'action', 'data-confirm' => _("Do you want to deactivate this organization?") %>
  26 + <% else %>
  27 + <%= button_without_text :'activate-user', _('Activate'), {:action => 'activate', :id => p.id}, :class => 'action', 'data-confirm' => _("Do you want to activate this organization?") %>
  28 + <% end %>
  29 + <%= button_without_text :'delete', _('Remove'), {:action => 'destroy', :id => p.id}, :class => 'action', 'data-method' => :post, 'data-confirm' => _("Do you want to destroy this organization?") %>
  30 + </div>
  31 + </td>
  32 +
  33 + <td> <%= _("#{p.type}") %> </td>
  34 + </tr>
  35 + <% end %>
  36 + </table>
  37 +
  38 + <div>
  39 + <%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %>
  40 + </div>
  41 +</div>
... ...
app/views/organizations/index.html.erb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +<h1><%= _('Organizations') %></h1>
  2 +
  3 +<%= form_tag( { :action => 'index' }, :method => 'get', :id => 'manage-profiles' ) do %>
  4 +
  5 + <div class="search-field">
  6 + <span class="formfield">
  7 + <%= text_field_tag 'q', @q, :title => _('Find organizations'), :style=>"width:85%" %>
  8 + </span>
  9 +
  10 + <%= submit_button(:search, _('Search')) %>
  11 + </div>
  12 +
  13 + <div class="environment-profiles-results-header">
  14 + <div id='environment-profiles-filter-title'><%= @title %></div>
  15 +
  16 + <div id="environment-profiles-filter-filter">
  17 + <strong><%= _("Filter by: ") %></strong>
  18 + <%= select_tag(:filter, options_for_select([[_('Any'), 'any'],[_('Disabled'), "disabled"], [_('Enabled') , "enabled"]], @filter)) %>
  19 + </div>
  20 + <div style="clear: both"></div>
  21 + </div>
  22 +
  23 + <%= render :partial => 'results' %>
  24 +
  25 + <% button_bar do %>
  26 + <%= button :back, _('Back'), :controller => 'admin_panel' %>
  27 + <% end %>
  28 +<% end %>
  29 +
  30 +<%= javascript_include_tag 'manage-organizations' %>
... ...
app/views/organizations/index.js.erb 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../../views/shared/admin/profiles/index.js.rb
0 2 \ No newline at end of file
... ...
app/views/person_notifier/mailer/_comment.html.erb
... ... @@ -19,7 +19,7 @@
19 19 <span style="font-size: 12px;"><%= comment.title %></span><br/>
20 20 <% end %>
21 21 <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/>
22   - <span style="font-size: 8px; color: #929292"><%= time_ago_as_sentence(comment.created_at) %></span>
  22 + <span style="font-size: 8px; color: #929292"><%= time_ago_in_words(comment.created_at) %></span>
23 23 <br style="clear: both;" />
24 24  
25 25 <% unless comment.replies.blank? %>
... ...
app/views/person_notifier/mailer/_create_article.html.erb
... ... @@ -6,7 +6,7 @@
6 6 <p>
7 7 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
8 8 <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span>
9   - <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  9 + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span>
10 10 </p>
11 11 <p>
12 12 <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span>
... ...
app/views/person_notifier/mailer/_default_activity.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <td>
6 6 <p>
7 7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
8   - <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  8 + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(activity.created_at) %></span>
9 9 </p>
10 10 </td>
11 11 </tr>
... ...
app/views/person_notifier/mailer/_task.html.erb
... ... @@ -12,7 +12,7 @@
12 12 <span style="font-size: 14px">
13 13 <%= task_information(task) %>
14 14 </span>
15   - <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(task.created_at) %></span>
  15 + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(task.created_at) %></span>
16 16 </div>
17 17 </td>
18 18 </tr>
... ...
app/views/person_notifier/mailer/_upload_image.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <td>
6 6 <p>
7 7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
8   - <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  8 + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span>
9 9 </p>
10 10 </td>
11 11 </tr>
... ...
app/views/profile/_comment.html.erb
... ... @@ -40,7 +40,7 @@
40 40 <%= txt2html comment.body %>
41 41 </div>
42 42 <div class="profile-activity-time">
43   - <%= time_ago_as_sentence(comment.created_at) %>
  43 + <%= time_ago_in_words(comment.created_at) %>
44 44 </div>
45 45 </div>
46 46  
... ...
app/views/profile/_create_article.html.erb
... ... @@ -12,7 +12,7 @@
12 12 <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') unless activity.params['lead'].blank? %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small>
13 13 </div>
14 14 <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %>
15   - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
  15 + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
16 16 <div class='profile-wall-actions'>
17 17 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
18 18 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :only_hide => true, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
... ...
app/views/profile/_default_activity.html.erb
... ... @@ -3,7 +3,7 @@
3 3 </div>
4 4 <div class='profile-activity-description'>
5 5 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
6   - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
  6 + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
7 7 <div class='profile-wall-actions'>
8 8 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
9 9 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
... ...
app/views/profile/_leave_scrap.html.erb
... ... @@ -3,7 +3,7 @@
3 3 </div>
4 4 <div class='profile-activity-description'>
5 5 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
6   - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
  6 + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
7 7 <div class='profile-wall-actions'>
8 8 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
9 9 </div>
... ...
app/views/profile/_profile_scrap.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <div class='profile-activity-description'>
6 6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p>
7 7 <p class='profile-activity-text'><%= txt2html scrap.content %></p>
8   - <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p>
  8 + <p class='profile-activity-time'><%= time_ago_in_words(scrap.created_at) %></p>
9 9 <div class='profile-wall-actions'>
10 10 <% if logged_in? && current_person.follows?(scrap.sender) %>
11 11 <span class='profile-activity-send-reply'>
... ... @@ -22,5 +22,5 @@
22 22 <% end %>
23 23 </ul>
24 24 <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %>
25   - <hr />
  25 + <hr />
26 26 </li>
... ...
app/views/profile/_profile_scraps.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <div class='profile-activity-description'>
6 6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p>
7 7 <p class='profile-activity-text'><%= txt2html scrap.content %></p>
8   - <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p>
  8 + <p class='profile-activity-time'><%= time_ago_in_words(scrap.created_at) %></p>
9 9 <div class='profile-wall-actions'>
10 10 <% if logged_in? && current_person.follows?(scrap.sender) %>
11 11 <span class='profile-activity-send-reply'>
... ...
app/views/profile/_upload_image.html.erb
... ... @@ -4,7 +4,7 @@
4 4 </div>
5 5 <div class='profile-activity-description'>
6 6 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
7   - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
  7 + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
8 8 <div class='profile-wall-actions'>
9 9 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
10 10 </div>
... ...
app/views/profile/content_tagged.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <h1><%= _('Content tagged with "%s"') % escaped_tag %></h1>
6 6  
7 7 <p>
8   -<%= link_to image_tag('icons-mime/rss-feed.png', :alt => _('Feed for this tag'), :title => _('Feed for this tag')), tag_feed_path, :class => 'blog-feed-link'%>
  8 +<%= link_to image_tag('/images/icons-mime/rss-feed.png', :alt => _('Feed for this tag'), :title => _('Feed for this tag')), tag_feed_path, :class => 'blog-feed-link'%>
9 9 </p>
10 10  
11 11 <% cache_timeout(@tag_cache_key, 4.hour) do %>
... ...
app/views/profile/report_abuse.html.erb
... ... @@ -24,7 +24,7 @@
24 24 $('#report-abuse-submit-button').css('cursor', 'progress');
25 25 $.ajax({
26 26 type: 'POST',
27   - url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}) %>,
  27 + url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}).to_json %>,
28 28 data: $(form).serialize(),
29 29 dataType: 'json',
30 30 success: function(data, status, ajax){
... ...