Commit 1c541c6f1431c436ece9fae60635390778647eea

Authored by Leandro Santos
2 parents a6c2ec9e e41d1f06

Merge branch 'serpro-context' of gitlab.com:participa/noosfero into serpro-context

Showing 366 changed files with 22696 additions and 8215 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 366 files displayed.

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 The samples of config file to configure a XMPP/BOSH server with ejabberd, 17 The samples of config file to configure a XMPP/BOSH server with ejabberd,
5 postgresql and apache2 can be found at util/chat directory. 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,7 +21,7 @@ This setup supposes that you are using Noosfero installed via Debian package
8 in a production environment. 21 in a production environment.
9 22
10 Steps 23 Steps
11 -===== 24 +-----
12 25
13 This is a step-by-step guide to get a XMPP service working, in a Debian system. 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,15 +157,8 @@ You should see a page with a message like that:
144 157
145 ## 9. Test chat session 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 Ruby-BOSH - SEND 163 Ruby-BOSH - SEND
158 <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"/> 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,8 +11,8 @@ as below:
11 11
12 # mkdir /etc/noosfero/ssl 12 # mkdir /etc/noosfero/ssl
13 # cd /etc/noosfero/ssl 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 # cat noosfero.key noosfero.cert > noosfero.pem 16 # cat noosfero.key noosfero.cert > noosfero.pem
17 17
18 ## Web server configuration 18 ## Web server configuration
@@ -74,7 +74,7 @@ downloading from git @@ -74,7 +74,7 @@ downloading from git
74 74
75 Here we are cloning the noosfero repository from git. Note: you will need to install git before. 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 $ cd current 78 $ cd current
79 $ git checkout -b stable origin/stable 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,22 +71,4 @@ class AdminPanelController &lt; AdminController
71 end 71 end
72 end 72 end
73 end 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 end 74 end
app/controllers/admin/organizations_controller.rb 0 → 100644
@@ -0,0 +1,66 @@ @@ -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/my_profile/cms_controller.rb
@@ -112,6 +112,11 @@ class CmsController &lt; MyProfileController @@ -112,6 +112,11 @@ class CmsController &lt; MyProfileController
112 end 112 end
113 end 113 end
114 end 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 end 120 end
116 121
117 def new 122 def new
@@ -144,7 +149,13 @@ class CmsController &lt; MyProfileController @@ -144,7 +149,13 @@ class CmsController &lt; MyProfileController
144 article_data = environment.enabled?('articles_dont_accept_comments_by_default') ? { :accept_comments => false } : {} 149 article_data = environment.enabled?('articles_dont_accept_comments_by_default') ? { :accept_comments => false } : {}
145 article_data.merge!(params[:article]) if params[:article] 150 article_data.merge!(params[:article]) if params[:article]
146 article_data.merge!(:profile => profile) if profile 151 article_data.merge!(:profile => profile) if profile
147 - @article = klass.new(article_data) 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
148 159
149 parent = check_parent(params[:parent_id]) 160 parent = check_parent(params[:parent_id])
150 if parent 161 if parent
app/controllers/my_profile/friends_controller.rb
1 class FriendsController < MyProfileController 1 class FriendsController < MyProfileController
2 - 2 +
3 protect 'manage_friends', :profile 3 protect 'manage_friends', :profile
4 - 4 +
5 def index 5 def index
6 - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) 6 + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page)
7 if is_cache_expired?(profile.manage_friends_cache_key(params)) 7 if is_cache_expired?(profile.manage_friends_cache_key(params))
8 @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) 8 @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage])
9 end 9 end
@@ -18,7 +18,7 @@ class FriendsController &lt; MyProfileController @@ -18,7 +18,7 @@ class FriendsController &lt; MyProfileController
18 end 18 end
19 19
20 def suggest 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 end 22 end
23 23
24 def remove_suggestion 24 def remove_suggestion
@@ -26,13 +26,13 @@ class FriendsController &lt; MyProfileController @@ -26,13 +26,13 @@ class FriendsController &lt; MyProfileController
26 redirect_to :action => 'suggest' unless @person 26 redirect_to :action => 'suggest' unless @person
27 if @person && request.post? 27 if @person && request.post?
28 profile.remove_suggestion(@person) 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 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page } 30 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page }
31 end 31 end
32 end 32 end
33 33
34 def connections 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 if @suggestion 36 if @suggestion
37 @tags = @suggestion.tag_connections 37 @tags = @suggestion.tag_connections
38 @profiles = @suggestion.profile_connections 38 @profiles = @suggestion.profile_connections
app/controllers/my_profile/memberships_controller.rb
@@ -40,7 +40,7 @@ class MembershipsController &lt; MyProfileController @@ -40,7 +40,7 @@ class MembershipsController &lt; MyProfileController
40 end 40 end
41 41
42 def suggest 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 end 44 end
45 45
46 def remove_suggestion 46 def remove_suggestion
@@ -49,13 +49,13 @@ class MembershipsController &lt; MyProfileController @@ -49,13 +49,13 @@ class MembershipsController &lt; MyProfileController
49 redirect_to :action => 'suggest' unless @community 49 redirect_to :action => 'suggest' unless @community
50 if @community && request.post? 50 if @community && request.post?
51 profile.remove_suggestion(@community) 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 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page} 53 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page}
54 end 54 end
55 end 55 end
56 56
57 def connections 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 if @suggestion 59 if @suggestion
60 @tags = @suggestion.tag_connections 60 @tags = @suggestion.tag_connections
61 @profiles = @suggestion.profile_connections 61 @profiles = @suggestion.profile_connections
app/controllers/my_profile/tasks_controller.rb
1 class TasksController < MyProfileController 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 def index 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 @task_types = Task.pending_types_for(profile) 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 @failed = params ? params[:failed] : {} 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 end 21 end
11 22
12 def processed 23 def processed
13 @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) 24 @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at)
14 end 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 VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] 40 VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ]
17 41
18 def close 42 def close
@@ -25,7 +49,7 @@ class TasksController &lt; MyProfileController @@ -25,7 +49,7 @@ class TasksController &lt; MyProfileController
25 task = profile.find_in_all_tasks(id) 49 task = profile.find_in_all_tasks(id)
26 begin 50 begin
27 task.update_attributes(value[:task]) 51 task.update_attributes(value[:task])
28 - task.send(decision) 52 + task.send(decision, current_person)
29 rescue Exception => ex 53 rescue Exception => ex
30 message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})" 54 message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"
31 failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message] 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,6 +2,7 @@ class ChatController &lt; PublicController
2 2
3 before_filter :login_required 3 before_filter :login_required
4 before_filter :check_environment_feature 4 before_filter :check_environment_feature
  5 + before_filter :can_send_message, :only => :register_message
5 6
6 def start_session 7 def start_session
7 login = user.jid 8 login = user.jid
@@ -54,6 +55,16 @@ class ChatController &lt; PublicController @@ -54,6 +55,16 @@ class ChatController &lt; PublicController
54 end 55 end
55 end 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 def update_presence_status 68 def update_presence_status
58 if request.xhr? 69 if request.xhr?
59 current_user.update_attributes({:chat_status_at => DateTime.now}.merge(params[:status] || {})) 70 current_user.update_attributes({:chat_status_at => DateTime.now}.merge(params[:status] || {}))
@@ -62,11 +73,17 @@ class ChatController &lt; PublicController @@ -62,11 +73,17 @@ class ChatController &lt; PublicController
62 end 73 end
63 74
64 def save_message 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 end 87 end
71 88
72 def recent_messages 89 def recent_messages
@@ -90,8 +107,9 @@ class ChatController &lt; PublicController @@ -90,8 +107,9 @@ class ChatController &lt; PublicController
90 end 107 end
91 108
92 def recent_conversations 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 end 113 end
96 114
97 #TODO Ideally this is done through roster table on ejabberd. 115 #TODO Ideally this is done through roster table on ejabberd.
@@ -108,4 +126,14 @@ class ChatController &lt; PublicController @@ -108,4 +126,14 @@ class ChatController &lt; PublicController
108 end 126 end
109 end 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 end 139 end
app/controllers/public/content_viewer_controller.rb
@@ -11,6 +11,7 @@ class ContentViewerController &lt; ApplicationController @@ -11,6 +11,7 @@ class ContentViewerController &lt; ApplicationController
11 path = get_path(params[:page], params[:format]) 11 path = get_path(params[:page], params[:format])
12 12
13 @version = params[:version].to_i 13 @version = params[:version].to_i
  14 + @npage = params[:npage] || '1'
14 15
15 if path.blank? 16 if path.blank?
16 @page = profile.home_page 17 @page = profile.home_page
@@ -127,7 +128,7 @@ class ContentViewerController &lt; ApplicationController @@ -127,7 +128,7 @@ class ContentViewerController &lt; ApplicationController
127 end 128 end
128 129
129 unless @page.display_to?(user) 130 unless @page.display_to?(user)
130 - if !profile.visible? || profile.secret? || (user && user.follows?(profile)) 131 + if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank?
131 render_access_denied 132 render_access_denied
132 else #!profile.public? 133 else #!profile.public?
133 private_profile_partial_parameters 134 private_profile_partial_parameters
app/helpers/application_helper.rb
@@ -871,7 +871,7 @@ module ApplicationHelper @@ -871,7 +871,7 @@ module ApplicationHelper
871 field_html += capture(&block) 871 field_html += capture(&block)
872 end 872 end
873 873
874 - 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?)
875 if profile.signup_fields.include?(name) 875 if profile.signup_fields.include?(name)
876 result = field_html 876 result = field_html
877 end 877 end
@@ -931,6 +931,19 @@ module ApplicationHelper @@ -931,6 +931,19 @@ module ApplicationHelper
931 article_helper.cms_label_for_edit 931 article_helper.cms_label_for_edit
932 end 932 end
933 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 +
934 def add_rss_feed_to_head(title, url) 947 def add_rss_feed_to_head(title, url)
935 content_for :feeds do 948 content_for :feeds do
936 tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url)) 949 tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url))
@@ -1202,35 +1215,6 @@ module ApplicationHelper @@ -1202,35 +1215,6 @@ module ApplicationHelper
1202 list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort 1215 list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort
1203 end 1216 end
1204 1217
1205 - #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+  
1206 - def time_ago_as_sentence(from_time, include_seconds = false)  
1207 - to_time = Time.now  
1208 - from_time = Time.parse(from_time.to_s)  
1209 - from_time = from_time.to_time if from_time.respond_to?(:to_time)  
1210 - to_time = to_time.to_time if to_time.respond_to?(:to_time)  
1211 - distance_in_minutes = (((to_time - from_time).abs)/60).round  
1212 - distance_in_seconds = ((to_time - from_time).abs).round  
1213 - case distance_in_minutes  
1214 - when 0..1  
1215 - return (distance_in_minutes == 0) ? _('less than a minute') : _('1 minute') unless include_seconds  
1216 - case distance_in_seconds  
1217 - when 0..4 then _('less than 5 seconds')  
1218 - when 5..9 then _('less than 10 seconds')  
1219 - when 10..19 then _('less than 20 seconds')  
1220 - when 20..39 then _('half a minute')  
1221 - when 40..59 then _('less than a minute')  
1222 - else _('1 minute')  
1223 - end  
1224 -  
1225 - when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes }  
1226 - when 45..89 then _('about 1 hour ago')  
1227 - when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round }  
1228 - when 1440..2879 then _('1 day ago')  
1229 - when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round }  
1230 - else show_time(from_time)  
1231 - end  
1232 - end  
1233 -  
1234 def comment_balloon(options = {}, &block) 1218 def comment_balloon(options = {}, &block)
1235 wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content') 1219 wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content')
1236 (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") } 1220 (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") }
@@ -1498,4 +1482,26 @@ module ApplicationHelper @@ -1498,4 +1482,26 @@ module ApplicationHelper
1498 text_field(object_name, method, options.merge(:class => 'colorpicker_field')) 1482 text_field(object_name, method, options.merge(:class => 'colorpicker_field'))
1499 end 1483 end
1500 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 +
1501 end 1507 end
app/helpers/article_helper.rb
@@ -12,6 +12,7 @@ module ArticleHelper @@ -12,6 +12,7 @@ module ArticleHelper
12 @article = article 12 @article = article
13 13
14 visibility_options(@article, tokenized_children) + 14 visibility_options(@article, tokenized_children) +
  15 + topic_creation(@article) +
15 content_tag('h4', _('Options')) + 16 content_tag('h4', _('Options')) +
16 content_tag('div', 17 content_tag('div',
17 (article.profile.has_members? ? 18 (article.profile.has_members? ?
@@ -55,14 +56,7 @@ module ArticleHelper @@ -55,14 +56,7 @@ module ArticleHelper
55 'div', 56 'div',
56 check_box(:article, :display_versions) + 57 check_box(:article, :display_versions) +
57 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions') 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 end 61 end
68 62
@@ -81,6 +75,22 @@ module ArticleHelper @@ -81,6 +75,22 @@ module ArticleHelper
81 ) 75 )
82 end 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 def privacity_exceptions(article, tokenized_children) 94 def privacity_exceptions(article, tokenized_children)
85 content_tag('div', 95 content_tag('div',
86 content_tag('div', 96 content_tag('div',
app/helpers/blog_helper.rb
@@ -22,7 +22,9 @@ module BlogHelper @@ -22,7 +22,9 @@ module BlogHelper
22 :param_name => 'npage', 22 :param_name => 'npage',
23 :previous_label => _('&laquo; Newer posts'), 23 :previous_label => _('&laquo; Newer posts'),
24 :next_label => _('Older posts &raquo;'), 24 :next_label => _('Older posts &raquo;'),
25 - :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} 25 + :params => {:action=>"view_page",
  26 + :page=>articles.first.parent.path.split('/'),
  27 + :controller=>"content_viewer"}
26 }) if articles.present? && conf[:paginate] 28 }) if articles.present? && conf[:paginate]
27 content = [] 29 content = []
28 artic_len = articles.length 30 artic_len = articles.length
@@ -44,7 +46,7 @@ module BlogHelper @@ -44,7 +46,7 @@ module BlogHelper
44 end 46 end
45 47
46 def display_post(article, format = 'full') 48 def display_post(article, format = 'full')
47 - no_comments = (format == 'full') ? false : true 49 + no_comments = (format == 'full' || format == 'compact' ) ? false : true
48 title = article_title(article, :no_comments => no_comments) 50 title = article_title(article, :no_comments => no_comments)
49 method = "display_#{format.split('+')[0]}_format" 51 method = "display_#{format.split('+')[0]}_format"
50 html = send(method, FilePresenter.for(article)).html_safe 52 html = send(method, FilePresenter.for(article)).html_safe
@@ -55,8 +57,12 @@ module BlogHelper @@ -55,8 +57,12 @@ module BlogHelper
55 else 57 else
56 '<div class="post-pic" style="background-image:url('+img+')"></div>' 58 '<div class="post-pic" style="background-image:url('+img+')"></div>'
57 end 59 end
58 - end.to_s +  
59 - title + html 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" }
60 end 66 end
61 67
62 def display_full_format(article) 68 def display_full_format(article)
app/helpers/boxes_helper.rb
@@ -122,7 +122,7 @@ module BoxesHelper @@ -122,7 +122,7 @@ module BoxesHelper
122 end 122 end
123 123
124 def wrap_main_content(content) 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 end 126 end
127 127
128 def extract_block_content(content) 128 def extract_block_content(content)
app/helpers/chat_helper.rb
@@ -9,12 +9,12 @@ module ChatHelper @@ -9,12 +9,12 @@ module ChatHelper
9 avatar = profile_image(user, :portrait, :class => 'avatar') 9 avatar = profile_image(user, :portrait, :class => 'avatar')
10 content_tag('span', 10 content_tag('span',
11 link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'), 11 link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'),
12 - '#', 12 + '',
13 :onclick => 'toggleMenu(this); return false', 13 :onclick => 'toggleMenu(this); return false',
14 :class => icon_class + ' simplemenu-trigger' 14 :class => icon_class + ' simplemenu-trigger'
15 ) + 15 ) +
16 content_tag('ul', 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 :style => 'display: none; z-index: 100', 18 :style => 'display: none; z-index: 100',
19 :class => 'simplemenu-submenu' 19 :class => 'simplemenu-submenu'
20 ), 20 ),
app/helpers/comment_helper.rb
1 module CommentHelper 1 module CommentHelper
  2 + include DatesHelper
2 3
3 def article_title(article, args = {}) 4 def article_title(article, args = {})
4 title = article.title 5 title = article.title
app/helpers/content_viewer_helper.rb
@@ -2,6 +2,7 @@ module ContentViewerHelper @@ -2,6 +2,7 @@ module ContentViewerHelper
2 2
3 include BlogHelper 3 include BlogHelper
4 include ForumHelper 4 include ForumHelper
  5 + include DatesHelper
5 6
6 def display_number_of_comments(n) 7 def display_number_of_comments(n)
7 base_str = "<span class='comment-count hide'>#{n}</span>" 8 base_str = "<span class='comment-count hide'>#{n}</span>"
@@ -24,8 +25,9 @@ module ContentViewerHelper @@ -24,8 +25,9 @@ module ContentViewerHelper
24 unless args[:no_comments] || !article.accept_comments 25 unless args[:no_comments] || !article.accept_comments
25 comments = (" - %s") % link_to_comments(article) 26 comments = (" - %s") % link_to_comments(article)
26 end 27 end
  28 + date_format = show_with_right_format_date article
27 title << content_tag('span', 29 title << content_tag('span',
28 - content_tag('span', show_date(article.published_at), :class => 'date') + 30 + date_format +
29 content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') + 31 content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') +
30 content_tag('span', comments, :class => 'comments'), 32 content_tag('span', comments, :class => 'comments'),
31 :class => 'created-at' 33 :class => 'created-at'
@@ -34,6 +36,24 @@ module ContentViewerHelper @@ -34,6 +36,24 @@ module ContentViewerHelper
34 title 36 title
35 end 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 def link_to_comments(article, args = {}) 57 def link_to_comments(article, args = {})
38 return '' unless article.accept_comments? 58 return '' unless article.accept_comments?
39 reference_to_article number_of_comments(article), article, 'comments_list' 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,6 +2,7 @@ require &#39;noosfero/i18n&#39;
2 2
3 module DatesHelper 3 module DatesHelper
4 4
  5 + include ActionView::Helpers::DateHelper
5 def months 6 def months
6 I18n.t('date.month_names') 7 I18n.t('date.month_names')
7 end 8 end
@@ -15,10 +16,12 @@ module DatesHelper @@ -15,10 +16,12 @@ module DatesHelper
15 end 16 end
16 17
17 # formats a date for displaying. 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 if date && use_numbers 20 if date && use_numbers
20 date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}') 21 date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}')
21 date_format % { :day => date.day, :month => date.month, :year => date.year } 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 elsif date 25 elsif date
23 date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}') 26 date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}')
24 date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year } 27 date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year }
app/helpers/events_helper.rb
1 module EventsHelper 1 module EventsHelper
2 2
  3 + include DatesHelper
3 def list_events(date, events) 4 def list_events(date, events)
4 title = _('Events for %s') % show_date_month(date) 5 title = _('Events for %s') % show_date_month(date)
5 content_tag('h2', title) + 6 content_tag('h2', title) +
app/helpers/folder_helper.rb
@@ -25,49 +25,32 @@ module FolderHelper @@ -25,49 +25,32 @@ module FolderHelper
25 articles.select {|article| article.display_to?(user)} 25 articles.select {|article| article.display_to?(user)}
26 end 26 end
27 27
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] 28 + def display_content_icon(content_item)
  29 + content = FilePresenter.for content_item
33 content_link = if content.image? 30 content_link = if content.image?
34 - link_to('&nbsp;' * (level * 4) +  
35 - image_tag(icon_for_article(content)) + short_filename(content.name), 31 + link_to(
  32 + image_tag(icon_for_article(content, :bigicon)),
36 content.url.merge(:view => true) 33 content.url.merge(:view => true)
37 ) 34 )
38 else 35 else
39 - link_to('&nbsp;' * (level * 4) +  
40 - short_filename(content.name),  
41 - content.url.merge(:view => true), :class => icon_for_article(content) 36 + link_to('',
  37 + content.url.merge(:view => true),
  38 + :class => icon_for_article(content, :bigicon)
42 ) 39 )
43 end 40 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 end 41 end
59 42
60 - def icon_for_article(article) 43 + def icon_for_article(article, size = 'icon')
61 article = FilePresenter.for article 44 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 45 + if article.respond_to?(:sized_icon)
  46 + article.sized_icon(size)
67 else 47 else
68 - klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ') 48 + icon = article.respond_to?(:icon_name) ?
  49 + article.icon_name :
  50 + article.class.icon_name(article)
  51 + klasses = "#{size} " + [icon].flatten.map{|name| "#{size}-"+name}.join(' ')
69 if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) 52 if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter)
70 - klasses += ' icon-upload-file' 53 + klasses += " #{size}-upload-file"
71 end 54 end
72 klasses 55 klasses
73 end 56 end
app/helpers/forum_helper.rb
1 module ForumHelper 1 module ForumHelper
  2 + include ActionView::Helpers::DateHelper
2 3
3 def cms_label_for_new_children 4 def cms_label_for_new_children
4 _('New discussion topic') 5 _('New discussion topic')
@@ -42,9 +43,9 @@ module ForumHelper @@ -42,9 +43,9 @@ module ForumHelper
42 def last_topic_update(article) 43 def last_topic_update(article)
43 info = article.info_from_last_update 44 info = article.info_from_last_update
44 if info[:author_url] 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 else 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 end 49 end
49 end 50 end
50 51
app/helpers/profile_editor_helper.rb
@@ -141,8 +141,9 @@ module ProfileEditorHelper @@ -141,8 +141,9 @@ module ProfileEditorHelper
141 ) 141 )
142 end 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 end 147 end
147 148
148 def unchangeable_privacy_field(profile) 149 def unchangeable_privacy_field(profile)
app/helpers/search_helper.rb
@@ -106,6 +106,10 @@ module SearchHelper @@ -106,6 +106,10 @@ module SearchHelper
106 end 106 end
107 end 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 def display_selector(asset, display, float = 'right') 113 def display_selector(asset, display, float = 'right')
110 display = nil if display.blank? 114 display = nil if display.blank?
111 display ||= asset_class(asset).default_search_display 115 display ||= asset_class(asset).default_search_display
app/helpers/tinymce_helper.rb
@@ -20,7 +20,7 @@ module TinymceHelper @@ -20,7 +20,7 @@ module TinymceHelper
20 :image_advtab => true, 20 :image_advtab => true,
21 :language => tinymce_language 21 :language => tinymce_language
22 22
23 - 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"
24 if options[:mode] == 'simple' 24 if options[:mode] == 'simple'
25 options[:menubar] = false 25 options[:menubar] = false
26 else 26 else
app/helpers/users_helper.rb
@@ -14,7 +14,7 @@ module UsersHelper @@ -14,7 +14,7 @@ module UsersHelper
14 select_field = select_tag(:filter, options, :onchange => onchange) 14 select_field = select_tag(:filter, options, :onchange => onchange)
15 content_tag('div', 15 content_tag('div',
16 content_tag('strong', _('Filter')) + ': ' + select_field, 16 content_tag('strong', _('Filter')) + ': ' + select_field,
17 - :class => "environment-users-customize-search" 17 + :class => "environment-profiles-customize-search"
18 ) 18 )
19 end 19 end
20 20
app/models/add_friend.rb
@@ -54,7 +54,7 @@ class AddFriend &lt; Task @@ -54,7 +54,7 @@ class AddFriend &lt; Task
54 end 54 end
55 55
56 def remove_from_suggestion_list(task) 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 suggestion.disable if suggestion 58 suggestion.disable if suggestion
59 end 59 end
60 end 60 end
app/models/article.rb
@@ -28,7 +28,7 @@ class Article &lt; ActiveRecord::Base @@ -28,7 +28,7 @@ class Article &lt; ActiveRecord::Base
28 def initialize(*params) 28 def initialize(*params)
29 super 29 super
30 30
31 - if !params.blank? && params.first.has_key?(:profile) 31 + if !params.blank? && params.first.has_key?(:profile) && !params.first[:profile].blank?
32 profile = params.first[:profile] 32 profile = params.first[:profile]
33 self.published = false unless profile.public? 33 self.published = false unless profile.public?
34 end 34 end
@@ -96,6 +96,8 @@ class Article &lt; ActiveRecord::Base @@ -96,6 +96,8 @@ class Article &lt; ActiveRecord::Base
96 belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id 96 belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id
97 before_destroy :rotate_translations 97 before_destroy :rotate_translations
98 98
  99 + acts_as_voteable
  100 +
99 before_create do |article| 101 before_create do |article|
100 article.published_at ||= Time.now 102 article.published_at ||= Time.now
101 if article.reference_article && !article.parent 103 if article.reference_article && !article.parent
@@ -498,13 +500,13 @@ class Article &lt; ActiveRecord::Base @@ -498,13 +500,13 @@ class Article &lt; ActiveRecord::Base
498 500
499 scope :display_filter, lambda {|user, profile| 501 scope :display_filter, lambda {|user, profile|
500 return published if (user.nil? && profile && profile.public?) 502 return published if (user.nil? && profile && profile.public?)
501 - return [] if user.nil? || profile.nil? || (profile && !profile.public? && !user.follows?(profile)) 503 + return [] if user.nil? || (profile && !profile.public? && !user.follows?(profile))
502 where( 504 where(
503 [ 505 [
504 "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ? 506 "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ?
505 OR (show_to_followers = ? AND ? AND profile_id = ?)", true, user.id, user.id, 507 OR (show_to_followers = ? AND ? AND profile_id = ?)", true, user.id, user.id,
506 profile.nil? ? false : user.has_permission?(:view_private_content, profile), 508 profile.nil? ? false : user.has_permission?(:view_private_content, profile),
507 - true, user.follows?(profile), profile.id 509 + true, user.follows?(profile), (profile.nil? ? nil : profile.id)
508 ] 510 ]
509 ) 511 )
510 } 512 }
@@ -577,25 +579,24 @@ class Article &lt; ActiveRecord::Base @@ -577,25 +579,24 @@ class Article &lt; ActiveRecord::Base
577 profile.visible? && profile.public? && published? 579 profile.visible? && profile.public? && published?
578 end 580 end
579 581
580 -  
581 - def copy(options = {}) 582 + def copy_without_save(options = {})
582 attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) } 583 attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) }
583 attrs.merge!(options) 584 attrs.merge!(options)
584 object = self.class.new 585 object = self.class.new
585 attrs.each do |key, value| 586 attrs.each do |key, value|
586 object.send(key.to_s+'=', value) 587 object.send(key.to_s+'=', value)
587 end 588 end
  589 + object
  590 + end
  591 +
  592 + def copy(options = {})
  593 + object = copy_without_save(options)
588 object.save 594 object.save
589 object 595 object
590 end 596 end
591 597
592 def copy!(options = {}) 598 def copy!(options = {})
593 - attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) }  
594 - attrs.merge!(options)  
595 - object = self.class.new  
596 - attrs.each do |key, value|  
597 - object.send(key.to_s+'=', value)  
598 - end 599 + object = copy_without_save(options)
599 object.save! 600 object.save!
600 object 601 object
601 end 602 end
app/models/block.rb
@@ -2,7 +2,7 @@ class Block &lt; ActiveRecord::Base @@ -2,7 +2,7 @@ class Block &lt; ActiveRecord::Base
2 2
3 attr_accessible :title, :display, :limit, :box_id, :posts_per_page, 3 attr_accessible :title, :display, :limit, :box_id, :posts_per_page,
4 :visualization_format, :language, :display_user, 4 :visualization_format, :language, :display_user,
5 - :box, :edit_modes, :move_modes 5 + :box, :edit_modes, :move_modes, :mirror
6 6
7 # to be able to generate HTML 7 # to be able to generate HTML
8 include ActionView::Helpers::UrlHelper 8 include ActionView::Helpers::UrlHelper
@@ -15,11 +15,23 @@ class Block &lt; ActiveRecord::Base @@ -15,11 +15,23 @@ class Block &lt; ActiveRecord::Base
15 15
16 acts_as_list :scope => :box 16 acts_as_list :scope => :box
17 belongs_to :box 17 belongs_to :box
  18 + belongs_to :mirror_block, :class_name => "Block"
  19 + has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id"
18 20
19 acts_as_having_settings 21 acts_as_having_settings
20 22
21 scope :enabled, :conditions => { :enabled => true } 23 scope :enabled, :conditions => { :enabled => true }
22 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 +
23 def embedable? 35 def embedable?
24 false 36 false
25 end 37 end
@@ -269,6 +281,10 @@ class Block &lt; ActiveRecord::Base @@ -269,6 +281,10 @@ class Block &lt; ActiveRecord::Base
269 self.position = block.position 281 self.position = block.position
270 end 282 end
271 283
  284 + def add_observer(block)
  285 + self.observers << block
  286 + end
  287 +
272 private 288 private
273 289
274 def home_page_path 290 def home_page_path
app/models/blog.rb
@@ -76,9 +76,12 @@ class Blog &lt; Folder @@ -76,9 +76,12 @@ class Blog &lt; Folder
76 end 76 end
77 77
78 settings_items :visualization_format, :type => :string, :default => 'full' 78 settings_items :visualization_format, :type => :string, :default => 'full'
79 - validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :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 alias :display_posts_in_current_language? :display_posts_in_current_language 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 +4,5 @@ class ChatMessage &lt; ActiveRecord::Base
4 belongs_to :to, :class_name => 'Profile' 4 belongs_to :to, :class_name => 'Profile'
5 belongs_to :from, :class_name => 'Profile' 5 belongs_to :from, :class_name => 'Profile'
6 6
  7 + validates_presence_of :from, :to
7 end 8 end
app/models/comment.rb
@@ -37,6 +37,8 @@ class Comment &lt; ActiveRecord::Base @@ -37,6 +37,8 @@ class Comment &lt; ActiveRecord::Base
37 37
38 xss_terminate :only => [ :body, :title, :name ], :on => 'validation' 38 xss_terminate :only => [ :body, :title, :name ], :on => 'validation'
39 39
  40 + acts_as_voteable
  41 +
40 def comment_root 42 def comment_root
41 (reply_of && reply_of.comment_root) || self 43 (reply_of && reply_of.comment_root) || self
42 end 44 end
app/models/environment.rb
@@ -3,7 +3,17 @@ @@ -3,7 +3,17 @@
3 # domains. 3 # domains.
4 class Environment < ActiveRecord::Base 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 has_many :users 18 has_many :users
9 19
@@ -14,6 +24,12 @@ class Environment &lt; ActiveRecord::Base @@ -14,6 +24,12 @@ class Environment &lt; ActiveRecord::Base
14 24
15 IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ 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 def self.verify_filename(filename) 33 def self.verify_filename(filename)
18 filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS 34 filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS
19 filename 35 filename
@@ -29,6 +45,7 @@ class Environment &lt; ActiveRecord::Base @@ -29,6 +45,7 @@ class Environment &lt; ActiveRecord::Base
29 'manage_environment_roles' => N_('Manage environment roles'), 45 'manage_environment_roles' => N_('Manage environment roles'),
30 'manage_environment_validators' => N_('Manage environment validators'), 46 'manage_environment_validators' => N_('Manage environment validators'),
31 'manage_environment_users' => N_('Manage environment users'), 47 'manage_environment_users' => N_('Manage environment users'),
  48 + 'manage_environment_organizations' => N_('Manage environment organizations'),
32 'manage_environment_templates' => N_('Manage environment templates'), 49 'manage_environment_templates' => N_('Manage environment templates'),
33 'manage_environment_licenses' => N_('Manage environment licenses'), 50 'manage_environment_licenses' => N_('Manage environment licenses'),
34 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'), 51 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'),
@@ -74,7 +91,8 @@ class Environment &lt; ActiveRecord::Base @@ -74,7 +91,8 @@ class Environment &lt; ActiveRecord::Base
74 'edit_profile_design', 91 'edit_profile_design',
75 'manage_products', 92 'manage_products',
76 'manage_friends', 93 'manage_friends',
77 - 'perform_task' 94 + 'perform_task',
  95 + 'view_tasks'
78 ] 96 ]
79 ) 97 )
80 end 98 end
@@ -339,6 +357,16 @@ class Environment &lt; ActiveRecord::Base @@ -339,6 +357,16 @@ class Environment &lt; ActiveRecord::Base
339 self.save! 357 self.save!
340 end 358 end
341 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 +
342 # Disables a feature identified by its name 370 # Disables a feature identified by its name
343 def disable(feature, must_save=true) 371 def disable(feature, must_save=true)
344 self.settings["#{feature}_enabled".to_sym] = false 372 self.settings["#{feature}_enabled".to_sym] = false
app/models/forum.rb
@@ -3,11 +3,11 @@ class Forum &lt; Folder @@ -3,11 +3,11 @@ class Forum &lt; Folder
3 acts_as_having_posts :order => 'updated_at DESC' 3 acts_as_having_posts :order => 'updated_at DESC'
4 include PostsLimit 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 settings_items :terms_of_use, :type => :string, :default => "" 8 settings_items :terms_of_use, :type => :string, :default => ""
9 settings_items :has_terms_of_use, :type => :boolean, :default => false 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 has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people' 11 has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people'
12 12
13 before_save do |forum| 13 before_save do |forum|
@@ -33,6 +33,23 @@ class Forum &lt; Folder @@ -33,6 +33,23 @@ class Forum &lt; Folder
33 _('An internet forum, also called message board, where discussions can be held.') 33 _('An internet forum, also called message board, where discussions can be held.')
34 end 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 include ActionView::Helpers::TagHelper 53 include ActionView::Helpers::TagHelper
37 def to_html(options = {}) 54 def to_html(options = {})
38 proc do 55 proc do
@@ -69,11 +86,17 @@ class Forum &lt; Folder @@ -69,11 +86,17 @@ class Forum &lt; Folder
69 self.users_with_agreement.exists? user 86 self.users_with_agreement.exists? user
70 end 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 end 97 end
75 98
76 def allow_create?(user) 99 def allow_create?(user)
77 - super || can_create_topic?(user, profile) 100 + super || can_create_topic?(user)
78 end 101 end
79 end 102 end
app/models/person.rb
@@ -84,9 +84,9 @@ roles] } @@ -84,9 +84,9 @@ roles] }
84 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' 84 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people'
85 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' 85 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions'
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 scope :more_popular, :order => 'friends_count DESC' 91 scope :more_popular, :order => 'friends_count DESC'
92 92
@@ -103,6 +103,8 @@ roles] } @@ -103,6 +103,8 @@ roles] }
103 103
104 belongs_to :user, :dependent => :delete 104 belongs_to :user, :dependent => :delete
105 105
  106 + acts_as_voter
  107 +
106 def can_change_homepage? 108 def can_change_homepage?
107 !environment.enabled?('cant_change_homepage') || is_admin? 109 !environment.enabled?('cant_change_homepage') || is_admin?
108 end 110 end
@@ -522,7 +524,7 @@ roles] } @@ -522,7 +524,7 @@ roles] }
522 end 524 end
523 525
524 def remove_suggestion(profile) 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 suggestion.disable if suggestion 528 suggestion.disable if suggestion
527 end 529 end
528 530
app/models/product_category.rb
@@ -10,6 +10,9 @@ class ProductCategory &lt; Category @@ -10,6 +10,9 @@ class ProductCategory &lt; Category
10 :joins => :products, 10 :joins => :products,
11 :conditions => ['products.profile_id = ?', enterprise.id] 11 :conditions => ['products.profile_id = ?', enterprise.id]
12 }} 12 }}
  13 + scope :by_environment, lambda { |environment| {
  14 + :conditions => ['environment_id = ?', environment.id]
  15 + }}
13 scope :unique_by_level, lambda { |level| { 16 scope :unique_by_level, lambda { |level| {
14 :select => "DISTINCT ON (filtered_category) split_part(path, '/', #{level}) AS filtered_category, categories.*" 17 :select => "DISTINCT ON (filtered_category) split_part(path, '/', #{level}) AS filtered_category, categories.*"
15 }} 18 }}
app/models/profile.rb
@@ -71,6 +71,7 @@ class Profile &lt; ActiveRecord::Base @@ -71,6 +71,7 @@ class Profile &lt; ActiveRecord::Base
71 'manage_friends' => N_('Manage friends'), 71 'manage_friends' => N_('Manage friends'),
72 'validate_enterprise' => N_('Validate enterprise'), 72 'validate_enterprise' => N_('Validate enterprise'),
73 'perform_task' => N_('Perform task'), 73 'perform_task' => N_('Perform task'),
  74 + 'view_tasks' => N_('View tasks'),
74 'moderate_comments' => N_('Moderate comments'), 75 'moderate_comments' => N_('Moderate comments'),
75 'edit_appearance' => N_('Edit appearance'), 76 'edit_appearance' => N_('Edit appearance'),
76 'view_private_content' => N_('View private content'), 77 'view_private_content' => N_('View private content'),
@@ -392,6 +393,9 @@ class Profile &lt; ActiveRecord::Base @@ -392,6 +393,9 @@ class Profile &lt; ActiveRecord::Base
392 new_block = block.class.new(:title => block[:title]) 393 new_block = block.class.new(:title => block[:title])
393 new_block.copy_from(block) 394 new_block.copy_from(block)
394 new_box.blocks << new_block 395 new_box.blocks << new_block
  396 + if block.mirror?
  397 + block.add_observer(new_block)
  398 + end
395 end 399 end
396 end 400 end
397 end 401 end
@@ -1021,7 +1025,7 @@ private :generate_url, :url_options @@ -1021,7 +1025,7 @@ private :generate_url, :url_options
1021 end 1025 end
1022 1026
1023 def remove_from_suggestion_list(person) 1027 def remove_from_suggestion_list(person)
1024 - suggestion = person.profile_suggestions.find_by_suggestion_id self.id 1028 + suggestion = person.suggested_profiles.find_by_suggestion_id self.id
1025 suggestion.disable if suggestion 1029 suggestion.disable if suggestion
1026 end 1030 end
1027 1031
app/models/profile_suggestion.rb
@@ -113,14 +113,14 @@ class ProfileSuggestion &lt; ActiveRecord::Base @@ -113,14 +113,14 @@ class ProfileSuggestion &lt; ActiveRecord::Base
113 suggested_profiles = all_suggestions(person) 113 suggested_profiles = all_suggestions(person)
114 return if suggested_profiles.nil? 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 suggested_profiles = suggested_profiles.where("profiles.id NOT IN (#{already_suggested_profiles})") if already_suggested_profiles.present? 117 suggested_profiles = suggested_profiles.where("profiles.id NOT IN (#{already_suggested_profiles})") if already_suggested_profiles.present?
118 #TODO suggested_profiles = suggested_profiles.order('score DESC') 118 #TODO suggested_profiles = suggested_profiles.order('score DESC')
119 suggested_profiles = suggested_profiles.limit(N_SUGGESTIONS) 119 suggested_profiles = suggested_profiles.limit(N_SUGGESTIONS)
120 return if suggested_profiles.blank? 120 return if suggested_profiles.blank?
121 121
122 suggested_profiles.each do |suggested_profile| 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 RULES.each do |rule, options| 124 RULES.each do |rule, options|
125 begin 125 begin
126 value = suggested_profile.send("#{rule}_count").to_i 126 value = suggested_profile.send("#{rule}_count").to_i
@@ -273,7 +273,7 @@ class ProfileSuggestion &lt; ActiveRecord::Base @@ -273,7 +273,7 @@ class ProfileSuggestion &lt; ActiveRecord::Base
273 end 273 end
274 274
275 def self.generate_profile_suggestions(person, force = false) 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 Delayed::Job.enqueue ProfileSuggestionsJob.new(person.id) unless ProfileSuggestionsJob.exists?(person.id) 277 Delayed::Job.enqueue ProfileSuggestionsJob.new(person.id) unless ProfileSuggestionsJob.exists?(person.id)
278 end 278 end
279 279
app/models/suggest_article.rb
@@ -25,7 +25,7 @@ class SuggestArticle &lt; Task @@ -25,7 +25,7 @@ class SuggestArticle &lt; Task
25 25
26 def article_object 26 def article_object
27 if @article_object.nil? 27 if @article_object.nil?
28 - @article_object = article_type.new(article.merge({:profile => target}).except(:type)) 28 + @article_object = article_type.new(article.merge(target.present? ? {:profile => target} : {}).except(:type))
29 if requestor.present? 29 if requestor.present?
30 @article_object.author = requestor 30 @article_object.author = requestor
31 else 31 else
app/models/task.rb
@@ -33,6 +33,8 @@ class Task &lt; ActiveRecord::Base @@ -33,6 +33,8 @@ class Task &lt; ActiveRecord::Base
33 33
34 belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id 34 belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id
35 belongs_to :target, :foreign_key => :target_id, :polymorphic => true 35 belongs_to :target, :foreign_key => :target_id, :polymorphic => true
  36 + 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 validates_uniqueness_of :code, :on => :create 39 validates_uniqueness_of :code, :on => :create
38 validates_presence_of :code 40 validates_presence_of :code
@@ -76,11 +78,9 @@ class Task &lt; ActiveRecord::Base @@ -76,11 +78,9 @@ class Task &lt; ActiveRecord::Base
76 # this method finished the task. It calls #perform, which must be overriden 78 # this method finished the task. It calls #perform, which must be overriden
77 # by subclasses. At the end a message (as returned by #finish_message) is 79 # by subclasses. At the end a message (as returned by #finish_message) is
78 # sent to the requestor with #notify_requestor. 80 # sent to the requestor with #notify_requestor.
79 - def finish 81 + def finish(closed_by=nil)
80 transaction do 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 self.perform 84 self.perform
85 begin 85 begin
86 send_notification(:finished) 86 send_notification(:finished)
@@ -105,11 +105,9 @@ class Task &lt; ActiveRecord::Base @@ -105,11 +105,9 @@ class Task &lt; ActiveRecord::Base
105 105
106 # this method cancels the task. At the end a message (as returned by 106 # this method cancels the task. At the end a message (as returned by
107 # #cancel_message) is sent to the requestor with #notify_requestor. 107 # #cancel_message) is sent to the requestor with #notify_requestor.
108 - def cancel 108 + def cancel(closed_by=nil)
109 transaction do 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 begin 111 begin
114 send_notification(:cancelled) 112 send_notification(:cancelled)
115 rescue NotImplementedError => ex 113 rescue NotImplementedError => ex
@@ -118,6 +116,13 @@ class Task &lt; ActiveRecord::Base @@ -118,6 +116,13 @@ class Task &lt; ActiveRecord::Base
118 end 116 end
119 end 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 # Here are the tasks customizable options. 126 # Here are the tasks customizable options.
122 127
123 def title 128 def title
@@ -239,6 +244,10 @@ class Task &lt; ActiveRecord::Base @@ -239,6 +244,10 @@ class Task &lt; ActiveRecord::Base
239 scope :opened, :conditions => { :status => [Task::Status::ACTIVE, Task::Status::HIDDEN] } 244 scope :opened, :conditions => { :status => [Task::Status::ACTIVE, Task::Status::HIDDEN] }
240 scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } 245 scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} }
241 scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } 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 scope :to, lambda { |profile| 252 scope :to, lambda { |profile|
244 environment_condition = nil 253 environment_condition = nil
app/models/uploaded_file.rb
@@ -65,7 +65,7 @@ class UploadedFile &lt; Article @@ -65,7 +65,7 @@ class UploadedFile &lt; Article
65 # :min_size => 2.megabytes 65 # :min_size => 2.megabytes
66 # :max_size => 5.megabytes 66 # :max_size => 5.megabytes
67 has_attachment :storage => :file_system, 67 has_attachment :storage => :file_system,
68 - :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, 68 + :thumbnails => { :icon => [24,24], :bigicon => [50,50], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' },
69 :thumbnail_class => Thumbnail, 69 :thumbnail_class => Thumbnail,
70 :max_size => self.max_size 70 :max_size => self.max_size
71 71
app/presenters/image.rb
@@ -4,6 +4,10 @@ class FilePresenter::Image &lt; FilePresenter @@ -4,6 +4,10 @@ class FilePresenter::Image &lt; FilePresenter
4 f.image? ? 10 : nil 4 f.image? ? 10 : nil
5 end 5 end
6 6
  7 + def sized_icon(size)
  8 + public_filename size
  9 + end
  10 +
7 def icon_name 11 def icon_name
8 public_filename :icon 12 public_filename :icon
9 end 13 end
app/views/admin_panel/_site_info.html.erb
@@ -3,6 +3,21 @@ @@ -3,6 +3,21 @@
3 <%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %> 3 <%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %>
4 <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %> 4 <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %>
5 <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %> 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 <%= required f.text_field(:reports_lower_bound, :size => 3) %> 21 <%= required f.text_field(:reports_lower_bound, :size => 3) %>
7 <%= labelled_form_field(_('Default language'), select(:environment, :default_language, environment.locales.invert, { :selected => environment.default_locale, :include_blank => true })) %> 22 <%= labelled_form_field(_('Default language'), select(:environment, :default_language, environment.locales.invert, { :selected => environment.default_locale, :include_blank => true })) %>
8 <%= label_tag :languages, _('Available languages') %> 23 <%= label_tag :languages, _('Available languages') %>
app/views/admin_panel/index.html.erb
@@ -18,9 +18,9 @@ @@ -18,9 +18,9 @@
18 <table> 18 <table>
19 <tr><td><%= link_to _('User roles'), :controller => 'role' %></td></tr> 19 <tr><td><%= link_to _('User roles'), :controller => 'role' %></td></tr>
20 <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> 20 <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr>
  21 + <tr><td><%= link_to _('Organizations'), :controller => 'organizations' %></td></tr>
21 <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> 22 <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr>
22 <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> 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 </table> 24 </table>
25 25
26 26
app/views/admin_panel/manage_organizations_status.html.erb
@@ -1,69 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
app/views/blocks/profile_info_actions/_common.html.erb 0 → 100644
@@ -0,0 +1,2 @@ @@ -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,8 +13,6 @@
13 </li> 13 </li>
14 <% end %> 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 <% end %> 17 <% end %>
20 </ul> 18 </ul>
app/views/blocks/profile_info_actions/_enterprise.html.erb
@@ -8,5 +8,5 @@ @@ -8,5 +8,5 @@
8 <li><%= button(:'menu-mail', _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button'} ) %></li> 8 <li><%= button(:'menu-mail', _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button'} ) %></li>
9 <% end %> 9 <% end %>
10 10
11 - <li><%= report_abuse(profile, :button) %></li> 11 + <%= render :partial => 'blocks/profile_info_actions/common' %>
12 </ul> 12 </ul>
app/views/blocks/profile_info_actions/_person.html.erb
@@ -11,6 +11,6 @@ @@ -11,6 +11,6 @@
11 <li><%= button(:back, _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}) %></li> 11 <li><%= button(:back, _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}) %></li>
12 <% end %> 12 <% end %>
13 13
14 - <li><%= report_abuse(profile, :button) %></li> 14 + <%= render :partial => 'blocks/profile_info_actions/common' %>
15 <% end %> 15 <% end %>
16 </ul> 16 </ul>
app/views/box_organizer/edit.html.erb
@@ -28,6 +28,12 @@ @@ -28,6 +28,12 @@
28 </div> 28 </div>
29 <% end %> 29 <% end %>
30 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 +
31 <% button_bar do %> 37 <% button_bar do %>
32 <%= submit_button(:save, _('Save')) %> 38 <%= submit_button(:save, _('Save')) %>
33 <%= modal_close_button(_('Cancel')) %> 39 <%= modal_close_button(_('Cancel')) %>
app/views/chat/start_session_error.html.erb
1 <p> 1 <p>
2 <%= ui_icon('ui-icon-alert') %> 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 </p> 4 </p>
app/views/cms/_blog.html.erb
@@ -67,7 +67,8 @@ @@ -67,7 +67,8 @@
67 <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ 67 <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [
68 [ _('Full post'), 'full'], 68 [ _('Full post'), 'full'],
69 [ _('First paragraph'), 'short'], 69 [ _('First paragraph'), 'short'],
70 - [ _('First paragraph, with post picture'), 'short+pic'] 70 + [ _('First paragraph, with post picture'), 'short+pic'],
  71 + [ _("Title, Image, Lead"), 'compact']
71 ])) %> 72 ])) %>
72 73
73 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> 74 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %>
app/views/cms/_forum.html.erb
@@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
2 2
3 <h1><%= _('My Forum') %></h1> 3 <h1><%= _('My Forum') %></h1>
4 4
  5 +<%= required_fields_message %>
  6 +
5 <%= render :file => 'shared/tiny_mce' %> 7 <%= render :file => 'shared/tiny_mce' %>
6 8
7 <%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %> 9 <%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %>
app/views/content_viewer/_article_toolbar.html.erb
1 <div<%= user && " class='logged-in'" %>> 1 <div<%= user && " class='logged-in'" %>>
2 <div id="article-actions"> 2 <div id="article-actions">
3 3
  4 + <%= fullscreen_buttons('#article') %>
4 5
5 <% if @page.allow_edit?(user) && !remove_content_button(:edit, @page) %> 6 <% if @page.allow_edit?(user) && !remove_content_button(:edit, @page) %>
6 <% content = content_tag('span', label_for_edit_article(@page)) %> 7 <% content = content_tag('span', label_for_edit_article(@page)) %>
@@ -29,6 +30,10 @@ @@ -29,6 +30,10 @@
29 <% end %> 30 <% end %>
30 31
31 <%= 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) %> 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 <% end %> 37 <% end %>
33 38
34 <% if @page.accept_uploads? && @page.allow_create?(user) %> 39 <% if @page.accept_uploads? && @page.allow_create?(user) %>
@@ -57,7 +62,7 @@ @@ -57,7 +62,7 @@
57 <% if @page.blog? and !@page.image.nil? %> 62 <% if @page.blog? and !@page.image.nil? %>
58 <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div> 63 <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div>
59 <% end %> 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 <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %> 66 <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
62 <%= article_title(@page, :no_link => true) %> 67 <%= article_title(@page, :no_link => true) %>
63 <%= article_translations(@page) %> 68 <%= article_translations(@page) %>
app/views/content_viewer/_display_compact_format.html.erb 0 → 100644
@@ -0,0 +1,21 @@ @@ -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,7 +8,7 @@
8 </div> 8 </div>
9 </div> 9 </div>
10 <hr class="pre-posts"/> 10 <hr class="pre-posts"/>
11 -<div class="blog-posts"> 11 +<div class="blog-posts page-<%= @npage %>">
12 <% paginate = true %> 12 <% paginate = true %>
13 <%= 13 <%=
14 posts = @posts 14 posts = @posts
app/views/content_viewer/folder.html.erb
1 <% unless folder.body.blank? %> 1 <% unless folder.body.blank? %>
2 - <div> 2 + <div class="folder-description">
3 <%= folder.body %> 3 <%= folder.body %>
4 </div> 4 </div>
5 - <hr/>  
6 <% end %> 5 <% end %>
7 6
8 <% if folder.children.empty? %> 7 <% if folder.children.empty? %>
app/views/organizations/_results.html.erb 0 → 100644
@@ -0,0 +1,41 @@ @@ -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 @@ @@ -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 @@ @@ -0,0 +1 @@
  1 +../../views/shared/admin/profiles/index.js.rb
0 \ No newline at end of file 2 \ No newline at end of file
app/views/person_notifier/mailer/_comment.html.erb
@@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
19 <span style="font-size: 12px;"><%= comment.title %></span><br/> 19 <span style="font-size: 12px;"><%= comment.title %></span><br/>
20 <% end %> 20 <% end %>
21 <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/> 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 <br style="clear: both;" /> 23 <br style="clear: both;" />
24 24
25 <% unless comment.replies.blank? %> 25 <% unless comment.replies.blank? %>
app/views/person_notifier/mailer/_create_article.html.erb
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 <p> 6 <p>
7 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
8 <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span> 8 <span style="font-size: 14px;"><%= _("has published on community %s") % 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 </p> 10 </p>
11 <p> 11 <p>
12 <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span> 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,7 +5,7 @@
5 <td> 5 <td>
6 <p> 6 <p>
7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 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 </p> 9 </p>
10 </td> 10 </td>
11 </tr> 11 </tr>
app/views/person_notifier/mailer/_task.html.erb
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <span style="font-size: 14px"> 12 <span style="font-size: 14px">
13 <%= task_information(task) %> 13 <%= task_information(task) %>
14 </span> 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 </div> 16 </div>
17 </td> 17 </td>
18 </tr> 18 </tr>
app/views/person_notifier/mailer/_upload_image.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <td> 5 <td>
6 <p> 6 <p>
7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 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 </p> 9 </p>
10 </td> 10 </td>
11 </tr> 11 </tr>
app/views/profile/_comment.html.erb
@@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
40 <%= txt2html comment.body %> 40 <%= txt2html comment.body %>
41 </div> 41 </div>
42 <div class="profile-activity-time"> 42 <div class="profile-activity-time">
43 - <%= time_ago_as_sentence(comment.created_at) %> 43 + <%= time_ago_in_words(comment.created_at) %>
44 </div> 44 </div>
45 </div> 45 </div>
46 46
app/views/profile/_create_article.html.erb
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
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> 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 </div> 13 </div>
14 <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %> 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 <div class='profile-wall-actions'> 16 <div class='profile-wall-actions'>
17 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> 17 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
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 %> 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,7 +3,7 @@
3 </div> 3 </div>
4 <div class='profile-activity-description'> 4 <div class='profile-activity-description'>
5 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 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 <div class='profile-wall-actions'> 7 <div class='profile-wall-actions'>
8 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> 8 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
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 %> 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,7 +3,7 @@
3 </div> 3 </div>
4 <div class='profile-activity-description'> 4 <div class='profile-activity-description'>
5 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 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 <div class='profile-wall-actions'> 7 <div class='profile-wall-actions'>
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 %> 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 </div> 9 </div>
app/views/profile/_profile_scrap.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <div class='profile-activity-description'> 5 <div class='profile-activity-description'>
6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> 6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p>
7 <p class='profile-activity-text'><%= txt2html scrap.content %></p> 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 <div class='profile-wall-actions'> 9 <div class='profile-wall-actions'>
10 <% if logged_in? && current_person.follows?(scrap.sender) %> 10 <% if logged_in? && current_person.follows?(scrap.sender) %>
11 <span class='profile-activity-send-reply'> 11 <span class='profile-activity-send-reply'>
@@ -22,5 +22,5 @@ @@ -22,5 +22,5 @@
22 <% end %> 22 <% end %>
23 </ul> 23 </ul>
24 <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %> 24 <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %>
25 - <hr /> 25 + <hr />
26 </li> 26 </li>
app/views/profile/_profile_scraps.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <div class='profile-activity-description'> 5 <div class='profile-activity-description'>
6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> 6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p>
7 <p class='profile-activity-text'><%= txt2html scrap.content %></p> 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 <div class='profile-wall-actions'> 9 <div class='profile-wall-actions'>
10 <% if logged_in? && current_person.follows?(scrap.sender) %> 10 <% if logged_in? && current_person.follows?(scrap.sender) %>
11 <span class='profile-activity-send-reply'> 11 <span class='profile-activity-send-reply'>
app/views/profile/_upload_image.html.erb
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 </div> 4 </div>
5 <div class='profile-activity-description'> 5 <div class='profile-activity-description'>
6 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 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 <div class='profile-wall-actions'> 8 <div class='profile-wall-actions'>
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 %> 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 </div> 10 </div>
app/views/profile/content_tagged.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <h1><%= _('Content tagged with "%s"') % escaped_tag %></h1> 5 <h1><%= _('Content tagged with "%s"') % escaped_tag %></h1>
6 6
7 <p> 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 </p> 9 </p>
10 10
11 <% cache_timeout(@tag_cache_key, 4.hour) do %> 11 <% cache_timeout(@tag_cache_key, 4.hour) do %>
app/views/profile_editor/index.html.erb
@@ -73,7 +73,7 @@ @@ -73,7 +73,7 @@
73 <%= control_panel_button(_('Edit welcome page'), 'welcome-page', :action => 'welcome_page') if has_welcome_page %> 73 <%= control_panel_button(_('Edit welcome page'), 'welcome-page', :action => 'welcome_page') if has_welcome_page %>
74 74
75 <% @plugins.dispatch(:control_panel_buttons).each do |button| %> 75 <% @plugins.dispatch(:control_panel_buttons).each do |button| %>
76 - <%= control_panel_button(button[:title], button[:icon], button[:url]) %> 76 + <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %>
77 <% end %> 77 <% end %>
78 78
79 <% end %> 79 <% end %>
app/views/shared/_content_item.html.erb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +<div id="list-item">
  2 + <div class="item-info">
  3 + <div class="item-icon" >
  4 + <%= display_content_icon(content) %>
  5 + </div>
  6 + <span class="item-description">
  7 + <%= link_to(short_filename_upper_ext(content.name), content.url) %>
  8 + </span>
  9 + <span class="item-date"><%= _("Published at: #{show_date(content.updated_at)}") %></span>
  10 + </div>
  11 +</div>
0 \ No newline at end of file 12 \ No newline at end of file
app/views/shared/_lead_and_body.html.erb
@@ -19,17 +19,27 @@ @@ -19,17 +19,27 @@
19 19
20 <div class='article-lead' id="article-lead-<%=lead_id.to_s%>"> 20 <div class='article-lead' id="article-lead-<%=lead_id.to_s%>">
21 21
  22 + <% abstract_options = {:style => 'width: 100%; height: 200px;', :class => editor_type} %>
22 <% if f %> 23 <% if f %>
23 - <%= labelled_form_field(_(abstract_label), f.text_area(abstract_method, :style => 'width: 100%; height: 200px;', :class => editor_type)) %> 24 + <%= labelled_form_field(_(abstract_label), f.text_area(abstract_method, abstract_options)) %>
24 <% else %> 25 <% else %>
25 - <%= labelled_form_field(_(abstract_label), text_area(object, abstract_method, :style => 'width: 100%; height: 200px;', :class => editor_type)) %> 26 + <% if @article.kind_of?(Article) %>
  27 + <%= labelled_form_field(_(abstract_label), text_area_tag("article[abstract]", @escaped_abstract, abstract_options)) %>
  28 + <% else %>
  29 + <%= labelled_form_field(_(abstract_label), text_area(object, abstract_method, abstract_options)) %>
  30 + <% end %>
26 <% end %> 31 <% end %>
27 </div> 32 </div>
28 <div style="margin-top: 10px;"> 33 <div style="margin-top: 10px;">
  34 + <% body_options = {:style => 'width: 100%; height: 400px;', :class => editor_type} %>
29 <% if f %> 35 <% if f %>
30 - <%= labelled_form_field(_(body_label), f.text_area(body_method, :style => 'width: 100%; height: 400px;', :class => editor_type)) %> 36 + <%= labelled_form_field(_(body_label), f.text_area(body_method, body_options)) %>
31 <% else %> 37 <% else %>
32 - <%= labelled_form_field(_(body_label), text_area(object, body_method, :style => 'width: 100%; height: 400px;', :class => editor_type)) %> 38 + <% if @article.kind_of?(Article) %>
  39 + <%= labelled_form_field(_(body_label), text_area_tag("article[body]", @escaped_body, body_options)) %>
  40 + <% else %>
  41 + <%= labelled_form_field(_(body_label), text_area(object, body_method, body_options)) %>
  42 + <% end %>
33 <% end %> 43 <% end %>
34 </div> 44 </div>
35 45
app/views/shared/admin/profiles/index.js.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +jQuery('#manage-profiles .results').replaceWith('<%= escape_javascript(render 'results') %>');
app/views/shared/content_list.html.erb
1 -<table class="<%= list_type %>-content">  
2 - <tr>  
3 - <th><%= _('Title') %></th>  
4 - <th><%= _('Last update') %></th>  
5 - </tr> 1 +<ul class="<%= list_type %>-content">
6 <% contents.each do |content| %> 2 <% contents.each do |content| %>
7 - <% if content.display_to?(user) %>  
8 - <%= display_content_in_listing :content=>content, :list_type=>list_type, :recursive=>recursive %>  
9 - <% end %> 3 + <li class="<%= list_type %>-item">
  4 + <% if content.display_to?(user) %>
  5 + <%= render :partial => 'shared/content_item', :locals => { :content => content } %>
  6 + <% end %>
  7 + </li>
10 <% end %> 8 <% end %>
11 -</table> 9 +</ul>
12 10
13 <p><%= pagination_links contents, :param_name => 'npage', :page_links => true %></p> 11 <p><%= pagination_links contents, :param_name => 'npage', :page_links => true %></p>
app/views/shared/logged_in/xmpp_chat.html.erb
@@ -7,13 +7,13 @@ @@ -7,13 +7,13 @@
7 var $own_name = '<%= user.name %>'; 7 var $own_name = '<%= user.name %>';
8 var $muc_domain = '<%= "conference.#{environment.default_hostname}" %>'; 8 var $muc_domain = '<%= "conference.#{environment.default_hostname}" %>';
9 var $bosh_service = '//<%= environment.default_hostname %>/http-bind'; 9 var $bosh_service = '//<%= environment.default_hostname %>/http-bind';
10 - var $user_unavailable_error = '<%= _("<strong>ooops!</strong> The message could not be sent because the user is not online") %>'; 10 + var $user_unavailable_error = '<%= _("The user is not online now. He/She will receive these messages as soon as he/she gets online.") %>';
11 var $update_presence_status_every = <%= User.expires_chat_status_every.minutes %>; 11 var $update_presence_status_every = <%= User.expires_chat_status_every.minutes %>;
12 var $presence = '<%= current_user.last_chat_status %>'; 12 var $presence = '<%= current_user.last_chat_status %>';
13 </script> 13 </script>
14 14
15 -  
16 <div id="chat-label"> 15 <div id="chat-label">
  16 + <span id="unread-messages"></span>
17 <span class="right-arrow">&#9654;</span> 17 <span class="right-arrow">&#9654;</span>
18 <span class="title"><%= _('Chat') %></span> 18 <span class="title"><%= _('Chat') %></span>
19 </div> 19 </div>
@@ -98,10 +98,5 @@ @@ -98,10 +98,5 @@
98 </div> 98 </div>
99 </div> 99 </div>
100 </div> 100 </div>
101 -  
102 - <div class="error-message">  
103 - <span class='error'>%{text}</span>  
104 - </div>  
105 -  
106 </div> 101 </div>
107 </div> 102 </div>
app/views/shared/profile_actions/xmpp_chat.html.erb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +<% label_name = profile.person? ? _('Open chat') : _('Join chat room') %>
  2 +<% display = profile.person? ? profile.friends.include?(user) : profile.members.include?(user) %>
  3 +
  4 +<% if display %>
  5 + <li>
  6 + <%= button(:chat, label_name , {}, :class => 'open-conversation', 'data-jid' => profile.jid) %>
  7 + </li>
  8 +<% end %>
app/views/tasks/_abuse_complaint_accept_details.html.erb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <% task.abuse_reports.each do |abuse_report| %> 2 <% task.abuse_reports.each do |abuse_report| %>
3 <div> 3 <div>
4 <strong style="word-wrap: break-word; display: block; padding-right: 40px">"<%= abuse_report.reason %>"</strong> <br /> 4 <strong style="word-wrap: break-word; display: block; padding-right: 40px">"<%= abuse_report.reason %>"</strong> <br />
5 - <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_as_sentence(abuse_report.created_at) }%></i> <br /> 5 + <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_in_words(abuse_report.created_at) }%></i> <br />
6 <% if !abuse_report.content.blank? %> 6 <% if !abuse_report.content.blank? %>
7 <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button> 7 <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button>
8 <div style='display: none' id=<%= 'abuse-report-details-'+abuse_report.id.to_s %> class="abuse-report-details"> 8 <div style='display: none' id=<%= 'abuse-report-details-'+abuse_report.id.to_s %> class="abuse-report-details">
app/views/tasks/_task.html.erb
@@ -2,8 +2,26 @@ @@ -2,8 +2,26 @@
2 2
3 <%= render :partial => 'task_icon', :locals => {:task => task} %> 3 <%= render :partial => 'task_icon', :locals => {:task => task} %>
4 4
  5 + <% if !@view_only && profile.organization? && @responsible_candidates.present? %>
  6 + <div class="task_responsible">
  7 + <span class="label"><%= _('Assign to:') %></span>
  8 + <span>
  9 + <% change_responsible_url = url_for :action => :change_responsible, :controller => :tasks %>
  10 + <%= select_tag "tasks[#{task.id}][responsible]", options_from_collection_for_select(@responsible_candidates, :id, :name, task.responsible.present? ? task.responsible.id : nil), :include_blank => true, :onchange => "change_task_responsible(this);", 'data-old-responsible' => task.responsible.present? ? task.responsible.id : nil, 'data-task' => task.id, 'data-url' => change_responsible_url %>
  11 + </span>
  12 + </div>
  13 + <% end %>
  14 +
  15 + <% if @view_only && task.responsible.present? %>
  16 + <div class="task_responsible">
  17 + <span class="label"><%= _('Assigned to:') %></span>
  18 + <span class="value"><%= task.responsible.name %></span>
  19 + </div>
  20 + <% end %>
  21 +
5 <div class="task_decisions"> 22 <div class="task_decisions">
6 - <%= 23 + <% unless @view_only %>
  24 + <%=
7 labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept', 25 labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept',
8 :id => "decision-finish-#{task.id}", 26 :id => "decision-finish-#{task.id}",
9 :class => 'task_accept_radio', 27 :class => 'task_accept_radio',
@@ -19,9 +37,12 @@ @@ -19,9 +37,12 @@
19 :class => 'task_skip_radio', 37 :class => 'task_skip_radio',
20 :disabled => task.skip_disabled?, 38 :disabled => task.skip_disabled?,
21 :task_id => "#{task.id}") 39 :task_id => "#{task.id}")
22 - %> 40 + %>
  41 + <% end %>
23 </div><!-- class="task_decisions" --> 42 </div><!-- class="task_decisions" -->
24 43
  44 + <div class="task_date"><%= show_time(task.created_at) %></div>
  45 +
25 <%= render :partial => 'task_title', :locals => {:task => task} %> 46 <%= render :partial => 'task_title', :locals => {:task => task} %>
26 47
27 <div class="task_information"> 48 <div class="task_information">
app/views/tasks/index.html.erb
@@ -21,45 +21,66 @@ @@ -21,45 +21,66 @@
21 </div> 21 </div>
22 <% end %> 22 <% end %>
23 23
  24 +<%= form_tag '#', :method => 'get' do %>
  25 + <%= field_set_tag _('Filter'), :class => 'filter_fields' do %>
  26 + <p>
  27 + <%= labelled_select(_('Type of task')+': ', :filter_type, :first, :last, @filter_type, type_collection, {:id => 'filter-type'}) %>
  28 + </p>
  29 + <p>
  30 + <%= labelled_text_field(_("Text filter")+': ', :filter_text, nil, {:id => 'filter-text',:value => @filter_text}) %>
  31 + </p>
  32 + <% if profile.organization? %>
  33 + <p>
  34 + <%= labelled_select(_('Assigned to')+': ', :filter_responsible, :id, :name, @filter_responsible, [OpenStruct.new(:name => _('All'), :id => nil), OpenStruct.new(:name => _('Unassigned'), :id => -1)] + @responsible_candidates, :class => 'filter_responsible') %>
  35 + </p>
  36 + <% end %>
  37 + <p>
  38 + <%= submit_button(:search, _('Search')) %>
  39 + </p>
  40 + <% end %>
  41 +<% end %>
  42 +
24 <% if @tasks.empty? %> 43 <% if @tasks.empty? %>
25 <p> 44 <p>
26 - <%= labelled_select(_('Filter')+': ', :filter_type, :first, :last, @filter, type_collection, :onchange => "document.location.href = '?filter_type='+this.value")%> 45 + <em><%= _('No pending tasks for %s') % profile.name %></em>
27 </p> 46 </p>
28 - <em><%= _('No pending tasks for %s') % profile.name %></em>  
29 <% else %> 47 <% else %>
30 <%= form_tag :action => 'close' do%> 48 <%= form_tag :action => 'close' do%>
31 - <% button_bar do %> 49 + <% button_bar(:class => 'task-actions') do %>
32 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> 50 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %>
33 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> 51 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %>
34 <%= submit_button :save, _("Apply!") %> 52 <%= submit_button :save, _("Apply!") %>
35 <%= button(:edit, _('View processed tasks'), :action => 'processed') %> 53 <%= button(:edit, _('View processed tasks'), :action => 'processed') %>
36 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> 54 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
37 - <% end %> 55 + <% end unless @view_only %>
38 56
39 <ul class='task-list'> 57 <ul class='task-list'>
40 - <p>  
41 - <%= labelled_select(_('Filter')+': ', :filter_type, :first, :last, @filter, type_collection, :onchange => "document.location.href = '?filter_type='+this.value") %>  
42 - </p>  
43 - <p>  
44 - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %>  
45 - </p>  
46 - <% @tasks.each do |task| %>  
47 - <%= render :partial => 'task', :locals => { :task => task } %> 58 + <% unless @view_only %>
  59 + <p>
  60 + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %>
  61 + </p>
  62 + <% end %>
  63 +
  64 + <div class="task_boxes">
  65 + <%= render :partial => 'task', :collection => @tasks %>
  66 + </div>
  67 +
  68 + <% unless @view_only %>
  69 + <p>
  70 + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %>
  71 + </p>
48 <% end %> 72 <% end %>
49 - <p>  
50 - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %>  
51 - </p>  
52 </ul> 73 </ul>
53 74
54 <%= pagination_links(@tasks)%> 75 <%= pagination_links(@tasks)%>
55 76
56 - <% button_bar do %> 77 + <% button_bar(:class => 'task-actions') do %>
57 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> 78 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %>
58 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> 79 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %>
59 <%= submit_button :save, _("Apply!") %> 80 <%= submit_button :save, _("Apply!") %>
60 <%= button(:edit, _('View processed tasks'), :action => 'processed') %> 81 <%= button(:edit, _('View processed tasks'), :action => 'processed') %>
61 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> 82 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
62 - <% end %> 83 + <% end unless @view_only %>
63 <% end %> 84 <% end %>
64 <% end %> 85 <% end %>
65 </p> 86 </p>
app/views/users/_users_list.html.erb
1 -<div class="environment-users-results-header">  
2 - <div id='environment-users-filter-title'><%= users_filter_title(@filter) %></div> 1 +<div class="environment-profiles-results-header">
  2 + <div id='environment-profiles-filter-title'><%= users_filter_title(@filter) %></div>
3 <%= filter_selector(@filter) %> 3 <%= filter_selector(@filter) %>
4 <div style="clear: both"></div> 4 <div style="clear: both"></div>
5 </div> 5 </div>
config/initializers/delayed_job_config.rb
@@ -23,3 +23,13 @@ end @@ -23,3 +23,13 @@ end
23 # end 23 # end
24 # alias_method_chain :handle_failed_job, :loggin 24 # alias_method_chain :handle_failed_job, :loggin
25 #end 25 #end
  26 +
  27 +# Chain delayed job's handle_failed_job method to do exception notification
  28 +Delayed::Worker.class_eval do
  29 + def handle_failed_job_with_notification job, error
  30 + handle_failed_job_without_notification job, error
  31 + ExceptionNotifier.notify_exception error, exception_recipients: NOOSFERO_CONF['exception_recipients'],
  32 + data: {job: job, handler: job.handler} rescue nil
  33 + end
  34 + alias_method_chain :handle_failed_job, :notification
  35 +end
config/initializers/noosfero_extensions.rb
1 require 'noosfero/role_assignment_ext' 1 require 'noosfero/role_assignment_ext'
2 require 'noosfero/action_tracker_ext' 2 require 'noosfero/action_tracker_ext'
  3 +require 'noosfero/vote_ext'
config/initializers/wrap_parameters.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +# Be sure to restart your server when you modify this file.
  2 +# This file contains settings for ActionController::ParamsWrapper which
  3 +# is enabled by default.
  4 +
  5 +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
  6 +ActiveSupport.on_load(:action_controller) do
  7 + wrap_parameters :format => []
  8 +end
  9 +
  10 +# Disable root element in JSON by default.
  11 +ActiveSupport.on_load(:active_record) do
  12 + self.include_root_in_json = false
  13 +end
db/migrate/20140820173129_create_chat_messages.rb
1 class CreateChatMessages < ActiveRecord::Migration 1 class CreateChatMessages < ActiveRecord::Migration
2 - def change 2 + def up
3 create_table :chat_messages do |t| 3 create_table :chat_messages do |t|
4 t.integer :to_id 4 t.integer :to_id
5 t.integer :from_id 5 t.integer :from_id
@@ -8,4 +8,8 @@ class CreateChatMessages &lt; ActiveRecord::Migration @@ -8,4 +8,8 @@ class CreateChatMessages &lt; ActiveRecord::Migration
8 t.timestamps 8 t.timestamps
9 end 9 end
10 end 10 end
  11 +
  12 + def down
  13 + drop_table :chat_messages
  14 + end
11 end 15 end
db/migrate/20141014205254_change_chat_messages_columns_and_add_indexes.rb 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +class ChangeChatMessagesColumnsAndAddIndexes < ActiveRecord::Migration
  2 + def up
  3 + change_table :chat_messages do |t|
  4 + t.change :from_id, :integer, :null => false
  5 + t.change :to_id, :integer, :null => false
  6 + t.change :body, :text
  7 + end
  8 + add_index :chat_messages, :from_id
  9 + add_index :chat_messages, :to_id
  10 + add_index :chat_messages, :created_at
  11 + end
  12 +
  13 + def down
  14 + remove_index :chat_messages, :from_id
  15 + remove_index :chat_messages, :to_id
  16 + remove_index :chat_messages, :created_at
  17 + change_table :chat_messages do |t|
  18 + t.change :from_id, :integer, :null => true
  19 + t.change :to_id, :integer, :null => true
  20 + t.change :body, :string
  21 + end
  22 + end
  23 +end
db/migrate/20150423203352_fix_tags_case_differences.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +class FixTagsCaseDifferences < ActiveRecord::Migration
  2 + def up
  3 + tags = ActsAsTaggableOn::Tag.joins('LEFT JOIN tags as b on LOWER(tags.name) = b.name').where('b.id is null')
  4 + tags.find_each do |tag|
  5 + unless ActsAsTaggableOn::Tag.exists?(:name => tag.name.mb_chars.downcase)
  6 + ActsAsTaggableOn::Tag.create(:name => tag.name.mb_chars.downcase)
  7 + end
  8 + end
  9 +
  10 + execute("UPDATE taggings SET tag_id = new.id FROM taggings AS t INNER JOIN tags AS old ON t.tag_id = old.id INNER JOIN tags AS new ON LOWER(old.name) = new.name WHERE old.id != new.id AND taggings.id = t.id")
  11 +
  12 + execute("UPDATE tags SET taggings_count = (SELECT COUNT(*) FROM taggings WHERE taggings.tag_id = tags.id)")
  13 + execute("DELETE FROM tags WHERE taggings_count = 0")
  14 + end
  15 +
  16 + def down
  17 + say 'This migration is irreversible.'
  18 + end
  19 +end
db/migrate/20150429145001_add_mirror_to_block.rb 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +class AddMirrorToBlock < ActiveRecord::Migration
  2 + def up
  3 + change_table :blocks do |t|
  4 + t.boolean :mirror, :default => false
  5 + t.references :mirror_block
  6 + t.references :observers
  7 + end
  8 + end
  9 +
  10 + def down
  11 + remove_column :blocks, :mirror
  12 + remove_column :blocks, :mirror_block_id
  13 + remove_column :blocks, :observers_id
  14 + end
  15 +end
db/migrate/20150507204849_remove_broken_profile_suggestions.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class RemoveBrokenProfileSuggestions < ActiveRecord::Migration
  2 + def up
  3 + execute("DELETE FROM profile_suggestions WHERE suggestion_id NOT IN (SELECT id from profiles)")
  4 + end
  5 +
  6 + def down
  7 + say "this migration can't be reverted"
  8 + end
  9 +end
db/migrate/20150513213939_update_topic_creation_configuration.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class UpdateTopicCreationConfiguration < ActiveRecord::Migration
  2 + def up
  3 + Forum.where("setting LIKE '%:allows_members_to_create_topics: true%'").find_each do |forum|
  4 + forum.setting.delete(:allows_members_to_create_topics)
  5 + forum.setting.merge!(:topic_creation => 'related')
  6 + forum.save
  7 + end
  8 + end
  9 +
  10 + def down
  11 + say "this migration can't be reverted"
  12 + end
  13 +end
db/migrate/20150525101430_add_responsible_to_task.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +class AddResponsibleToTask < ActiveRecord::Migration
  2 +
  3 + def change
  4 + add_column :tasks, :responsible_id, :integer
  5 + end
  6 +
  7 +end
db/migrate/20150529180110_add_date_format_to_environment.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddDateFormatToEnvironment < ActiveRecord::Migration
  2 + def up
  3 + add_column :environments, :date_format, :string, :default => 'month_name_with_year'
  4 + end
  5 +
  6 + def down
  7 + remove_column :environments, :date_format
  8 + end
  9 +end
db/migrate/20150602142030_add_closed_by_to_task.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +class AddClosedByToTask < ActiveRecord::Migration
  2 +
  3 + def change
  4 + add_column :tasks, :closed_by_id, :integer
  5 + end
  6 +
  7 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20150408231524) do 14 +ActiveRecord::Schema.define(:version => 20150602142030) do
15 15
16 create_table "abuse_reports", :force => true do |t| 16 create_table "abuse_reports", :force => true do |t|
17 t.integer "reporter_id" 17 t.integer "reporter_id"
@@ -183,10 +183,13 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do @@ -183,10 +183,13 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do
183 t.string "type" 183 t.string "type"
184 t.text "settings" 184 t.text "settings"
185 t.integer "position" 185 t.integer "position"
186 - t.boolean "enabled", :default => true 186 + t.boolean "enabled", :default => true
187 t.datetime "created_at" 187 t.datetime "created_at"
188 t.datetime "updated_at" 188 t.datetime "updated_at"
189 t.datetime "fetched_at" 189 t.datetime "fetched_at"
  190 + t.boolean "mirror", :default => false
  191 + t.integer "mirror_block_id"
  192 + t.integer "observers_id"
190 end 193 end
191 194
192 add_index "blocks", ["box_id"], :name => "index_blocks_on_box_id" 195 add_index "blocks", ["box_id"], :name => "index_blocks_on_box_id"
@@ -242,13 +245,17 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do @@ -242,13 +245,17 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do
242 end 245 end
243 246
244 create_table "chat_messages", :force => true do |t| 247 create_table "chat_messages", :force => true do |t|
245 - t.integer "to_id"  
246 - t.integer "from_id"  
247 - t.string "body" 248 + t.integer "from_id", :null => false
  249 + t.integer "to_id", :null => false
  250 + t.text "body"
248 t.datetime "created_at", :null => false 251 t.datetime "created_at", :null => false
249 t.datetime "updated_at", :null => false 252 t.datetime "updated_at", :null => false
250 end 253 end
251 254
  255 + add_index "chat_messages", ["created_at"], :name => "index_chat_messages_on_created_at"
  256 + add_index "chat_messages", ["from_id"], :name => "index_chat_messages_on_from_id"
  257 + add_index "chat_messages", ["to_id"], :name => "index_chat_messages_on_to_id"
  258 +
252 create_table "comments", :force => true do |t| 259 create_table "comments", :force => true do |t|
253 t.string "title" 260 t.string "title"
254 t.text "body" 261 t.text "body"
@@ -313,17 +320,18 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do @@ -313,17 +320,18 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do
313 t.text "design_data" 320 t.text "design_data"
314 t.text "custom_header" 321 t.text "custom_header"
315 t.text "custom_footer" 322 t.text "custom_footer"
316 - t.string "theme", :default => "default", :null => false 323 + t.string "theme", :default => "default", :null => false
317 t.text "terms_of_use_acceptance_text" 324 t.text "terms_of_use_acceptance_text"
318 t.datetime "created_at" 325 t.datetime "created_at"
319 t.datetime "updated_at" 326 t.datetime "updated_at"
320 - t.integer "reports_lower_bound", :default => 0, :null => false 327 + t.integer "reports_lower_bound", :default => 0, :null => false
321 t.string "redirection_after_login", :default => "keep_on_same_page" 328 t.string "redirection_after_login", :default => "keep_on_same_page"
322 t.text "signup_welcome_text" 329 t.text "signup_welcome_text"
323 t.string "languages" 330 t.string "languages"
324 t.string "default_language" 331 t.string "default_language"
325 t.string "noreply_email" 332 t.string "noreply_email"
326 t.string "redirection_after_signup", :default => "keep_on_same_page" 333 t.string "redirection_after_signup", :default => "keep_on_same_page"
  334 + t.string "date_format", :default => "month_name_with_year"
327 end 335 end
328 336
329 create_table "external_feeds", :force => true do |t| 337 create_table "external_feeds", :force => true do |t|
@@ -677,12 +685,14 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do @@ -677,12 +685,14 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do
677 t.date "end_date" 685 t.date "end_date"
678 t.integer "requestor_id" 686 t.integer "requestor_id"
679 t.integer "target_id" 687 t.integer "target_id"
680 - t.string "code", :limit => 40 688 + t.string "code", :limit => 40
681 t.string "type" 689 t.string "type"
682 t.datetime "created_at" 690 t.datetime "created_at"
683 t.string "target_type" 691 t.string "target_type"
684 t.integer "image_id" 692 t.integer "image_id"
685 - t.boolean "spam", :default => false 693 + t.boolean "spam", :default => false
  694 + t.integer "responsible_id"
  695 + t.integer "closed_by_id"
686 end 696 end
687 697
688 add_index "tasks", ["requestor_id"], :name => "index_tasks_on_requestor_id" 698 add_index "tasks", ["requestor_id"], :name => "index_tasks_on_requestor_id"
debian/apache2/conf.d/noosfero-chat 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<IfModule mpm_worker_module>
  2 + StartServers 8
  3 + MinSpareThreads 25
  4 + MaxSpareThreads 75
  5 + ThreadLimit 128
  6 + ThreadsPerChild 128
  7 + MaxClients 2048
  8 + MaxRequestsPerChild 0
  9 +</IfModule>
debian/changelog
1 -noosfero (1.2~0) UNRELEASED; urgency=medium 1 +noosfero (1.2~1) UNRELEASED; urgency=medium
2 2
  3 + [ Antonio Terceiro ]
3 * Temporary version in heavy development 4 * Temporary version in heavy development
4 5
5 - -- Antonio Terceiro <terceiro@debian.org> Fri, 08 May 2015 16:08:18 -0300 6 + [ Joenio Costa ]
  7 + * Build noosfero-chat package
  8 +
  9 + -- Joenio Costa <joenio@colivre.coop.br> Mon, 18 May 2015 14:32:21 -0300
6 10
7 noosfero (1.1) wheezy; urgency=low 11 noosfero (1.1) wheezy; urgency=low
8 12
debian/control
@@ -85,3 +85,14 @@ Description: free web-based platform for social networks (apache frontend) @@ -85,3 +85,14 @@ Description: free web-based platform for social networks (apache frontend)
85 . 85 .
86 This package contains the configuration files needed to run Noosfero with the 86 This package contains the configuration files needed to run Noosfero with the
87 Apache HTTPD server as frontend. 87 Apache HTTPD server as frontend.
  88 +
  89 +Package: noosfero-chat
  90 +Architecture: all
  91 +Depends: noosfero (>= 1.2), ejabberd, odbc-postgresql, pidgin-data
  92 +Description: free web-based platform for social networks (ejabberd based chat)
  93 + Noosfero is a web platform for social and solidarity economy networks with
  94 + blog, e-Porfolios, CMS, RSS, thematic discussion, events agenda and collective
  95 + inteligence for solidarity economy in the same system.
  96 + .
  97 + This package contains the configuration files needed to run Noosfero with the
  98 + Ejabberd XMPP chat server.