Commit 4d9daa44dbf61490640b32a8fb9f6f49f0f8b152

Authored by Rodrigo Souto
2 parents 1fe6b276 4b00dad4
Exists in staging and in 1 other branch production

Merge branch 'master' into staging

Showing 136 changed files with 1279 additions and 399 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 136 files displayed.

@@ -37,7 +37,7 @@ before_install: @@ -37,7 +37,7 @@ before_install:
37 cache: bundler 37 cache: bundler
38 38
39 before_script: 39 before_script:
40 - - mkdir -p tmp/{pids,cache} log 40 + - mkdir -p tmp/{pids,cache} log cache
41 - script/noosfero-plugins disableall 41 - script/noosfero-plugins disableall
42 #- bundle exec rake makemo &>/dev/null 42 #- bundle exec rake makemo &>/dev/null
43 # database 43 # database
@@ -3,37 +3,30 @@ Noosfero release tasks @@ -3,37 +3,30 @@ Noosfero release tasks
3 3
4 This file documents release-related activities. 4 This file documents release-related activities.
5 5
6 -Working with translations  
7 --------------------------  
8 -  
9 -* Update translation files: `rake updatepo`. Then `git commit` them.  
10 -* Send the PO files to the translators.  
11 -* Get the PO files back from translators, put in `po/` under the correct language name (e.,g. `po/pt_BR/`) and `git commit`.  
12 -* test translations: `rake makemo` and browse the application on the web.  
13 -  
14 Releasing noosfero 6 Releasing noosfero
15 ------------------ 7 ------------------
16 8
17 -Considering you are on a Debian GNU/Linux or Debian-based system 9 +Considering you are on a Debian GNU/Linux or Debian-based system, the following
  10 +packages are required during the release process:
18 11
19 - # apt-get install devscripts debhelper 12 +```
  13 +# apt install git devscripts debhelper
  14 +```
20 15
21 To prepare a release of noosfero, you must follow the steps below: 16 To prepare a release of noosfero, you must follow the steps below:
22 17
23 -* Finish all requirements and bugs assigned to the to-be-released version 18 +* Disable the automatic pushing of translation updates in weblate.
24 * Make sure all tests pass 19 * Make sure all tests pass
25 -* Write release notes at the version's wiki topic  
26 * Generate packages with `rake noosfero:release[(stable|test)]`. This task will: 20 * Generate packages with `rake noosfero:release[(stable|test)]`. This task will:
27 * Update the version in lib/noosfero.rb and debian/changelog. 21 * Update the version in lib/noosfero.rb and debian/changelog.
28 * Create the tarbal and the deb pkg under pkg/ directory. 22 * Create the tarbal and the deb pkg under pkg/ directory.
29 * Create a git tag and push it. 23 * Create a git tag and push it.
30 - * Upload the pkg to the configured repository (if configured) on ~/.dput.cf. 24 + * Upload the packages to the configured repository (if configured) on ~/.dput.cf.
31 * Test that the tarball and deb package are ok 25 * Test that the tarball and deb package are ok
32 -* Go to the version's wiki topic and edit it to reflect the new reality  
33 -* Edit the topic WebPreferences and update DEBIAN_REPOSITORY_TOPICS setting  
34 -* Attach the generated packages to that topic. Before attaching calculate the sha1 of the package (with sha1sum and paste the SHA1 hash as comment in the attachment form)  
35 -* Download the attached and verify the MD5 hash  
36 * Update an eventual demonstration version that you run. 26 * Update an eventual demonstration version that you run.
37 -* Write an announcement e-mail to the relevant mailing lists pointing to the release notes, and maybe to the demonstration version. 27 +* Write an announcement e-mail to the relevant mailing lists pointing to the
  28 + release notes, and maybe to the demonstration version.
  29 +* Re-enable the automatic pushing of trasnlatio updates in weblate.
38 30
39 -If you had any problem during these steps, you can do `rake clobber_package` to completely delete the generated packages and start the process again. 31 +If you had any problem during these steps, you can do `rake clobber_package` to
  32 +completely delete the generated packages and start the process again.
app/controllers/box_organizer_controller.rb
@@ -83,12 +83,9 @@ class BoxOrganizerController < ApplicationController @@ -83,12 +83,9 @@ class BoxOrganizerController < ApplicationController
83 83
84 def save 84 def save
85 @block = boxes_holder.blocks.find(params[:id]) 85 @block = boxes_holder.blocks.find(params[:id])
86 - if @block.kind_of?(RawHTMLBlock) && !user.is_admin?(environment)  
87 - render_access_denied  
88 - else  
89 - @block.update(params[:block])  
90 - redirect_to :action => 'index'  
91 - end 86 + return render_access_denied unless @block.editable?(user)
  87 + @block.update(params[:block])
  88 + redirect_to :action => 'index'
92 end 89 end
93 90
94 def boxes_editor? 91 def boxes_editor?
app/controllers/my_profile/cms_controller.rb
@@ -32,7 +32,8 @@ class CmsController < MyProfileController @@ -32,7 +32,8 @@ class CmsController < MyProfileController
32 end 32 end
33 33
34 protect_if :only => [:new, :upload_files] do |c, user, profile| 34 protect_if :only => [:new, :upload_files] do |c, user, profile|
35 - parent = profile.articles.find_by_id(c.params[:parent_id]) 35 + parent_id = c.params[:article].present? ? c.params[:article][:parent_id] : c.params[:parent_id]
  36 + parent = profile.articles.find_by_id(parent_id)
36 user && user.can_post_content?(profile, parent) 37 user && user.can_post_content?(profile, parent)
37 end 38 end
38 39
app/controllers/my_profile/profile_members_controller.rb
@@ -2,8 +2,27 @@ class ProfileMembersController < MyProfileController @@ -2,8 +2,27 @@ class ProfileMembersController < MyProfileController
2 protect 'manage_memberships', :profile 2 protect 'manage_memberships', :profile
3 3
4 def index 4 def index
5 - @members = profile.members_by_name  
6 - @member_role = environment.roles.find_by_name('member') 5 + @filters = params[:filters] || {:roles => []}
  6 + all_roles = Profile::Roles.organization_member_roles(environment.id) | Profile::Roles.organization_custom_roles(environment.id, profile.id)
  7 + @filters[:roles] = all_roles unless @filters[:roles].present?
  8 + @data = {}
  9 + field = 'name'
  10 + field = 'email' if @filters[:name] =~ /\@/
  11 +
  12 + @data[:members] = profile.members_by(field,@filters[:name]).by_role(@filters[:roles])
  13 + session[:members_filtered] = @data[:members].map{|m|m.id} if request.post?
  14 + @data[:roles] = all_roles
  15 +
  16 + end
  17 +
  18 + def send_mail
  19 + session[:members_filtered] = params[:members_filtered].select{|value| value!="0"}
  20 + if session[:members_filtered].present?
  21 + redirect_to :controller => :profile, :action => :send_mail
  22 + else
  23 + session[:notice] = _("Select at least one member.")
  24 + redirect_to :action => :index
  25 + end
7 end 26 end
8 27
9 def update_roles 28 def update_roles
@@ -156,4 +175,13 @@ class ProfileMembersController < MyProfileController @@ -156,4 +175,13 @@ class ProfileMembersController < MyProfileController
156 end 175 end
157 end 176 end
158 177
  178 + def search_members
  179 + field = 'name'
  180 + field = 'email' if params[:filter_name] =~ /\@/
  181 +
  182 + result = profile.members_like field, params[:filter_name]
  183 + result = result.select{|member| member.can_view_field?(current_person, "email") } if field=="email"
  184 + render :json => result.map { |member| {:label => "#{member.name}#{member.can_view_field?(current_person, "email") ? " <#{member.email}>" : ""}", :value => member.name }}
  185 + end
  186 +
159 end 187 end
app/controllers/public/account_controller.rb
@@ -198,7 +198,7 @@ class AccountController &lt; ApplicationController @@ -198,7 +198,7 @@ class AccountController &lt; ApplicationController
198 if request.post? 198 if request.post?
199 begin 199 begin
200 unless verify_recaptcha 200 unless verify_recaptcha
201 - @change_password.errors.add(:base, _('Please type the words correctly')) 201 + @change_password.errors.add(:base, _('Please type the captcha text correctly'))
202 return false 202 return false
203 end 203 end
204 204
app/controllers/public/content_viewer_controller.rb
@@ -68,11 +68,7 @@ class ContentViewerController &lt; ApplicationController @@ -68,11 +68,7 @@ class ContentViewerController &lt; ApplicationController
68 process_comments(params) 68 process_comments(params)
69 69
70 if request.xhr? and params[:comment_order] 70 if request.xhr? and params[:comment_order]
71 - if @comment_order == 'newest'  
72 - @comments = @comments.reverse  
73 - end  
74 -  
75 - return render :partial => 'comment/comment', :collection => @comments 71 + return render :partial => 'comment/comments_with_pagination'
76 end 72 end
77 73
78 if params[:slideshow] 74 if params[:slideshow]
@@ -209,8 +205,6 @@ class ContentViewerController &lt; ApplicationController @@ -209,8 +205,6 @@ class ContentViewerController &lt; ApplicationController
209 205
210 def rendered_file_download(view = nil) 206 def rendered_file_download(view = nil)
211 if @page.download? view 207 if @page.download? view
212 - headers['Content-Type'] = @page.mime_type  
213 - headers.merge! @page.download_headers  
214 data = @page.data 208 data = @page.data
215 209
216 # TODO test the condition 210 # TODO test the condition
@@ -218,7 +212,12 @@ class ContentViewerController &lt; ApplicationController @@ -218,7 +212,12 @@ class ContentViewerController &lt; ApplicationController
218 raise "No data for file" 212 raise "No data for file"
219 end 213 end
220 214
221 - render :text => data, :layout => false 215 + if @page.published && @page.uploaded_file?
  216 + redirect_to @page.public_filename
  217 + else
  218 + send_data data, @page.download_headers
  219 + end
  220 +
222 return true 221 return true
223 end 222 end
224 223
@@ -244,8 +243,12 @@ class ContentViewerController &lt; ApplicationController @@ -244,8 +243,12 @@ class ContentViewerController &lt; ApplicationController
244 243
245 def get_posts(year = nil, month = nil) 244 def get_posts(year = nil, month = nil)
246 if year && month 245 if year && month
247 - filter_date = DateTime.parse("#{year}-#{month}-01")  
248 - return @page.posts.by_range(filter_date..filter_date.at_end_of_month) 246 + begin
  247 + filter_date = DateTime.parse("#{year}-#{month}-01")
  248 + return @page.posts.by_range(filter_date..filter_date.at_end_of_month)
  249 + rescue ArgumentError
  250 + return @page.posts
  251 + end
249 else 252 else
250 return @page.posts 253 return @page.posts
251 end 254 end
@@ -276,8 +279,12 @@ class ContentViewerController &lt; ApplicationController @@ -276,8 +279,12 @@ class ContentViewerController &lt; ApplicationController
276 @comments = @page.comments.without_spam 279 @comments = @page.comments.without_spam
277 @comments = @plugins.filter(:unavailable_comments, @comments) 280 @comments = @plugins.filter(:unavailable_comments, @comments)
278 @comments_count = @comments.count 281 @comments_count = @comments.count
279 - @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] )  
280 @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order] 282 @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order]
  283 + @comments = @comments.without_reply
  284 + if @comment_order == 'newest'
  285 + @comments = @comments.reverse
  286 + end
  287 + @comments = @comments.paginate(:per_page => per_page, :page => params[:comment_page] )
281 end 288 end
282 289
283 private 290 private
app/controllers/public/profile_controller.rb
@@ -155,6 +155,18 @@ class ProfileController &lt; PublicController @@ -155,6 +155,18 @@ class ProfileController &lt; PublicController
155 end 155 end
156 end 156 end
157 157
  158 + def follow_article
  159 + article = profile.environment.articles.find params[:article_id]
  160 + article.person_followers << user
  161 + redirect_to article.url
  162 + end
  163 +
  164 + def unfollow_article
  165 + article = profile.environment.articles.find params[:article_id]
  166 + article.person_followers.delete(user)
  167 + redirect_to article.url
  168 + end
  169 +
158 def unblock 170 def unblock
159 if current_user.person.is_admin?(profile.environment) 171 if current_user.person.is_admin?(profile.environment)
160 profile.unblock 172 profile.unblock
@@ -362,6 +374,7 @@ class ProfileController &lt; PublicController @@ -362,6 +374,7 @@ class ProfileController &lt; PublicController
362 def send_mail 374 def send_mail
363 @mailing = profile.mailings.build(params[:mailing]) 375 @mailing = profile.mailings.build(params[:mailing])
364 @email_templates = profile.email_templates.find_all_by_template_type(:organization_members) 376 @email_templates = profile.email_templates.find_all_by_template_type(:organization_members)
  377 + @mailing.data = session[:members_filtered] ? {:members_filtered => session[:members_filtered]} : {}
365 if request.post? 378 if request.post?
366 @mailing.locale = locale 379 @mailing.locale = locale
367 @mailing.person = user 380 @mailing.person = user
app/helpers/application_helper.rb
@@ -150,14 +150,8 @@ module ApplicationHelper @@ -150,14 +150,8 @@ module ApplicationHelper
150 link_to text, profile_path(:profile => profile) , options 150 link_to text, profile_path(:profile => profile) , options
151 end 151 end
152 152
153 - def link_to_homepage(text, profile = nil, options = {})  
154 - p = if profile  
155 - Profile[profile]  
156 - else  
157 - user  
158 - end  
159 -  
160 - link_to text, p.url, options 153 + def link_to_homepage(text, profile, options = {})
  154 + link_to text, profile.url, options
161 end 155 end
162 156
163 def link_if_permitted(link, permission = nil, target = nil) 157 def link_if_permitted(link, permission = nil, target = nil)
@@ -556,14 +550,25 @@ module ApplicationHelper @@ -556,14 +550,25 @@ module ApplicationHelper
556 trigger_class = 'enterprise-trigger' 550 trigger_class = 'enterprise-trigger'
557 end 551 end
558 end 552 end
559 - extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) 553 +
  554 + extra_info_tag = ''
  555 + img_class = 'profile-image'
  556 +
  557 + if extra_info.is_a? Hash
  558 + extra_info_tag = content_tag( 'span', extra_info[:value], :class => 'extra_info '+extra_info[:class])
  559 + img_class +=' '+extra_info[:class]
  560 + else
  561 + extra_info_tag = content_tag( 'span', extra_info, :class => 'extra_info' )
  562 + end
  563 +
560 links = links_for_balloon(profile) 564 links = links_for_balloon(profile)
561 content_tag('div', content_tag(tag, 565 content_tag('div', content_tag(tag,
562 - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") + 566 + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ?
  567 + popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") +
563 link_to( 568 link_to(
564 - content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + 569 + content_tag( 'span', profile_image( profile, size ), :class => img_class ) +
565 content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + 570 content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +
566 - extra_info + profile_sex_icon( profile ), 571 + extra_info_tag + profile_sex_icon( profile ),
567 profile.url, 572 profile.url,
568 :class => 'profile_link url', 573 :class => 'profile_link url',
569 :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, 574 :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name,
@@ -711,7 +716,7 @@ module ApplicationHelper @@ -711,7 +716,7 @@ module ApplicationHelper
711 class NoosferoFormBuilder < ActionView::Helpers::FormBuilder 716 class NoosferoFormBuilder < ActionView::Helpers::FormBuilder
712 extend ActionView::Helpers::TagHelper 717 extend ActionView::Helpers::TagHelper
713 718
714 - def self.output_field(text, field_html, field_id = nil, options = {}) 719 + def self.output_field(text, field_html, field_id = nil)
715 # try to guess an id if none given 720 # try to guess an id if none given
716 if field_id.nil? 721 if field_id.nil?
717 field_html =~ /id=['"]([^'"]*)['"]/ 722 field_html =~ /id=['"]([^'"]*)['"]/
@@ -1040,10 +1045,11 @@ module ApplicationHelper @@ -1040,10 +1045,11 @@ module ApplicationHelper
1040 end 1045 end
1041 1046
1042 def search_contents_menu 1047 def search_contents_menu
  1048 + host = environment.default_hostname
1043 links = [ 1049 links = [
1044 - {s_('contents|More recent') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_recent'})}},  
1045 - {s_('contents|More viewed') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_popular'})}},  
1046 - {s_('contents|Most commented') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_comments'})}} 1050 + {s_('contents|More recent') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_recent'})}},
  1051 + {s_('contents|More viewed') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_popular'})}},
  1052 + {s_('contents|Most commented') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_comments'})}}
1047 ] 1053 ]
1048 if logged_in? 1054 if logged_in?
1049 links.push(_('New content') => modal_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})})) 1055 links.push(_('New content') => modal_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})}))
@@ -1055,10 +1061,11 @@ module ApplicationHelper @@ -1055,10 +1061,11 @@ module ApplicationHelper
1055 alias :browse_contents_menu :search_contents_menu 1061 alias :browse_contents_menu :search_contents_menu
1056 1062
1057 def search_people_menu 1063 def search_people_menu
  1064 + host = environment.default_hostname
1058 links = [ 1065 links = [
1059 - {s_('people|More recent') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_recent'})}},  
1060 - {s_('people|More active') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_active'})}},  
1061 - {s_('people|More popular') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_popular'})}} 1066 + {s_('people|More recent') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_recent'})}},
  1067 + {s_('people|More active') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_active'})}},
  1068 + {s_('people|More popular') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_popular'})}}
1062 ] 1069 ]
1063 if logged_in? 1070 if logged_in?
1064 links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})}) 1071 links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})})
@@ -1071,10 +1078,11 @@ module ApplicationHelper @@ -1071,10 +1078,11 @@ module ApplicationHelper
1071 alias :browse_people_menu :search_people_menu 1078 alias :browse_people_menu :search_people_menu
1072 1079
1073 def search_communities_menu 1080 def search_communities_menu
  1081 + host = environment.default_hostname
1074 links = [ 1082 links = [
1075 - {s_('communities|More recent') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_recent'})}},  
1076 - {s_('communities|More active') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_active'})}},  
1077 - {s_('communities|More popular') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_popular'})}} 1083 + {s_('communities|More recent') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_recent'})}},
  1084 + {s_('communities|More active') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_active'})}},
  1085 + {s_('communities|More popular') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_popular'})}}
1078 ] 1086 ]
1079 if logged_in? 1087 if logged_in?
1080 links.push(_('My communities') => {:href => url_for({:profile => current_user.login, :controller => 'memberships'})}) 1088 links.push(_('My communities') => {:href => url_for({:profile => current_user.login, :controller => 'memberships'})})
app/helpers/article_helper.rb
@@ -169,4 +169,30 @@ module ArticleHelper @@ -169,4 +169,30 @@ module ArticleHelper
169 _('Edit') 169 _('Edit')
170 end 170 end
171 171
  172 + def follow_button_text(article)
  173 + if article.event?
  174 + _('Attend')
  175 + else
  176 + _('Follow')
  177 + end
  178 + end
  179 +
  180 + def unfollow_button_text(article)
  181 + if article.event?
  182 + _('Unattend')
  183 + else
  184 + _('Unfollow')
  185 + end
  186 + end
  187 +
  188 + def following_button(page, user)
  189 + if !user.blank? and user != page.author
  190 + if page.is_followed_by? user
  191 + button :cancel, unfollow_button_text(page), {:controller => 'profile', :action => 'unfollow_article', :article_id => page.id}
  192 + else
  193 + button :add, follow_button_text(page), {:controller => 'profile', :action => 'follow_article', :article_id => page.id}
  194 + end
  195 + end
  196 + end
  197 +
172 end 198 end
app/helpers/block_helper.rb
@@ -14,6 +14,7 @@ module BlockHelper @@ -14,6 +14,7 @@ module BlockHelper
14 </td> 14 </td>
15 <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td> 15 <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td>
16 <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td> 16 <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td>
  17 + <td>#{check_box_tag 'block[images][][new_window]', '1', image[:new_window], :class => 'highlight-new_window', :size => 1}</td>
17 </tr><tr class=\"image-title\" data-row-number='#{row_number}'> 18 </tr><tr class=\"image-title\" data-row-number='#{row_number}'>
18 <td colspan=\"3\"><label>#{ 19 <td colspan=\"3\"><label>#{
19 content_tag('span', _('Title')) + 20 content_tag('span', _('Title')) +
app/helpers/boxes_helper.rb
@@ -250,7 +250,7 @@ module BoxesHelper @@ -250,7 +250,7 @@ module BoxesHelper
250 end 250 end
251 end 251 end
252 252
253 - if editable?(block) 253 + if editable?(block, user)
254 buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) 254 buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
255 end 255 end
256 256
@@ -296,7 +296,7 @@ module BoxesHelper @@ -296,7 +296,7 @@ module BoxesHelper
296 return block.movable? || user.is_admin? 296 return block.movable? || user.is_admin?
297 end 297 end
298 298
299 - def editable?(block)  
300 - return block.editable? || user.is_admin? 299 + def editable?(block, user=nil)
  300 + return block.editable?(user) || user.is_admin?
301 end 301 end
302 end 302 end
app/helpers/forms_helper.rb
@@ -7,9 +7,10 @@ module FormsHelper @@ -7,9 +7,10 @@ module FormsHelper
7 7
8 def labelled_check_box( human_name, name, value = "1", checked = false, options = {} ) 8 def labelled_check_box( human_name, name, value = "1", checked = false, options = {} )
9 options[:id] ||= 'checkbox-' + FormsHelper.next_id_number 9 options[:id] ||= 'checkbox-' + FormsHelper.next_id_number
10 - hidden_field_tag(name, '0') +  
11 - check_box_tag( name, value, checked, options ) +  
12 - content_tag( 'label', human_name, :for => options[:id] ) 10 + html = options[:add_hidden] == false ? "" : hidden_field_tag(name, '0')
  11 +
  12 + html += check_box_tag( name, value, checked, options ) +
  13 + content_tag( 'label', human_name, :for => options[:id] )
13 end 14 end
14 15
15 def labelled_text_field( human_name, name, value=nil, options={} ) 16 def labelled_text_field( human_name, name, value=nil, options={} )
app/mailers/mailing.rb
@@ -2,7 +2,10 @@ require_dependency &#39;mailing_job&#39; @@ -2,7 +2,10 @@ require_dependency &#39;mailing_job&#39;
2 2
3 class Mailing < ActiveRecord::Base 3 class Mailing < ActiveRecord::Base
4 4
5 - attr_accessible :subject, :body 5 + acts_as_having_settings :field => :data
  6 +
  7 + attr_accessible :subject, :body, :data
  8 +
6 validates_presence_of :source_id, :subject, :body 9 validates_presence_of :source_id, :subject, :body
7 belongs_to :source, :foreign_key => :source_id, :polymorphic => true 10 belongs_to :source, :foreign_key => :source_id, :polymorphic => true
8 belongs_to :person 11 belongs_to :person
app/mailers/organization_mailing.rb
@@ -5,9 +5,17 @@ class OrganizationMailing &lt; Mailing @@ -5,9 +5,17 @@ class OrganizationMailing &lt; Mailing
5 end 5 end
6 6
7 def recipients(offset=0, limit=100) 7 def recipients(offset=0, limit=100)
8 - source.members.order(:id).offset(offset).limit(limit)  
9 - .joins("LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)") 8 + result = source.members.order(:id).offset(offset).limit(limit)
  9 +
  10 + if data.present? and data.is_a?(Hash) and data[:members_filtered]
  11 + result = result.where('profiles.id IN (?)', data[:members_filtered])
  12 + end
  13 +
  14 + if result.blank?
  15 + result = result.joins("LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)")
10 .where("m.person_id" => nil) 16 .where("m.person_id" => nil)
  17 + end
  18 + result
11 end 19 end
12 20
13 def each_recipient 21 def each_recipient
app/models/article.rb
@@ -8,8 +8,9 @@ class Article &lt; ActiveRecord::Base @@ -8,8 +8,9 @@ class Article &lt; ActiveRecord::Base
8 :accept_comments, :feed, :published, :source, :source_name, 8 :accept_comments, :feed, :published, :source, :source_name,
9 :highlighted, :notify_comments, :display_hits, :slug, 9 :highlighted, :notify_comments, :display_hits, :slug,
10 :external_feed_builder, :display_versions, :external_link, 10 :external_feed_builder, :display_versions, :external_link,
11 - :author, :published_at, :person_followers, :show_to_followers,  
12 - :image_builder, :display_preview, :archived 11 + :image_builder, :show_to_followers,
  12 + :author, :display_preview, :published_at, :person_followers,
  13 + :archived
13 14
14 acts_as_having_image 15 acts_as_having_image
15 16
@@ -83,6 +84,10 @@ class Article &lt; ActiveRecord::Base @@ -83,6 +84,10 @@ class Article &lt; ActiveRecord::Base
83 84
84 has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' 85 has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
85 86
  87 + has_many :article_followers, :dependent => :destroy
  88 + has_many :person_followers, :class_name => 'Person', :through => :article_followers, :source => :person
  89 + has_many :person_followers_emails, :class_name => 'User', :through => :person_followers, :source => :user, :select => :email
  90 +
86 has_many :article_categorizations, -> { where 'articles_categories.virtual = ?', false } 91 has_many :article_categorizations, -> { where 'articles_categories.virtual = ?', false }
87 has_many :categories, :through => :article_categorizations 92 has_many :categories, :through => :article_categorizations
88 93
@@ -95,7 +100,6 @@ class Article &lt; ActiveRecord::Base @@ -95,7 +100,6 @@ class Article &lt; ActiveRecord::Base
95 settings_items :author_name, :type => :string, :default => "" 100 settings_items :author_name, :type => :string, :default => ""
96 settings_items :allow_members_to_edit, :type => :boolean, :default => false 101 settings_items :allow_members_to_edit, :type => :boolean, :default => false
97 settings_items :moderate_comments, :type => :boolean, :default => false 102 settings_items :moderate_comments, :type => :boolean, :default => false
98 - settings_items :followers, :type => Array, :default => []  
99 has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions' 103 has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions'
100 104
101 belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' 105 belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id'
@@ -173,7 +177,6 @@ class Article &lt; ActiveRecord::Base @@ -173,7 +177,6 @@ class Article &lt; ActiveRecord::Base
173 end 177 end
174 end 178 end
175 179
176 -  
177 def is_trackable? 180 def is_trackable?
178 self.published? && self.notifiable? && self.advertise? && self.profile.public_profile 181 self.published? && self.notifiable? && self.advertise? && self.profile.public_profile
179 end 182 end
@@ -374,6 +377,10 @@ class Article &lt; ActiveRecord::Base @@ -374,6 +377,10 @@ class Article &lt; ActiveRecord::Base
374 self.parent and self.parent.forum? 377 self.parent and self.parent.forum?
375 end 378 end
376 379
  380 + def person_followers_email_list
  381 + person_followers_emails.map{|p|p.email}
  382 + end
  383 +
377 def info_from_last_update 384 def info_from_last_update
378 last_comment = comments.last 385 last_comment = comments.last
379 if last_comment 386 if last_comment
@@ -383,6 +390,10 @@ class Article &lt; ActiveRecord::Base @@ -383,6 +390,10 @@ class Article &lt; ActiveRecord::Base
383 end 390 end
384 end 391 end
385 392
  393 + def full_path
  394 + profile.hostname.blank? ? "/#{profile.identifier}/#{path}" : "/#{path}"
  395 + end
  396 +
386 def url 397 def url
387 @url ||= self.profile.url.merge(:page => path.split('/')) 398 @url ||= self.profile.url.merge(:page => path.split('/'))
388 end 399 end
@@ -408,13 +419,19 @@ class Article &lt; ActiveRecord::Base @@ -408,13 +419,19 @@ class Article &lt; ActiveRecord::Base
408 end 419 end
409 420
410 def download? view = nil 421 def download? view = nil
411 - (self.uploaded_file? and not self.image?) or  
412 - (self.image? and view.blank?) or  
413 - (not self.uploaded_file? and self.mime_type != 'text/html') 422 + false
  423 + end
  424 +
  425 + def is_followed_by?(user)
  426 + self.person_followers.include? user
  427 + end
  428 +
  429 + def download_disposition
  430 + 'inline'
414 end 431 end
415 432
416 def download_headers 433 def download_headers
417 - {} 434 + { :filename => filename, :type => mime_type, :disposition => download_disposition}
418 end 435 end
419 436
420 def alternate_languages 437 def alternate_languages
app/models/block.rb
@@ -195,8 +195,8 @@ class Block &lt; ActiveRecord::Base @@ -195,8 +195,8 @@ class Block &lt; ActiveRecord::Base
195 nil 195 nil
196 end 196 end
197 197
198 - # Is this block editable? (Default to <tt>false</tt>)  
199 - def editable? 198 + # Is this block editable? (Default to <tt>true</tt>)
  199 + def editable?(user=nil)
200 self.edit_modes == "all" 200 self.edit_modes == "all"
201 end 201 end
202 202
app/models/comment.rb
@@ -6,13 +6,14 @@ class Comment &lt; ActiveRecord::Base @@ -6,13 +6,14 @@ class Comment &lt; ActiveRecord::Base
6 :body => {:label => _('Content'), :weight => 2}, 6 :body => {:label => _('Content'), :weight => 2},
7 } 7 }
8 8
9 - attr_accessible :body, :author, :name, :email, :title, :reply_of_id, :source 9 + attr_accessible :body, :author, :name, :email, :title, :reply_of_id, :source, :follow_article
10 10
11 validates_presence_of :body 11 validates_presence_of :body
12 12
13 belongs_to :source, :counter_cache => true, :polymorphic => true 13 belongs_to :source, :counter_cache => true, :polymorphic => true
14 alias :article :source 14 alias :article :source
15 alias :article= :source= 15 alias :article= :source=
  16 + attr_accessor :follow_article
16 17
17 belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' 18 belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id'
18 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy 19 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy
@@ -102,10 +103,9 @@ class Comment &lt; ActiveRecord::Base @@ -102,10 +103,9 @@ class Comment &lt; ActiveRecord::Base
102 103
103 after_create :new_follower 104 after_create :new_follower
104 def new_follower 105 def new_follower
105 - if source.kind_of?(Article)  
106 - article.followers += [author_email]  
107 - article.followers -= article.profile.notification_emails  
108 - article.followers.uniq! 106 + if source.kind_of?(Article) and !author.nil? and @follow_article
  107 + article.person_followers += [author]
  108 + article.person_followers.uniq!
109 article.save 109 article.save
110 end 110 end
111 end 111 end
@@ -147,7 +147,7 @@ class Comment &lt; ActiveRecord::Base @@ -147,7 +147,7 @@ class Comment &lt; ActiveRecord::Base
147 if !notification_emails.empty? 147 if !notification_emails.empty?
148 CommentNotifier.notification(self).deliver 148 CommentNotifier.notification(self).deliver
149 end 149 end
150 - emails = article.followers - [author_email] 150 + emails = article.person_followers_email_list - [author_email]
151 if !emails.empty? 151 if !emails.empty?
152 CommentNotifier.mail_to_followers(self, emails).deliver 152 CommentNotifier.mail_to_followers(self, emails).deliver
153 end 153 end
app/models/disabled_enterprise_message_block.rb
@@ -19,7 +19,7 @@ class DisabledEnterpriseMessageBlock &lt; Block @@ -19,7 +19,7 @@ class DisabledEnterpriseMessageBlock &lt; Block
19 end 19 end
20 end 20 end
21 21
22 - def editable? 22 + def editable?(user=nil)
23 false 23 false
24 end 24 end
25 25
app/models/environment.rb
@@ -56,6 +56,7 @@ class Environment &lt; ActiveRecord::Base @@ -56,6 +56,7 @@ class Environment &lt; ActiveRecord::Base
56 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'), 56 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'),
57 'edit_appearance' => N_('Edit appearance'), 57 'edit_appearance' => N_('Edit appearance'),
58 'manage_email_templates' => N_('Manage Email Templates'), 58 'manage_email_templates' => N_('Manage Email Templates'),
  59 + 'edit_raw_html_block' => N_('Edit Raw HTML block'),
59 } 60 }
60 61
61 module Roles 62 module Roles
app/models/highlights_block.rb
@@ -15,6 +15,8 @@ class HighlightsBlock &lt; Block @@ -15,6 +15,8 @@ class HighlightsBlock &lt; Block
15 if !Noosfero.root.nil? and !i[:address].start_with?(Noosfero.root + '/') 15 if !Noosfero.root.nil? and !i[:address].start_with?(Noosfero.root + '/')
16 i[:address] = Noosfero.root + i[:address] 16 i[:address] = Noosfero.root + i[:address]
17 end 17 end
  18 + i[:new_window] = i[:new_window] == '1' ? true : false
  19 +
18 begin 20 begin
19 file = UploadedFile.find(i[:image_id]) 21 file = UploadedFile.find(i[:image_id])
20 i[:image_src] = file.public_filename 22 i[:image_src] = file.public_filename
app/models/person.rb
1 # A person is the profile of an user holding all relationships with the rest of the system 1 # A person is the profile of an user holding all relationships with the rest of the system
2 class Person < Profile 2 class Person < Profile
3 3
4 - attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone,  
5 - :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference,  
6 - :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study,  
7 - :custom_area_of_study, :professional_activity, :organization_website, :following_articles 4 + attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, :custom_area_of_study, :professional_activity, :organization_website, :following_articles
8 5
9 SEARCH_FILTERS = { 6 SEARCH_FILTERS = {
10 :order => %w[more_recent more_popular more_active], 7 :order => %w[more_recent more_popular more_active],
@@ -19,26 +16,29 @@ class Person &lt; Profile @@ -19,26 +16,29 @@ class Person &lt; Profile
19 acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)} 16 acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)}
20 acts_as_accessor 17 acts_as_accessor
21 18
22 - scope :members_of, -> resources { 19 + scope :members_of, lambda { |resources, field = ''|
23 resources = Array(resources) 20 resources = Array(resources)
  21 + joins = [:role_assignments]
  22 + joins << :user if User.attribute_names.include? field
  23 +
24 conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ') 24 conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ')
25 - select('DISTINCT profiles.*').joins(:role_assignments).where([conditions]) 25 + distinct.select('profiles.*').joins(joins).where([conditions])
26 } 26 }
27 27
28 scope :not_members_of, -> resources { 28 scope :not_members_of, -> resources {
29 resources = Array(resources) 29 resources = Array(resources)
30 conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ') 30 conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ')
31 - select('DISTINCT profiles.*').where('"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "role_assignments" ON "role_assignments"."accessor_id" = "profiles"."id" AND "role_assignments"."accessor_type" = (Profile) WHERE "profiles"."type" IN (Person) AND (%s))' % conditions) 31 + distinct.select('profiles.*').where('"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "role_assignments" ON "role_assignments"."accessor_id" = "profiles"."id" AND "role_assignments"."accessor_type" = (Profile) WHERE "profiles"."type" IN (Person) AND (%s))' % conditions)
32 } 32 }
33 33
34 scope :by_role, -> roles { 34 scope :by_role, -> roles {
35 roles = Array(roles) 35 roles = Array(roles)
36 - select('DISTINCT profiles.*').joins(:role_assignments).where('role_assignments.role_id IN (?)', roles) 36 + distinct.select('profiles.*').joins(:role_assignments).where('role_assignments.role_id IN (?)', roles)
37 } 37 }
38 38
39 scope :not_friends_of, -> resources { 39 scope :not_friends_of, -> resources {
40 resources = Array(resources) 40 resources = Array(resources)
41 - select('DISTINCT profiles.*').where('"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "friendships" ON "friendships"."person_id" = "profiles"."id" WHERE "friendships"."friend_id" IN (%s))' % resources.map(&:id)) 41 + distinct.select('profiles.*').where('"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "friendships" ON "friendships"."person_id" = "profiles"."id" WHERE "friendships"."friend_id" IN (%s))' % resources.map(&:id))
42 } 42 }
43 43
44 scope :visible_for_person, lambda { |person| 44 scope :visible_for_person, lambda { |person|
@@ -51,8 +51,7 @@ class Person &lt; Profile @@ -51,8 +51,7 @@ class Person &lt; Profile
51 ['( roles.key = ? AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR ( 51 ['( roles.key = ? AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR (
52 ( ( friendships.person_id = ? ) OR (profiles.public_profile = ?)) AND (profiles.visible = ?) )', 'environment_administrator', Profile.name, person.id, person.id, true, true] 52 ( ( friendships.person_id = ? ) OR (profiles.public_profile = ?)) AND (profiles.visible = ?) )', 'environment_administrator', Profile.name, person.id, person.id, true, true]
53 ).uniq 53 ).uniq
54 - }  
55 - 54 + }
56 55
57 def has_permission_with_admin?(permission, resource) 56 def has_permission_with_admin?(permission, resource)
58 return true if resource.blank? || resource.admins.include?(self) 57 return true if resource.blank? || resource.admins.include?(self)
@@ -90,7 +89,8 @@ class Person &lt; Profile @@ -90,7 +89,8 @@ class Person &lt; Profile
90 has_many :article_followers, :dependent => :destroy 89 has_many :article_followers, :dependent => :destroy
91 has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article 90 has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article
92 has_many :comments, :foreign_key => :author_id 91 has_many :comments, :foreign_key => :author_id
93 - 92 + has_many :article_followers, :dependent => :destroy
  93 + has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article
94 has_many :friendships, :dependent => :destroy 94 has_many :friendships, :dependent => :destroy
95 has_many :friends, :class_name => 'Person', :through => :friendships 95 has_many :friends, :class_name => 'Person', :through => :friendships
96 96
@@ -123,10 +123,10 @@ class Person &lt; Profile @@ -123,10 +123,10 @@ class Person &lt; Profile
123 scope :more_popular, -> { order 'friends_count DESC' } 123 scope :more_popular, -> { order 'friends_count DESC' }
124 124
125 scope :abusers, -> { 125 scope :abusers, -> {
126 - joins(:abuse_complaints).where('tasks.status = 3').select('DISTINCT profiles.*') 126 + joins(:abuse_complaints).where('tasks.status = 3').distinct.select('profiles.*')
127 } 127 }
128 scope :non_abusers, -> { 128 scope :non_abusers, -> {
129 - select("DISTINCT profiles.*"). 129 + distinct.select("profiles.*").
130 joins("LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'"). 130 joins("LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'").
131 where("tasks.status != 3 OR tasks.id is NULL") 131 where("tasks.status != 3 OR tasks.id is NULL")
132 } 132 }
@@ -135,6 +135,11 @@ class Person &lt; Profile @@ -135,6 +135,11 @@ class Person &lt; Profile
135 scope :activated, -> { joins(:user).where('users.activation_code IS NULL AND users.activated_at IS NOT NULL') } 135 scope :activated, -> { joins(:user).where('users.activation_code IS NULL AND users.activated_at IS NOT NULL') }
136 scope :deactivated, -> { joins(:user).where('NOT (users.activation_code IS NULL AND users.activated_at IS NOT NULL)') } 136 scope :deactivated, -> { joins(:user).where('NOT (users.activation_code IS NULL AND users.activated_at IS NOT NULL)') }
137 137
  138 + scope :with_role, -> role_id {
  139 + distinct.joins(:role_assignments).
  140 + where("role_assignments.role_id = #{role_id}")
  141 + }
  142 +
138 after_destroy do |person| 143 after_destroy do |person|
139 Friendship.where(friend_id: person.id).each{ |friendship| friendship.destroy } 144 Friendship.where(friend_id: person.id).each{ |friendship| friendship.destroy }
140 end 145 end
app/models/profile.rb
@@ -78,6 +78,9 @@ class Profile &lt; ActiveRecord::Base @@ -78,6 +78,9 @@ class Profile &lt; ActiveRecord::Base
78 def self.organization_member_roles(env_id) 78 def self.organization_member_roles(env_id)
79 all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? || !r.profile_id.nil?} 79 all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? || !r.profile_id.nil?}
80 end 80 end
  81 + def self.organization_custom_roles(env_id, profile_id)
  82 + all_roles(env_id).where('profile_id = ?', profile_id)
  83 + end
81 def self.all_roles(env_id) 84 def self.all_roles(env_id)
82 Role.where(environment_id: env_id) 85 Role.where(environment_id: env_id)
83 end 86 end
@@ -119,7 +122,7 @@ class Profile &lt; ActiveRecord::Base @@ -119,7 +122,7 @@ class Profile &lt; ActiveRecord::Base
119 include Noosfero::Plugin::HotSpot 122 include Noosfero::Plugin::HotSpot
120 123
121 scope :memberships_of, -> person { 124 scope :memberships_of, -> person {
122 - select('DISTINCT profiles.*'). 125 + distinct.select('profiles.*').
123 joins(:role_assignments). 126 joins(:role_assignments).
124 where('role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id) 127 where('role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id)
125 } 128 }
@@ -185,15 +188,23 @@ class Profile &lt; ActiveRecord::Base @@ -185,15 +188,23 @@ class Profile &lt; ActiveRecord::Base
185 188
186 include TimeScopes 189 include TimeScopes
187 190
188 - def members 191 + def members(by_field = '')
189 scopes = plugins.dispatch_scopes(:organization_members, self) 192 scopes = plugins.dispatch_scopes(:organization_members, self)
190 - scopes << Person.members_of(self) 193 + scopes << Person.members_of(self,by_field)
191 return scopes.first if scopes.size == 1 194 return scopes.first if scopes.size == 1
192 ScopeTool.union *scopes 195 ScopeTool.union *scopes
193 end 196 end
194 197
195 - def members_by_name  
196 - members.order('profiles.name') 198 + def members_by(field,value = nil)
  199 + if value and !value.blank?
  200 + members_like(field,value).order('profiles.name')
  201 + else
  202 + members.order('profiles.name')
  203 + end
  204 + end
  205 +
  206 + def members_like(field,value)
  207 + members(field).where("LOWER(#{field}) LIKE ?", "%#{value.downcase}%") if value
197 end 208 end
198 209
199 class << self 210 class << self
@@ -781,13 +792,13 @@ private :generate_url, :url_options @@ -781,13 +792,13 @@ private :generate_url, :url_options
781 end 792 end
782 793
783 # Adds a person as member of this Profile. 794 # Adds a person as member of this Profile.
784 - def add_member(person) 795 + def add_member(person, attributes={})
785 if self.has_members? 796 if self.has_members?
786 if self.closed? && members.count > 0 797 if self.closed? && members.count > 0
787 AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) 798 AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person)
788 else 799 else
789 - self.affiliate(person, Profile::Roles.admin(environment.id)) if members.count == 0  
790 - self.affiliate(person, Profile::Roles.member(environment.id)) 800 + self.affiliate(person, Profile::Roles.admin(environment.id), attributes) if members.count == 0
  801 + self.affiliate(person, Profile::Roles.member(environment.id), attributes)
791 end 802 end
792 person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } 803 person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel }
793 remove_from_suggestion_list person 804 remove_from_suggestion_list person
@@ -1164,6 +1175,10 @@ private :generate_url, :url_options @@ -1164,6 +1175,10 @@ private :generate_url, :url_options
1164 end 1175 end
1165 end 1176 end
1166 1177
  1178 + def can_view_field? current_person, field
  1179 + display_private_info_to?(current_person) || (public_fields.include?(field) && public?)
  1180 + end
  1181 +
1167 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true 1182 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true
1168 def preferred_login_redirection 1183 def preferred_login_redirection
1169 redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login 1184 redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login
app/models/raw_html_block.rb
@@ -19,4 +19,9 @@ class RawHTMLBlock &lt; Block @@ -19,4 +19,9 @@ class RawHTMLBlock &lt; Block
19 def has_macro? 19 def has_macro?
20 true 20 true
21 end 21 end
  22 +
  23 + def editable?(user)
  24 + user.has_permission?('edit_raw_html_block', environment)
  25 + end
  26 +
22 end 27 end
app/models/rss_feed.rb
@@ -65,6 +65,10 @@ class RssFeed &lt; Article @@ -65,6 +65,10 @@ class RssFeed &lt; Article
65 'text/xml' 65 'text/xml'
66 end 66 end
67 67
  68 + def download?(view = nil)
  69 + true
  70 + end
  71 +
68 include Rails.application.routes.url_helpers 72 include Rails.application.routes.url_helpers
69 def fetch_articles 73 def fetch_articles
70 if parent && parent.has_posts? 74 if parent && parent.has_posts?
app/models/uploaded_file.rb
@@ -2,6 +2,9 @@ @@ -2,6 +2,9 @@
2 # 2 #
3 # Limitation: only file metadata are versioned. Only the latest version 3 # Limitation: only file metadata are versioned. Only the latest version
4 # of the file itself is kept. (FIXME?) 4 # of the file itself is kept. (FIXME?)
  5 +
  6 +require 'sdbm'
  7 +
5 class UploadedFile < Article 8 class UploadedFile < Article
6 9
7 attr_accessible :uploaded_data, :title 10 attr_accessible :uploaded_data, :title
@@ -10,6 +13,19 @@ class UploadedFile &lt; Article @@ -10,6 +13,19 @@ class UploadedFile &lt; Article
10 _('File') 13 _('File')
11 end 14 end
12 15
  16 + DBM_PRIVATE_FILE = 'cache/private_files'
  17 + after_save do |uploaded_file|
  18 + if uploaded_file.published_changed?
  19 + dbm = SDBM.open(DBM_PRIVATE_FILE)
  20 + if uploaded_file.published
  21 + dbm.delete(uploaded_file.public_filename)
  22 + else
  23 + dbm.store(uploaded_file.public_filename, uploaded_file.full_path)
  24 + end
  25 + dbm.close
  26 + end
  27 + end
  28 +
13 track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? }, :custom_target => :parent 29 track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? }, :custom_target => :parent
14 30
15 def title 31 def title
@@ -106,10 +122,13 @@ class UploadedFile &lt; Article @@ -106,10 +122,13 @@ class UploadedFile &lt; Article
106 self.name ||= self.filename 122 self.name ||= self.filename
107 end 123 end
108 124
109 - def download_headers  
110 - {  
111 - 'Content-Disposition' => "attachment; filename=\"#{self.filename}\"",  
112 - } 125 + def download_disposition
  126 + case content_type
  127 + when 'application/pdf'
  128 + 'inline'
  129 + else
  130 + 'attachment'
  131 + end
113 end 132 end
114 133
115 def data 134 def data
app/views/account/forgot_password.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <%= form_tag({:action => 'forgot_password'}, :method => 'post', :id => 'forgot-password-form') do %> 5 <%= form_tag({:action => 'forgot_password'}, :method => 'post', :id => 'forgot-password-form') do %>
6 <%= labelled_form_field fields_label, text_field_tag(:value) %> 6 <%= labelled_form_field fields_label, text_field_tag(:value) %>
7 7
8 - <h3><%= _('Please type the two words below') %></h3> 8 + <h3><%= _('Please type the captcha text below') %></h3>
9 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> 9 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %>
10 10
11 <div> 11 <div>
app/views/account/index.html.erb
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 </p> 11 </p>
12 12
13 <p> 13 <p>
14 -<%= link_to_homepage(_('My home page.')) %> 14 +<%= link_to_homepage(_('My home page.'), user) %>
15 <%= _('See your homepage.') %> 15 <%= _('See your homepage.') %>
16 </p> 16 </p>
17 17
app/views/blocks/highlights.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <div class='highlights-border'> 3 <div class='highlights-border'>
4 <div class='highlights-container'> 4 <div class='highlights-container'>
5 <% block.featured_images.each do |img| %> 5 <% block.featured_images.each do |img| %>
6 - <a href="<%= img[:address] %>" title="<%= img[:title] %>" class="highlights-image-link"> 6 + <a href="<%= img[:address] %>" <%= 'target="_blank"' if img[:new_window] %> title="<%= img[:title] %>" class="highlights-image-link">
7 <%= image_tag [Noosfero.root, img[:image_src]].join, alt: img[:title] %> 7 <%= image_tag [Noosfero.root, img[:image_src]].join, alt: img[:title] %>
8 <p class="highlights-label"><%= img[:title] %></p> 8 <p class="highlights-label"><%= img[:title] %></p>
9 </a> 9 </a>
app/views/box_organizer/_highlights_block.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <strong><%= _('Highlights') %></strong> 3 <strong><%= _('Highlights') %></strong>
4 4
5 <table class="noborder"><tbody id="highlights-data-table"> 5 <table class="noborder"><tbody id="highlights-data-table">
6 - <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th></tr> 6 + <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('New Window') %></th></tr>
7 <% @block.images.each_with_index do |image, index| %> 7 <% @block.images.each_with_index do |image, index| %>
8 <%= highlights_block_config_image_fields @block, image, index %> 8 <%= highlights_block_config_image_fields @block, image, index %>
9 <% end %> 9 <% end %>
app/views/cms/_drag_and_drop_note.html.erb
1 <p> 1 <p>
2 <em> 2 <em>
3 - <%= _('Drag images to add them to the text.') %>  
4 - <%= _('Click on file names to add links to the text.') %> 3 + <%= _('Drag images to add them to the text or click on file names to add links to the text.') %>
5 </em> 4 </em>
6 </p> 5 </p>
app/views/cms/_text_editor_sidebar.html.erb
@@ -17,8 +17,8 @@ @@ -17,8 +17,8 @@
17 :parent_id, profile, default_folder, {}, {}, 17 :parent_id, profile, default_folder, {}, {},
18 "type='Folder' or type='Gallery'" 18 "type='Folder' or type='Gallery'"
19 ) %> 19 ) %>
  20 + <%= button(:newfolder, _('New folder'), '#', :id => 'new-folder-button') %>
20 </div> 21 </div>
21 - <%= button(:newfolder, _('New folder'), '#', :id => 'new-folder-button') %>  
22 <p><%= file_field_tag('file', :multiple => true) %></p> 22 <p><%= file_field_tag('file', :multiple => true) %></p>
23 <% end %> 23 <% end %>
24 </div> 24 </div>
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 <div id='published-media' class='text-editor-sidebar-box' data-url='<%= url_for({:controller => 'cms', :action => 'published_media_items', :profile => profile.identifier}) %>'> 31 <div id='published-media' class='text-editor-sidebar-box' data-url='<%= url_for({:controller => 'cms', :action => 'published_media_items', :profile => profile.identifier}) %>'>
32 <%= select_profile_folder(nil, :parent_id, profile, 'recent-media', {}, {}, 32 <%= select_profile_folder(nil, :parent_id, profile, 'recent-media', {}, {},
33 "type='Folder' or type='Gallery'", {:root_label => _('Recent media')}) %> 33 "type='Folder' or type='Gallery'", {:root_label => _('Recent media')}) %>
34 - <%= labelled_form_field _('Search'), text_field_tag('q') %> 34 + <%= labelled_form_field _('Search among your uploaded files'), text_field_tag('q', '', placeholder: _('Write words about the file you are looking for')) %>
35 <%= render :partial => 'drag_and_drop_note' %> 35 <%= render :partial => 'drag_and_drop_note' %>
36 <div class='items'> 36 <div class='items'>
37 <%= render :partial => 'published_media_items' %> 37 <%= render :partial => 'published_media_items' %>
app/views/comment/_comment_form.html.erb
@@ -77,6 +77,10 @@ function check_captcha(button, confirm_action) { @@ -77,6 +77,10 @@ function check_captcha(button, confirm_action) {
77 <%= labelled_form_field(_('Title'), f.text_field(:title)) %> 77 <%= labelled_form_field(_('Title'), f.text_field(:title)) %>
78 <%= required labelled_form_field(_('Enter your comment'), f.text_area(:body, :rows => 5)) %> 78 <%= required labelled_form_field(_('Enter your comment'), f.text_area(:body, :rows => 5)) %>
79 79
  80 + <% if logged_in? %>
  81 + <%= labelled_form_field check_box(:comment, :follow_article, {}, true, false) + _('Follow this article'), '' %>
  82 + <% end%>
  83 +
80 <%= hidden_field_tag(:confirm, 'false') %> 84 <%= hidden_field_tag(:confirm, 'false') %>
81 <%= hidden_field_tag(:view, params[:view])%> 85 <%= hidden_field_tag(:view, params[:view])%>
82 <%= f.hidden_field(:reply_of_id) %> 86 <%= f.hidden_field(:reply_of_id) %>
app/views/comment/_comments_with_pagination.html.erb 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +<% if @comments.present? %>
  2 + <%= render :partial => 'comment/comment', :collection => @comments %>
  3 + <%= pagination_links @comments, :param_name => 'comment_page', :params => { :comment_order => @comment_order } %>
  4 +<% end %>
app/views/content_viewer/_article_toolbar.html.erb
@@ -57,6 +57,8 @@ @@ -57,6 +57,8 @@
57 <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url], plugin_button[:html_options] %> 57 <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url], plugin_button[:html_options] %>
58 <% end %> 58 <% end %>
59 59
  60 + <%= following_button @page, user %>
  61 +
60 <%= report_abuse(profile, :link, @page) %> 62 <%= report_abuse(profile, :link, @page) %>
61 63
62 </div> 64 </div>
app/views/content_viewer/_publishing_info.html.erb
@@ -10,6 +10,24 @@ @@ -10,6 +10,24 @@
10 <%= (" - %s") % link_to_comments(@page)%> 10 <%= (" - %s") % link_to_comments(@page)%>
11 </span> 11 </span>
12 <% end %> 12 <% end %>
  13 +
  14 +<span class="followers-count">
  15 +|
  16 +<% if @page.event? %>
  17 + <% if @page.person_followers.size > 0 %>
  18 + <%= _("%s will attend this event.") % [ pluralize(@page.person_followers.size, _("person"))]%>
  19 + <% else %>
  20 + <%= _("No one attending this event yet.") %>
  21 + <% end %>
  22 +<% else %>
  23 + <% if @page.person_followers.size > 0 %>
  24 + <%= _("%s following this article.") % [ pluralize(@page.person_followers.size, _("person"))]%>
  25 + <% else %>
  26 + <%= _("No one following this article yet.") %>
  27 + <% end %>
  28 +<% end %>
  29 +</span>
  30 +
13 </span> 31 </span>
14 32
15 <% if @page.display_hits? || @page.license.present? %> 33 <% if @page.display_hits? || @page.license.present? %>
app/views/content_viewer/view_page.html.erb
@@ -81,7 +81,7 @@ @@ -81,7 +81,7 @@
81 <ul class="article-comments-list"> 81 <ul class="article-comments-list">
82 <% if @comments.present? %> 82 <% if @comments.present? %>
83 <%= render :partial => 'comment/comment', :collection => @comments %> 83 <%= render :partial => 'comment/comment', :collection => @comments %>
84 - <%= pagination_links @comments, :param_name => 'comment_page' %> 84 + <%= pagination_links @comments, :param_name => 'comment_page', :params => { :comment_order => @comment_order } %>
85 <% end %> 85 <% end %>
86 </ul> 86 </ul>
87 87
app/views/file_presenter/_generic.html.erb
@@ -2,4 +2,4 @@ @@ -2,4 +2,4 @@
2 <%= generic.abstract %> 2 <%= generic.abstract %>
3 </div> 3 </div>
4 4
5 -<%= button(:download, _('Download'), [Noosfero.root, generic.public_filename].join, class:'download-link', option:'primary', size:'lg') %> 5 +<%= button(:download, _('Download'), generic.url, class:'download-link', option:'primary', size:'lg', :target => "_blank") %>
app/views/profile/_profile_members_list.html.erb
@@ -9,7 +9,8 @@ @@ -9,7 +9,8 @@
9 </div> 9 </div>
10 <ul class="profile-list-<%= role %>" > 10 <ul class="profile-list-<%= role %>" >
11 <% users.each do |u| %> 11 <% users.each do |u| %>
12 - <%= profile_image_link(u, :thumb) %> 12 + <% extra_info = u.member_since_date(profile) == Date.today ? {:value =>_('New'), :class => 'new-profile'}:'' %>
  13 + <%= profile_image_link(u, :thumb, 'li', extra_info) %>
13 <% end %> 14 <% end %>
14 </ul> 15 </ul>
15 16
app/views/profile/members.html.erb
@@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
19 :id => "members-tab", 19 :id => "members-tab",
20 :content => div_members 20 :content => div_members
21 } %> 21 } %>
22 -  
23 <% div_admins = content_tag :div, :class => "profile-admins" do 22 <% div_admins = content_tag :div, :class => "profile-admins" do
24 render :partial => 'profile_members_list', 23 render :partial => 'profile_members_list',
25 :locals => { 24 :locals => {
app/views/profile/send_mail.html.erb
@@ -10,6 +10,9 @@ @@ -10,6 +10,9 @@
10 </div> 10 </div>
11 <% end %> 11 <% end %>
12 12
  13 + <% to = @mailing.data[:members_filtered].present? ? @mailing.recipients.map{|r| r.name}.join(', ') : _('All members')%>
  14 + <%= labelled_form_field(_('To:'), text_area(:data, 'members_filtered', :value => to, :rows => 4, :disabled => 'disabled', :class => 'send-mail-recipients')) %>
  15 +
13 <%= form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %> 16 <%= form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %>
14 17
15 <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> 18 <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %>
app/views/profile_members/_index_buttons.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <%= button :person, _('Invite people to join'), :controller => 'invite', :action => 'invite_friends' %> 5 <%= button :person, _('Invite people to join'), :controller => 'invite', :action => 'invite_friends' %>
6 <% end %> 6 <% end %>
7 <% if profile.community? and user.has_permission?(:send_mail_to_members, profile) %> 7 <% if profile.community? and user.has_permission?(:send_mail_to_members, profile) %>
8 - <%= button :send, _('Send e-mail to members'), :controller => 'profile', :action => 'send_mail' %> 8 + <%= submit_button(:send, _('Send e-mail to members')) %>
9 <% end %> 9 <% end %>
10 <% @plugins.dispatch(:manage_members_extra_buttons).each do |plugin_button| %> 10 <% @plugins.dispatch(:manage_members_extra_buttons).each do |plugin_button| %>
11 <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url] %> 11 <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url] %>
app/views/profile_members/_members_filter.erb 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +<%= form_tag '#', :method => 'post' do %>
  2 +
  3 + <%= field_set_tag _('Filter'), :class => 'filter_fields' do %>
  4 + <p>
  5 + <%= labelled_text_field(_('Name or Email')+': ', "filters[name]", @filters[:name], {:id => 'filter-name-autocomplete',:size => 30}) %>
  6 + </p>
  7 +
  8 + <p><%= _('Roles:') %> </p>
  9 + <% @data[:roles].each do |r| %>
  10 + <%= labelled_check_box(r.name, 'filters[roles][]', r.id, @filters[:roles].include?(r.id.to_s), :add_hidden => false) %><br/>
  11 + <% end %>
  12 + <p>
  13 + <%= submit_button(:search, _('Search')) %>
  14 + </p>
  15 + <% end %>
  16 +<% end %>
  17 +
  18 +<%= javascript_include_tag params[:controller] %>
0 \ No newline at end of file 19 \ No newline at end of file
app/views/profile_members/_members_list.html.erb
1 -<% collection = @collection == :profile_admins ? profile.admins : profile.members_by_name %> 1 +<% members = @data ? @data[:members] : profile.members_by('name') %>
  2 +<% collection = @collection == :profile_admins ? profile.admins : members %>
2 <% title = @title ? @title : _('Current members') %> 3 <% title = @title ? @title : _('Current members') %>
3 <% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %> 4 <% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %>
  5 +<%= javascript_include_tag params[:controller] %>
4 6
5 <h3><%= title %></h3> 7 <h3><%= title %></h3>
6 8
7 <table> 9 <table>
  10 + <col width="1">
8 <tr> 11 <tr>
  12 + <th><%= check_box_tag 'checkbox-all', 1, false, :onClick => "toggle(this)" %></th>
9 <th><%= _('Member') %></th> 13 <th><%= _('Member') %></th>
10 <th><%= _('Actions') %></th> 14 <th><%= _('Actions') %></th>
11 </tr> 15 </tr>
  16 +
12 <% collection.each do |m| %> 17 <% collection.each do |m| %>
13 <tr title="<%= m.name %>"> 18 <tr title="<%= m.name %>">
  19 + <td><%= labelled_check_box('', 'members_filtered[]', m.id.to_s, false, :id => 'checkbox-'+m.identifier) %></td>
14 <td><%= link_to_profile m.short_name, m.identifier, :title => m.name %> </td> 20 <td><%= link_to_profile m.short_name, m.identifier, :title => m.name %> </td>
15 <td> 21 <td>
16 <div class="members-buttons-cell"> 22 <div class="members-buttons-cell">
@@ -27,3 +33,8 @@ @@ -27,3 +33,8 @@
27 </tr> 33 </tr>
28 <% end %> 34 <% end %>
29 </table> 35 </table>
  36 +<% if collection.empty? %>
  37 + <p>
  38 + <em><%= _('No members found to: %s') % profile.name %></em>
  39 + </p>
  40 +<% end %>
app/views/profile_members/index.html.erb
1 <h1><%= h profile.short_name(50) %></h1> 1 <h1><%= h profile.short_name(50) %></h1>
2 2
3 -<%= render :partial => 'index_buttons' %> 3 +<%= render :partial => 'members_filter' %>
4 4
5 -<div id="members-list">  
6 - <%= render :partial => 'members_list' %>  
7 -</div> 5 +<%= form_tag 'profile_members/send_mail', :method => 'post' do %>
  6 + <div id="members-list">
  7 + <%= render :partial => 'members_list' %>
  8 + </div>
8 9
9 -<%= render :partial => 'index_buttons' %> 10 + <%= render :partial => 'index_buttons' %>
  11 +
  12 +<% end %>
app/views/region_validators/region.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <ul> 5 <ul>
6 <% for validator in @region.validators %> 6 <% for validator in @region.validators %>
7 <li> 7 <li>
8 - <%= link_to_homepage validator.name, validator.identifier %> 8 + <%= link_to_homepage validator.name, validator %>
9 <%= link_to _('Remove validation rights'), { :action => 'remove', :id => @region.id, :validator_id => validator }, :method => 'post' %> 9 <%= link_to _('Remove validation rights'), { :action => 'remove', :id => @region.id, :validator_id => validator }, :method => 'post' %>
10 </li> 10 </li>
11 <% end %> 11 <% end %>
app/views/search/_full_enterprise.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 @order == 'more_recent' ? enterprise.send(@order + '_label') + show_date(enterprise.created_at) : enterprise.send(@order + '_label') %> 5 @order == 'more_recent' ? enterprise.send(@order + '_label') + show_date(enterprise.created_at) : enterprise.send(@order + '_label') %>
6 </div> 6 </div>
7 <div class="search-enterprise-item-column-right"> 7 <div class="search-enterprise-item-column-right">
8 - <%= link_to_homepage(enterprise.name, enterprise.identifier, :class => "search-result-title") %> 8 + <%= link_to_homepage enterprise.name, enterprise, class: "search-result-title" %>
9 <div class="search-enterprise-description"> 9 <div class="search-enterprise-description">
10 <% if enterprise.description %> 10 <% if enterprise.description %>
11 <% body_stripped = strip_tags(enterprise.description) %> 11 <% body_stripped = strip_tags(enterprise.description) %>
app/views/search/_full_product.html.erb
@@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
44 <div class="search-product-item-second-column"> 44 <div class="search-product-item-second-column">
45 <%= link_to_product product, :class => 'search-result-title' %> 45 <%= link_to_product product, :class => 'search-result-title' %>
46 <div class="search-product-supplier"> 46 <div class="search-product-supplier">
47 - <span class="search-field-label"><%= _('Supplier') %> </span><%= link_to_homepage(product.enterprise.name, product.enterprise.identifier) %> 47 + <span class="search-field-label"><%= _('Supplier') %> </span><%= link_to_homepage product.enterprise.name, product.enterprise %>
48 </div> 48 </div>
49 <div class="search-product-description"> 49 <div class="search-product-description">
50 <% if product.description %> 50 <% if product.description %>
app/views/search/_image.html.erb
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
26 <% end %> 26 <% end %>
27 <% elsif image.is_a? Gallery %> 27 <% elsif image.is_a? Gallery %>
28 <div class="search-gallery-items"> 28 <div class="search-gallery-items">
29 - <% r = image.children.order(:updated_at).where('type = ?', 'UploadedFile').last(3) %> 29 + <% r = image.children.latest.images.limit(3) %>
30 <% if r.length > 0 %> 30 <% if r.length > 0 %>
31 <% r.each_index do |i| img = r[i] %> 31 <% r.each_index do |i| img = r[i] %>
32 <%= link_to '', img.view_url, :class => "search-image-pic pic-num#{i+1}", 32 <%= link_to '', img.view_url, :class => "search-image-pic pic-num#{i+1}",
@@ -47,6 +47,8 @@ @@ -47,6 +47,8 @@
47 <% else %> 47 <% else %>
48 <div class="search-no-image"><span><%= _('No image') %></span></div> 48 <div class="search-no-image"><span><%= _('No image') %></span></div>
49 <% end %> 49 <% end %>
  50 + <% elsif image.first_image.present? %>
  51 + <img src="<%= image.first_image %>" class="automatic-abstract-thumb search-image-pic">
50 <% else %> 52 <% else %>
51 <div class="search-content-type-icon icon-content-<%=image.class.to_s.underscore.dasherize%>"></div> 53 <div class="search-content-type-icon icon-content-<%=image.class.to_s.underscore.dasherize%>"></div>
52 <% end %> 54 <% end %>
app/views/user_mailer/activation_code.text.erb
1 <%= _('Hi, %{recipient}!') % { :recipient => @recipient } %> 1 <%= _('Hi, %{recipient}!') % { :recipient => @recipient } %>
2 2
3 -<%= word_wrap(_('Welcome to %{environment}! To activate your account, follow the link: %{activation_url}') % { :environment => @environment.name, :activation_url => @url + url_for(:controller => :account, :action => :activate, :activation_code => @activation_code, :redirection => @redirection, :join => @join) }) %> 3 +<%= word_wrap(_('Welcome to %{environment}! To activate your account, follow the link: %{activation_url}') % { :environment => @environment.name, :activation_url => url_for(:controller => :account, :action => :activate, :activation_code => @activation_code, :redirection => @redirection, :join => @join) }) %>
4 4
5 <%= _("Greetings,") %> 5 <%= _("Greetings,") %>
6 6
7 -- 7 --
8 <%= _('%s team.') % @environment.name %> 8 <%= _('%s team.') % @environment.name %>
9 -<%= url_for @url %> 9 +<%= @url %>
db/migrate/20150103134141_add_edit_raw_html_block_to_admin_role.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +class AddEditRawHtmlBlockToAdminRole < ActiveRecord::Migration
  2 + def self.up
  3 + Environment.all.map(&:id).each do |id|
  4 + role = Environment::Roles.admin(id)
  5 + role.permissions << 'edit_raw_html_block'
  6 + role.save!
  7 + end
  8 + end
  9 +
  10 + def self.down
  11 + Environment.all.map(&:id).each do |id|
  12 + role = Environment::Roles.admin(id)
  13 + role.permissions -= ['edit_raw_html_block']
  14 + role.save!
  15 + end
  16 + end
  17 +end
db/migrate/20151105175041_create_article_followers.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class CreateArticleFollowers < ActiveRecord::Migration
  2 + def self.up
  3 + execute("CREATE TABLE article_followers AS (SELECT profiles.id AS person_id, t.id AS article_id, clock_timestamp() AS since FROM (SELECT articles.id, regexp_split_to_table(replace(replace(substring(articles.setting FROM ':followers:[^:]*'), ':followers:', ''), '- ', ''), '\n') AS follower FROM articles) t INNER JOIN users ON users.email = follower INNER JOIN profiles ON users.id = profiles.user_id WHERE follower != '');")
  4 + add_timestamps :article_followers
  5 + add_index :article_followers, :person_id
  6 + add_index :article_followers, :article_id
  7 + add_index :article_followers, [:person_id, :article_id], :unique => true
  8 + end
  9 +
  10 + def self.down
  11 + drop_table :article_followers
  12 + end
  13 +end
db/migrate/20151210230319_add_followers_count_to_article.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +class AddFollowersCountToArticle < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :articles, :followers_count, :integer, :default => 0
  4 + execute "update articles set followers_count = (select count(*) from article_followers where article_followers.article_id = articles.id)"
  5 + end
  6 +
  7 + def self.down
  8 + remove_column :articles, :followers_count
  9 + end
  10 +end
db/migrate/20160202142247_add_timestamps_to_role_assignments.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddTimestampsToRoleAssignments < ActiveRecord::Migration
  2 + def change
  3 + add_timestamps :role_assignments
  4 + end
  5 +end
db/migrate/20160224132937_add_data_to_mailing.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddDataToMailing < ActiveRecord::Migration
  2 + def change
  3 + add_column :mailings, :data, :text
  4 + end
  5 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended that you check this file into your version control system. 12 # It's strongly recommended that you check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(version: 20151221105330) do 14 +ActiveRecord::Schema.define(version: 20160224132937) do
15 15
16 # These are extensions that must be enabled in order to support this database 16 # These are extensions that must be enabled in order to support this database
17 enable_extension "plpgsql" 17 enable_extension "plpgsql"
@@ -88,9 +88,9 @@ ActiveRecord::Schema.define(version: 20151221105330) do @@ -88,9 +88,9 @@ ActiveRecord::Schema.define(version: 20151221105330) do
88 t.integer "profile_id" 88 t.integer "profile_id"
89 end 89 end
90 90
91 - create_table "article_followers", force: :cascade do |t|  
92 - t.integer "person_id", null: false  
93 - t.integer "article_id", null: false 91 + create_table "article_followers", id: false, force: :cascade do |t|
  92 + t.integer "person_id"
  93 + t.integer "article_id"
94 t.datetime "since" 94 t.datetime "since"
95 t.datetime "created_at" 95 t.datetime "created_at"
96 t.datetime "updated_at" 96 t.datetime "updated_at"
@@ -699,6 +699,7 @@ ActiveRecord::Schema.define(version: 20151221105330) do @@ -699,6 +699,7 @@ ActiveRecord::Schema.define(version: 20151221105330) do
699 t.string "locale" 699 t.string "locale"
700 t.datetime "created_at" 700 t.datetime "created_at"
701 t.datetime "updated_at" 701 t.datetime "updated_at"
  702 + t.text "data"
702 end 703 end
703 704
704 create_table "mark_comment_as_read_plugin", force: :cascade do |t| 705 create_table "mark_comment_as_read_plugin", force: :cascade do |t|
@@ -1071,12 +1072,14 @@ ActiveRecord::Schema.define(version: 20151221105330) do @@ -1071,12 +1072,14 @@ ActiveRecord::Schema.define(version: 20151221105330) do
1071 end 1072 end
1072 1073
1073 create_table "role_assignments", force: :cascade do |t| 1074 create_table "role_assignments", force: :cascade do |t|
1074 - t.integer "accessor_id", null: false  
1075 - t.string "accessor_type"  
1076 - t.integer "resource_id"  
1077 - t.string "resource_type"  
1078 - t.integer "role_id", null: false  
1079 - t.boolean "is_global" 1075 + t.integer "accessor_id", null: false
  1076 + t.string "accessor_type"
  1077 + t.integer "resource_id"
  1078 + t.string "resource_type"
  1079 + t.integer "role_id", null: false
  1080 + t.boolean "is_global"
  1081 + t.datetime "created_at"
  1082 + t.datetime "updated_at"
1080 end 1083 end
1081 1084
1082 create_table "roles", force: :cascade do |t| 1085 create_table "roles", force: :cascade do |t|
debian/apache2/virtualhost.conf
@@ -8,6 +8,19 @@ DocumentRoot &quot;/usr/share/noosfero/public&quot; @@ -8,6 +8,19 @@ DocumentRoot &quot;/usr/share/noosfero/public&quot;
8 8
9 RewriteEngine On 9 RewriteEngine On
10 10
  11 +# If your XMPP XMPP/BOSH isn't in localhost, change the config below to correct
  12 +# point to address
  13 +RewriteRule /http-bind http://localhost:5280/http-bind [P,QSA,L]
  14 +<Proxy http://localhost:5280/http-bind>
  15 + Order Allow,Deny
  16 + Allow from All
  17 +</Proxy>
  18 +
  19 +# Pass access to private files to backend
  20 +RewriteMap private_files "dbm=sdbm:/usr/share/noosfero/cache/private_files"
  21 +RewriteCond ${private_files:$1|NOT_FOUND} !NOT_FOUND
  22 +RewriteRule ^(/articles/.*) ${private_files:$1} [P,QSA,L]
  23 +
11 # Rewrite index to check for static index.html 24 # Rewrite index to check for static index.html
12 RewriteRule ^/$ /index.html [QSA] 25 RewriteRule ^/$ /index.html [QSA]
13 26
debian/changelog
  1 +noosfero (1.4) jessie-test; urgency=medium
  2 +
  3 + * Noosfero 1.4
  4 +
  5 + -- Antonio Terceiro <terceiro@colivre.coop.br> Thu, 18 Feb 2016 16:20:23 -0200
  6 +
1 noosfero (1.4~rc3) jessie-test; urgency=medium 7 noosfero (1.4~rc3) jessie-test; urgency=medium
2 8
3 * Noosfero 1.4 RC3 9 * Noosfero 1.4 RC3
debian/dbinstall
@@ -5,8 +5,6 @@ set -e @@ -5,8 +5,6 @@ set -e
5 # dbconfig-common uses "pgsql", but we want "postgresql" 5 # dbconfig-common uses "pgsql", but we want "postgresql"
6 sed -i -e 's/adapter: pgsql/adapter: postgresql/' /etc/noosfero/database.yml 6 sed -i -e 's/adapter: pgsql/adapter: postgresql/' /etc/noosfero/database.yml
7 7
8 -/etc/init.d/noosfero setup  
9 -  
10 cd /usr/share/noosfero && su noosfero -c "rake db:schema:load RAILS_ENV=production" 8 cd /usr/share/noosfero && su noosfero -c "rake db:schema:load RAILS_ENV=production"
11 cd /usr/share/noosfero && su noosfero -c "rake db:migrate RAILS_ENV=production SCHEMA=/dev/null" 9 cd /usr/share/noosfero && su noosfero -c "rake db:migrate RAILS_ENV=production SCHEMA=/dev/null"
12 cd /usr/share/noosfero && su noosfero -c "rake db:data:minimal RAILS_ENV=production" 10 cd /usr/share/noosfero && su noosfero -c "rake db:data:minimal RAILS_ENV=production"
debian/dbupgrade
@@ -2,7 +2,5 @@ @@ -2,7 +2,5 @@
2 2
3 set -e 3 set -e
4 4
5 -/etc/init.d/noosfero setup  
6 -  
7 cd /usr/share/noosfero && su noosfero -c "rake db:migrate RAILS_ENV=production SCHEMA=/dev/null" 5 cd /usr/share/noosfero && su noosfero -c "rake db:migrate RAILS_ENV=production SCHEMA=/dev/null"
8 6
debian/noosfero.links
1 var/tmp/noosfero usr/share/noosfero/tmp 1 var/tmp/noosfero usr/share/noosfero/tmp
2 var/log/noosfero usr/share/noosfero/log 2 var/log/noosfero usr/share/noosfero/log
  3 +var/cache/noosfero usr/share/noosfero/cache
3 etc/noosfero/database.yml usr/share/noosfero/config/database.yml 4 etc/noosfero/database.yml usr/share/noosfero/config/database.yml
4 etc/noosfero/unicorn.rb usr/share/noosfero/config/unicorn.rb 5 etc/noosfero/unicorn.rb usr/share/noosfero/config/unicorn.rb
5 etc/noosfero/plugins usr/share/noosfero/config/plugins 6 etc/noosfero/plugins usr/share/noosfero/config/plugins
debian/noosfero.postinst
@@ -68,10 +68,17 @@ if [ ! -z &quot;$RET&quot; ]; then @@ -68,10 +68,17 @@ if [ ! -z &quot;$RET&quot; ]; then
68 export NOOSFERO_DOMAIN="$RET" 68 export NOOSFERO_DOMAIN="$RET"
69 fi 69 fi
70 70
  71 +/etc/init.d/noosfero setup
  72 +
71 # dbconfig-common magic 73 # dbconfig-common magic
72 . /usr/share/dbconfig-common/dpkg/postinst 74 . /usr/share/dbconfig-common/dpkg/postinst
73 dbc_go noosfero $@ 75 dbc_go noosfero $@
74 76
  77 +if [ ! -f /usr/share/noosfero/cache/private_files.pag ] && [ $1 = "configure" ] && [ -n $2 ]; then
  78 + echo "Creating private files dbm map..."
  79 + cd /usr/share/noosfero && su noosfero -c "rake cache:private_files RAILS_ENV=production"
  80 +fi
  81 +
75 # stop debconf to avoid the problem with infinite hanging, cfe 82 # stop debconf to avoid the problem with infinite hanging, cfe
76 # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=295477 83 # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=295477
77 db_stop 84 db_stop
debian/update-noosfero-apache
@@ -17,13 +17,13 @@ if test -x /usr/share/noosfero/script/apacheconf; then @@ -17,13 +17,13 @@ if test -x /usr/share/noosfero/script/apacheconf; then
17 if ! test -e "$apache_site"; then 17 if ! test -e "$apache_site"; then
18 echo "Generating apache virtual host ..." 18 echo "Generating apache virtual host ..."
19 cd /usr/share/noosfero && su noosfero -c "RAILS_ENV=production ./script/apacheconf virtualhosts" > "$apache_site" 19 cd /usr/share/noosfero && su noosfero -c "RAILS_ENV=production ./script/apacheconf virtualhosts" > "$apache_site"
20 - else  
21 - pattern="Include \/etc\/noosfero\/apache\/virtualhost.conf"  
22 - include="Include \/usr\/share\/noosfero\/util\/chat\/apache\/xmpp.conf"  
23 - if ! cat $apache_site | grep "^ *$include" > /dev/null ; then  
24 - echo "Updating apache virtual host ..."  
25 - sed -i "s/.*$pattern.*/ $include\n&/" $apache_site  
26 - fi 20 + fi
  21 +
  22 + # remove old way to include chat config
  23 + pattern="Include \/usr\/share\/noosfero\/util\/chat\/apache\/xmpp.conf"
  24 + if cat $apache_site | grep "^ *$pattern" > /dev/null ; then
  25 + echo "Removing obsolete chat configuration ..."
  26 + sed -i "/.*$pattern.*/d" $apache_site
27 fi 27 fi
28 28
29 echo 'Noosfero Apache configuration updated.' 29 echo 'Noosfero Apache configuration updated.'
etc/init.d/noosfero
@@ -86,6 +86,13 @@ do_setup() { @@ -86,6 +86,13 @@ do_setup() {
86 chmod 750 /var/tmp/noosfero 86 chmod 750 /var/tmp/noosfero
87 fi 87 fi
88 88
  89 + # Noosfero cache directory
  90 + if [ ! -d /var/cache/noosfero ]; then
  91 + mkdir /var/cache/noosfero
  92 + chown $NOOSFERO_USER:root /var/cache/noosfero
  93 + chmod 755 /var/cache/noosfero
  94 + fi
  95 +
89 # symlink the directories into Noosfero directory 96 # symlink the directories into Noosfero directory
90 if [ ! -e $NOOSFERO_DIR/tmp ]; then 97 if [ ! -e $NOOSFERO_DIR/tmp ]; then
91 ln -s /var/tmp/noosfero $NOOSFERO_DIR/tmp 98 ln -s /var/tmp/noosfero $NOOSFERO_DIR/tmp
@@ -96,6 +103,9 @@ do_setup() { @@ -96,6 +103,9 @@ do_setup() {
96 if [ ! -e $NOOSFERO_DIR/log ]; then 103 if [ ! -e $NOOSFERO_DIR/log ]; then
97 ln -s /var/log/noosfero $NOOSFERO_DIR/log 104 ln -s /var/log/noosfero $NOOSFERO_DIR/log
98 fi 105 fi
  106 + if [ ! -e $NOOSFERO_DIR/cache ]; then
  107 + ln -s /var/cache/noosfero $NOOSFERO_DIR/cache
  108 + fi
99 } 109 }
100 110
101 do_start() { 111 do_start() {
features/admin_categories.feature
@@ -45,7 +45,7 @@ Feature: manage categories @@ -45,7 +45,7 @@ Feature: manage categories
45 And I should see "Steak" 45 And I should see "Steak"
46 When I follow "Hide" 46 When I follow "Hide"
47 Then I should not see "Vegetarian" 47 Then I should not see "Vegetarian"
48 - And "Steak" should not be visible within "div" 48 + And I should not see "Steak"
49 49
50 @selenium 50 @selenium
51 Scenario: the show link is available just for categories with category tree 51 Scenario: the show link is available just for categories with category tree
features/categories_block.feature
@@ -44,6 +44,7 @@ Feature: categories_block @@ -44,6 +44,7 @@ Feature: categories_block
44 And I follow "Edit" within ".block-outer .categories-block" 44 And I follow "Edit" within ".block-outer .categories-block"
45 And I check "Product" 45 And I check "Product"
46 And I press "Save" 46 And I press "Save"
  47 + And I go to /
47 Then I should see "Food" 48 Then I should see "Food"
48 And I should see "Book" 49 And I should see "Book"
49 And "Vegetarian" should not be visible within "span#category-name" 50 And "Vegetarian" should not be visible within "span#category-name"
@@ -62,6 +63,7 @@ Feature: categories_block @@ -62,6 +63,7 @@ Feature: categories_block
62 And I follow "Edit" within ".block-outer .categories-block" 63 And I follow "Edit" within ".block-outer .categories-block"
63 And I check "Product" 64 And I check "Product"
64 And I press "Save" 65 And I press "Save"
  66 + And I go to /
65 Then I should see "Book" 67 Then I should see "Book"
66 And "Literature" should not be visible within "span#category-name" 68 And "Literature" should not be visible within "span#category-name"
67 When I follow "block_2_category_2" 69 When I follow "block_2_category_2"
features/comment.feature
@@ -96,4 +96,4 @@ Feature: comment @@ -96,4 +96,4 @@ Feature: comment
96 Scenario: hide post a comment button when clicked 96 Scenario: hide post a comment button when clicked
97 Given I am on /booking/article-to-comment 97 Given I am on /booking/article-to-comment
98 And I follow "Post a comment" 98 And I follow "Post a comment"
99 - Then "Post a comment" should not be visible within "#article" 99 + Then "Post comment" should not be visible within "#article"
features/manage_categories.feature
@@ -27,5 +27,7 @@ Feature: manage categories @@ -27,5 +27,7 @@ Feature: manage categories
27 Then I should not see "Beans" 27 Then I should not see "Beans"
28 And I should not see "Potatoes" 28 And I should not see "Potatoes"
29 When I follow "Show" 29 When I follow "Show"
  30 + And I wait 0.5 seconds for Services show animation to finish
  31 + And I follow "Show"
30 Then I should see "Beans" 32 Then I should see "Beans"
31 And I should see "Potatoes" 33 And I should see "Potatoes"
features/manage_users.feature
@@ -15,7 +15,7 @@ Background: @@ -15,7 +15,7 @@ Background:
15 Scenario: deactive user 15 Scenario: deactive user
16 Given I follow "Deactivate user" within "tr[title='Joao Silva']" 16 Given I follow "Deactivate user" within "tr[title='Joao Silva']"
17 When I confirm the browser dialog 17 When I confirm the browser dialog
18 - Then the "tr[title='Joao Silva'] td.actions a.icon-activate-user" button should be enabled 18 + Then the field "tr[title='Joao Silva'] td.actions a.icon-activate-user" should be enabled
19 19
20 @selenium 20 @selenium
21 Scenario: activate user 21 Scenario: activate user
@@ -23,7 +23,7 @@ Background: @@ -23,7 +23,7 @@ Background:
23 And I confirm the browser dialog 23 And I confirm the browser dialog
24 And I follow "Activate user" within "tr[title='Paulo Santos']" 24 And I follow "Activate user" within "tr[title='Paulo Santos']"
25 When I confirm the browser dialog 25 When I confirm the browser dialog
26 - Then the "tr[title='Paulo Santos'] td.actions a.icon-deactivate-user" button should be enabled 26 + Then the field "tr[title='Paulo Santos'] td.actions a.icon-deactivate-user" should be enabled
27 27
28 @selenium 28 @selenium
29 Scenario: remove user 29 Scenario: remove user
@@ -36,7 +36,7 @@ Background: @@ -36,7 +36,7 @@ Background:
36 Scenario: admin user 36 Scenario: admin user
37 Given I follow "Set admin role" within "tr[title='Joao Silva']" 37 Given I follow "Set admin role" within "tr[title='Joao Silva']"
38 When I confirm the browser dialog 38 When I confirm the browser dialog
39 - Then the "tr[title='Joao Silva'] td.actions a.icon-reset-admin-role" button should be enabled 39 + Then the field "tr[title='Joao Silva'] td.actions a.icon-reset-admin-role" should be enabled
40 40
41 @selenium 41 @selenium
42 Scenario: unadmin user 42 Scenario: unadmin user
@@ -44,4 +44,4 @@ Background: @@ -44,4 +44,4 @@ Background:
44 And I confirm the browser dialog 44 And I confirm the browser dialog
45 And I follow "Reset admin role" within "tr[title='Paulo Santos']" 45 And I follow "Reset admin role" within "tr[title='Paulo Santos']"
46 When I confirm the browser dialog 46 When I confirm the browser dialog
47 - Then the "tr[title='Paulo Santos'] td.actions a.icon-set-admin-role" button should be enabled 47 + Then the field "tr[title='Paulo Santos'] td.actions a.icon-set-admin-role" should be enabled
features/secret_community.feature
@@ -17,6 +17,7 @@ Feature: Use a secret community @@ -17,6 +17,7 @@ Feature: Use a secret community
17 And I check "Secret" 17 And I check "Secret"
18 And I press "Save" 18 And I press "Save"
19 And I follow "Logout" 19 And I follow "Logout"
  20 + And I go to /account/login
20 21
21 @selenium 22 @selenium
22 Scenario: Hide privacity options when secret is checked 23 Scenario: Hide privacity options when secret is checked
features/send_email_to_organization_members.feature
@@ -31,7 +31,8 @@ Feature: send emails to organization members @@ -31,7 +31,8 @@ Feature: send emails to organization members
31 Scenario: Send e-mail to members 31 Scenario: Send e-mail to members
32 Given I am logged in as "joaosilva" 32 Given I am logged in as "joaosilva"
33 And I go to Sample Community's members management 33 And I go to Sample Community's members management
34 - And I follow "Send e-mail to members" 34 + And I check "checkbox-manoel"
  35 + And I press "Send e-mail to members"
35 And I fill in "Subject" with "Hello, member!" 36 And I fill in "Subject" with "Hello, member!"
36 And I fill in "Body" with "We have some news" 37 And I fill in "Body" with "We have some news"
37 When I press "Send" 38 When I press "Send"
@@ -40,7 +41,8 @@ Feature: send emails to organization members @@ -40,7 +41,8 @@ Feature: send emails to organization members
40 Scenario: Not send e-mail to members if subject is blank 41 Scenario: Not send e-mail to members if subject is blank
41 Given I am logged in as "joaosilva" 42 Given I am logged in as "joaosilva"
42 And I go to Sample Community's members management 43 And I go to Sample Community's members management
43 - And I follow "Send e-mail to members" 44 + And I check "checkbox-manoel"
  45 + And I press "Send e-mail to members"
44 And I fill in "Body" with "We have some news" 46 And I fill in "Body" with "We have some news"
45 When I press "Send" 47 When I press "Send"
46 Then I should be on /profile/sample-community/send_mail 48 Then I should be on /profile/sample-community/send_mail
@@ -48,7 +50,8 @@ Feature: send emails to organization members @@ -48,7 +50,8 @@ Feature: send emails to organization members
48 Scenario: Not send e-mail to members if body is blank 50 Scenario: Not send e-mail to members if body is blank
49 Given I am logged in as "joaosilva" 51 Given I am logged in as "joaosilva"
50 And I go to Sample Community's members management 52 And I go to Sample Community's members management
51 - And I follow "Send e-mail to members" 53 + And I check "checkbox-manoel"
  54 + And I press "Send e-mail to members"
52 And I fill in "Subject" with "Hello, user!" 55 And I fill in "Subject" with "Hello, user!"
53 When I press "Send" 56 When I press "Send"
54 Then I should be on /profile/sample-community/send_mail 57 Then I should be on /profile/sample-community/send_mail
@@ -56,7 +59,8 @@ Feature: send emails to organization members @@ -56,7 +59,8 @@ Feature: send emails to organization members
56 Scenario: Cancel creation of mailing 59 Scenario: Cancel creation of mailing
57 Given I am logged in as "joaosilva" 60 Given I am logged in as "joaosilva"
58 And I go to Sample Community's members management 61 And I go to Sample Community's members management
59 - And I follow "Send e-mail to members" 62 + And I check "checkbox-manoel"
  63 + And I press "Send e-mail to members"
60 When I follow "Cancel e-mail" 64 When I follow "Cancel e-mail"
61 Then I should be on Sample Community's members management 65 Then I should be on Sample Community's members management
62 66
features/step_definitions/custom_web_steps.rb
1 Then /^"([^"]*)" should not be visible within "([^"]*)"$/ do |text, selector| 1 Then /^"([^"]*)" should not be visible within "([^"]*)"$/ do |text, selector|
2 - if page.has_content?(text)  
3 - page.should have_no_css(selector, :text => text, :visible => false)  
4 - end 2 + page.should have_no_css selector, text: text, visible: false
5 end 3 end
6 4
7 Then /^"([^"]*)" should be visible within "([^"]*)"$/ do |text, selector| 5 Then /^"([^"]*)" should be visible within "([^"]*)"$/ do |text, selector|
8 - if page.has_content?(text)  
9 - page.should have_css(selector, :text => text, :visible => false)  
10 - end 6 + page.should have_css selector, text: text, visible: false
11 end 7 end
12 8
13 Then /^I should see "([^"]*)" link$/ do |text| 9 Then /^I should see "([^"]*)" link$/ do |text|
@@ -22,14 +18,14 @@ When /^I should see &quot;([^\&quot;]+)&quot; linking to &quot;([^\&quot;]+)&quot;$/ do |text, href| @@ -22,14 +18,14 @@ When /^I should see &quot;([^\&quot;]+)&quot; linking to &quot;([^\&quot;]+)&quot;$/ do |text, href|
22 page.should have_xpath("//a[@href='#{href}']") 18 page.should have_xpath("//a[@href='#{href}']")
23 end 19 end
24 20
25 -Then /^the "([^"]*)" button should be disabled$/ do |selector|  
26 - field = find(selector)  
27 - field['disabled'].should be_truthy  
28 -end 21 +Then /^the field "([^"]*)" should be (enabled|disabled)$/ do |selector, status|
  22 + field = page.find(:css, selector)
29 23
30 -Then /^the "([^"]*)" button should be enabled$/ do |selector|  
31 - field = find(selector)  
32 - field['disabled'].should_not be_truthy 24 + if status == 'enabled'
  25 + field.disabled?.should_not be_truthy
  26 + else
  27 + field.disabled?.should be_truthy
  28 + end
33 end 29 end
34 30
35 When /^I reload and wait for the page$/ do 31 When /^I reload and wait for the page$/ do
features/step_definitions/web_steps.rb
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 7
8 require 'uri' 8 require 'uri'
9 require 'cgi' 9 require 'cgi'
10 -require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths")) 10 +require_relative '../support/paths'
11 11
12 module WithinHelpers 12 module WithinHelpers
13 def with_scope(locator) 13 def with_scope(locator)
@@ -39,37 +39,15 @@ end @@ -39,37 +39,15 @@ end
39 39
40 When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector| 40 When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector|
41 with_scope(selector) do 41 with_scope(selector) do
42 - begin  
43 - click_link(link, :match => :prefer_exact)  
44 - rescue Selenium::WebDriver::Error::UnknownError => selenium_error  
45 - if selenium_error.message.start_with? 'Element is not clickable at point'  
46 - link = find_link(link)  
47 - href = link[:href]  
48 - onclick = link[:onClick]  
49 -  
50 - warn "#{selenium_error.message}\n\n"\  
51 - "Trying to overcome this by:\n"  
52 -  
53 - onclick_return = true  
54 -  
55 - unless onclick.nil?  
56 - warn "\t* Running onClick JS:\n"\  
57 - "\t\t'#{onclick}'\n"  
58 - onclick_return = page.execute_script onclick  
59 - end  
60 -  
61 - if onclick_return  
62 - warn "\t* Redirecting you to the link's href:\n"\  
63 - "\t\t'#{href}'\n"  
64 -  
65 - visit href  
66 - end  
67 -  
68 - warn "\nGood luck and be careful that this may produce hidden links to work on tests!\n"  
69 - else  
70 - raise selenium_error  
71 - end 42 + link = find :link_or_button, link, match: :prefer_exact
  43 + # If the link has child elements, then $(link).click() has no effect,
  44 + # so find the first child and click on it.
  45 + if Capybara.default_driver == :selenium
  46 + target = link.all('*').first || link
  47 + else
  48 + target = link
72 end 49 end
  50 + target.click
73 end 51 end
74 end 52 end
75 53
features/support/debug.rb
@@ -21,3 +21,8 @@ Before do |scenario| @@ -21,3 +21,8 @@ Before do |scenario|
21 puts "Can't find debugger or pry to debug" 21 puts "Can't find debugger or pry to debug"
22 end 22 end
23 end 23 end
  24 +
  25 +Then /^I open pry$/ do
  26 + require'pry';binding.pry
  27 +end
  28 +
features/support/env.rb
@@ -65,5 +65,13 @@ Before do @@ -65,5 +65,13 @@ Before do
65 fixtures_folder = Rails.root.join('test', 'fixtures') 65 fixtures_folder = Rails.root.join('test', 'fixtures')
66 fixtures = ['environments', 'roles'] 66 fixtures = ['environments', 'roles']
67 ActiveRecord::Fixtures.create_fixtures(fixtures_folder, fixtures) 67 ActiveRecord::Fixtures.create_fixtures(fixtures_folder, fixtures)
  68 +
  69 + # The same browser session is used across tests, so expire caching
  70 + # can create changes from scenario to another.
  71 + e=Environment.default
  72 + e.home_cache_in_minutes = 0
  73 + e.general_cache_in_minutes = 0
  74 + e.profile_cache_in_minutes = 0
  75 + e.save
68 end 76 end
69 77
gitignore.example
@@ -22,6 +22,7 @@ public/thumbnails @@ -22,6 +22,7 @@ public/thumbnails
22 public/user_themes 22 public/user_themes
23 public/designs/themes/default 23 public/designs/themes/default
24 public/designs/icons/default 24 public/designs/icons/default
  25 +cache
25 26
26 public/assets 27 public/assets
27 .sass-cache 28 .sass-cache
lib/file_presenter.rb
@@ -52,8 +52,8 @@ class FilePresenter @@ -52,8 +52,8 @@ class FilePresenter
52 nil 52 nil
53 end 53 end
54 54
55 - def download?(view=nil)  
56 - false 55 + def download? view = nil
  56 + view.blank?
57 end 57 end
58 58
59 def short_description 59 def short_description
lib/noosfero/api/v1/articles.rb
@@ -165,6 +165,37 @@ module Noosfero @@ -165,6 +165,37 @@ module Noosfero
165 end 165 end
166 end 166 end
167 167
  168 + desc "Returns the total followers for the article" do
  169 + detail 'Get the followers of a specific article by id'
  170 + failure [[403, 'Forbidden']]
  171 + named 'ArticleFollowers'
  172 + end
  173 + get ':id/followers' do
  174 + article = find_article(environment.articles, params[:id])
  175 + total = article.person_followers.count
  176 + {:total_followers => total}
  177 + end
  178 +
  179 + desc "Add a follower for the article" do
  180 + detail 'Add the current user identified by private token, like a follower of a article'
  181 + params Noosfero::API::Entities::UserLogin.documentation
  182 + failure [[401, 'Unauthorized']]
  183 + named 'ArticleFollow'
  184 + end
  185 + post ':id/follow' do
  186 + authenticate!
  187 + article = find_article(environment.articles, params[:id])
  188 + if article.article_followers.exists?(:person_id => current_person.id)
  189 + {:success => false, :already_follow => true}
  190 + else
  191 + article_follower = ArticleFollower.new
  192 + article_follower.article = article
  193 + article_follower.person = current_person
  194 + article_follower.save!
  195 + {:success => true}
  196 + end
  197 + end
  198 +
168 desc 'Return the children of a article identified by id' do 199 desc 'Return the children of a article identified by id' do
169 detail 'Get all children articles of a specific article' 200 detail 'Get all children articles of a specific article'
170 params Noosfero::API::Entities::Article.documentation 201 params Noosfero::API::Entities::Article.documentation
lib/noosfero/version.rb
1 module Noosfero 1 module Noosfero
2 PROJECT = 'noosfero' 2 PROJECT = 'noosfero'
3 - VERSION = '1.4~rc3' 3 + VERSION = '1.4'
4 end 4 end
5 5
6 root = File.expand_path(File.dirname(__FILE__) + '/../..') 6 root = File.expand_path(File.dirname(__FILE__) + '/../..')
lib/noosfero/vote_ext.rb
@@ -2,10 +2,10 @@ require_dependency &#39;models/vote&#39; @@ -2,10 +2,10 @@ require_dependency &#39;models/vote&#39;
2 2
3 class Vote 3 class Vote
4 4
5 - validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id], :if => :allow_duplicated_vote? 5 + validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id], :unless => :allow_duplicate?
6 6
7 - def allow_duplicated_vote?  
8 - voter.present? 7 + def allow_duplicate?
  8 + voter.blank?
9 end 9 end
10 10
11 validate :verify_target_archived 11 validate :verify_target_archived
lib/tasks/cache.rake 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +namespace :cache do
  2 + task :private_files => :environment do
  3 + require 'sdbm'
  4 +
  5 + hash = {}
  6 + UploadedFile.where(:published => false).find_each do |uploaded_file|
  7 + hash[uploaded_file.public_filename] = uploaded_file.full_path
  8 + end
  9 +
  10 + dbm = SDBM.open(UploadedFile::DBM_PRIVATE_FILE)
  11 + dbm.update(hash)
  12 + dbm.close
  13 + end
  14 +end
plugins/oauth_client/lib/ext/profile.rb
1 require_dependency 'profile' 1 require_dependency 'profile'
2 2
3 -Profile.descendants.each do |subclass|  
4 - subclass.class_eval do 3 +class Profile
5 4
6 - has_many :oauth_auths, foreign_key: :profile_id, class_name: 'OauthClientPlugin::Auth', dependent: :destroy  
7 - has_many :oauth_providers, through: :oauth_auths, source: :provider 5 + has_many :oauth_auths, foreign_key: :profile_id, class_name: 'OauthClientPlugin::Auth', dependent: :destroy
  6 + has_many :oauth_providers, through: :oauth_auths, source: :provider
8 7
9 - end  
10 end 8 end
plugins/organization_ratings/features/rate_community.feature
@@ -33,4 +33,4 @@ Feature: rate_community @@ -33,4 +33,4 @@ Feature: rate_community
33 Given I am on mycommunity's homepage 33 Given I am on mycommunity's homepage
34 When I follow "Rate this Community" 34 When I follow "Rate this Community"
35 Then I should see "Joao Silva" within ".star-profile-name" 35 Then I should see "Joao Silva" within ".star-profile-name"
36 - And I should see Joao Silva's profile image  
37 \ No newline at end of file 36 \ No newline at end of file
  37 + And I should see Joao Silva's profile image
plugins/organization_ratings/features/vote_once_disable_cooldown.feature 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +Feature: vote_once_disable_cooldown
  2 + As a admin
  3 + I want to disable the cooldown time when vote once is enabled
  4 + Making it clearly that there is no cooldown when vote once is enabled
  5 +
  6 + Background:
  7 + Given plugin "OrganizationRatings" is enabled on environment
  8 + And I am logged in as admin
  9 + And I go to /admin/plugins
  10 + And I check "Organization Ratings"
  11 + And I press "Save changes"
  12 +
  13 + @selenium
  14 + Scenario: disable or enable the cooldown field when vote on is checked or unchecked
  15 + Given I follow "Administration"
  16 + And I follow "Plugins"
  17 + And I follow "Configuration"
  18 + And the field "#organization_ratings_config_cooldown" should be enabled
  19 + And I check "Vote once"
  20 + And the field "#organization_ratings_config_cooldown" should be disabled
  21 + And I uncheck "Vote once"
  22 + Then the field "#organization_ratings_config_cooldown" should be enabled
  23 +
plugins/organization_ratings/lib/organization_ratings_plugin.rb
@@ -73,8 +73,8 @@ class OrganizationRatingsPlugin &lt; Noosfero::Plugin @@ -73,8 +73,8 @@ class OrganizationRatingsPlugin &lt; Noosfero::Plugin
73 73
74 def js_files 74 def js_files
75 %w( 75 %w(
76 - public/rate.js  
77 - public/organization_rating_management.js 76 + rate.js
  77 + organization_rating_management.js
78 ) 78 )
79 end 79 end
80 80
plugins/organization_ratings/public/organization_rating_management.js
@@ -9,8 +9,8 @@ @@ -9,8 +9,8 @@
9 9
10 10
11 cacheDom: function() { 11 cacheDom: function() {
12 - this.$vote_once_checkbox = $("#environment_organization_ratings_vote_once");  
13 - this.$hours_timer_input = $("#environment_organization_ratings_cooldown"); 12 + this.$vote_once_checkbox = $("#organization_ratings_config_vote_once");
  13 + this.$hours_timer_input = $("#organization_ratings_config_cooldown");
14 }, 14 },
15 15
16 16
@@ -21,10 +21,22 @@ @@ -21,10 +21,22 @@
21 21
22 verifyHoursTimerDisable: function() { 22 verifyHoursTimerDisable: function() {
23 if (this.$vote_once_checkbox.is(":checked")) { 23 if (this.$vote_once_checkbox.is(":checked")) {
24 - this.$hours_timer_input.attr("disabled", "disabled"); 24 + //this.$hours_timer_input.attr("disabled", "disabled");
  25 + this.disableVoteOnce();
25 } else { 26 } else {
26 - this.$hours_timer_input.removeAttr("disabled"); 27 + //this.$hours_timer_input.removeAttr("disabled");
  28 + this.enableVoteOnce();
27 } 29 }
  30 + },
  31 +
  32 +
  33 + enableVoteOnce: function() {
  34 + this.$hours_timer_input.removeAttr("disabled");
  35 + },
  36 +
  37 +
  38 + disableVoteOnce: function() {
  39 + this.$hours_timer_input.attr("disabled", "disabled");
28 } 40 }
29 } 41 }
30 42
plugins/organization_ratings/public/style.css
@@ -14,11 +14,11 @@ @@ -14,11 +14,11 @@
14 } 14 }
15 15
16 .star-negative { 16 .star-negative {
17 - background-image: url('public/images/star-negative.png'); 17 + background-image: url('images/star-negative.png');
18 } 18 }
19 19
20 .star-positive { 20 .star-positive {
21 - background-image: url('public/images/star-positive.png'); 21 + background-image: url('images/star-positive.png');
22 } 22 }
23 23
24 .small-star-negative, .small-star-positive { 24 .small-star-negative, .small-star-positive {
@@ -31,11 +31,11 @@ @@ -31,11 +31,11 @@
31 } 31 }
32 32
33 .small-star-negative { 33 .small-star-negative {
34 - background-image: url('public/images/small-star-negative.png'); 34 + background-image: url('images/small-star-negative.png');
35 } 35 }
36 36
37 .small-star-positive { 37 .small-star-positive {
38 - background-image: url('public/images/small-star-positive.png'); 38 + background-image: url('images/small-star-positive.png');
39 } 39 }
40 40
41 .medium-star-negative, .medium-star-positive { 41 .medium-star-negative, .medium-star-positive {
@@ -48,11 +48,11 @@ @@ -48,11 +48,11 @@
48 } 48 }
49 49
50 .medium-star-positive { 50 .medium-star-positive {
51 - background-image: url('public/images/star-positive-medium.png'); 51 + background-image: url('images/star-positive-medium.png');
52 } 52 }
53 53
54 .medium-star-negative { 54 .medium-star-negative {
55 - background-image: url('public/images/star-negative-medium.png'); 55 + background-image: url('images/star-negative-medium.png');
56 } 56 }
57 57
58 .star-hide { 58 .star-hide {
plugins/people_block/lib/ext/person.rb
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -require_dependency 'person'  
2 -  
3 -class Person  
4 -  
5 - scope :with_role, -> role_id {  
6 - joins(:role_assignments).  
7 - where("role_assignments.role_id = #{role_id}")  
8 - }  
9 -  
10 -end  
plugins/people_block/test/unit/members_block_test.rb
@@ -280,6 +280,21 @@ class MembersBlockTest &lt; ActionView::TestCase @@ -280,6 +280,21 @@ class MembersBlockTest &lt; ActionView::TestCase
280 assert_includes block.roles, Profile::Roles.moderator(owner.environment.id) 280 assert_includes block.roles, Profile::Roles.moderator(owner.environment.id)
281 end 281 end
282 282
  283 + should 'count number of profiles by role' do
  284 + owner = fast_create(Community)
  285 + profile1 = fast_create(Person, {:public_profile => true})
  286 + profile2 = fast_create(Person, {:public_profile => true})
  287 +
  288 + owner.add_member profile2
  289 + owner.add_moderator profile1
  290 +
  291 + block = MembersBlock.new
  292 + block.visible_role = Profile::Roles.moderator(owner.environment.id).key
  293 + block.expects(:owner).returns(owner).at_least_once
  294 +
  295 + assert_equivalent [profile1], block.profile_list
  296 + end
  297 +
283 protected 298 protected
284 include NoosferoTestHelper 299 include NoosferoTestHelper
285 300
plugins/pg_search/test/unit/pg_search_plugin_test.rb
@@ -25,7 +25,8 @@ class PgSearchPluginTest &lt; ActiveSupport::TestCase @@ -25,7 +25,8 @@ class PgSearchPluginTest &lt; ActiveSupport::TestCase
25 profile1 = fast_create(Profile, :identifier => 'profile1', :name => 'debugger') 25 profile1 = fast_create(Profile, :identifier => 'profile1', :name => 'debugger')
26 profile2 = fast_create(Profile, :identifier => 'profile2', :name => 'profile admin debugger') 26 profile2 = fast_create(Profile, :identifier => 'profile2', :name => 'profile admin debugger')
27 profile3 = fast_create(Profile, :identifier => 'profile3', :name => 'admin debugger') 27 profile3 = fast_create(Profile, :identifier => 'profile3', :name => 'admin debugger')
28 - assert_equal [profile2, profile3, profile1], search(Profile, 'profile admin deb') 28 + profile4 = fast_create(Profile, :identifier => 'profile4', :name => 'simple user')
  29 + assert_equal [profile2, profile3, profile1, profile4], search(Profile, 'profile admin deb')
29 end 30 end
30 31
31 should 'locate profile escaping special characters' do 32 should 'locate profile escaping special characters' do
plugins/site_tour/lib/ext/person.rb
1 -class Person 1 +require_dependency 'person'
2 2
  3 +class Person
3 settings_items :site_tour_plugin_actions, :type => Array, :default => [] 4 settings_items :site_tour_plugin_actions, :type => Array, :default => []
4 -  
5 end 5 end
plugins/stoa/test/functional/account_controller_test.rb
@@ -15,6 +15,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -15,6 +15,7 @@ class AccountControllerTest &lt; ActionController::TestCase
15 t.date "dtanas" 15 t.date "dtanas"
16 end 16 end
17 ActiveRecord::Base.establish_connection(:test) 17 ActiveRecord::Base.establish_connection(:test)
  18 + StoaPlugin::UspUser.reset_column_information
18 19
19 def setup 20 def setup
20 @controller = AccountController.new 21 @controller = AccountController.new
plugins/sub_organizations/views/sub_organizations_plugin_profile/_full_related_organizations.html.erb
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 <%= profile_image_link organization, :big, 'div' %> 10 <%= profile_image_link organization, :big, 'div' %>
11 </div> 11 </div>
12 <div class="related-organizations-item-column-right"> 12 <div class="related-organizations-item-column-right">
13 - <%= link_to_homepage(organization.name, organization.identifier, :class => "search-result-title") %> 13 + <%= link_to_homepage(organization.name, organization, :class => "search-result-title") %>
14 <div class="related-organizations-description"> 14 <div class="related-organizations-description">
15 <% if organization.description %> 15 <% if organization.description %>
16 <% body_stripped = strip_tags(organization.description) %> 16 <% body_stripped = strip_tags(organization.description) %>
plugins/video/lib/video_plugin.rb
@@ -33,10 +33,14 @@ class VideoPlugin &lt; Noosfero::Plugin @@ -33,10 +33,14 @@ class VideoPlugin &lt; Noosfero::Plugin
33 end 33 end
34 34
35 def article_extra_toolbar_buttons(content) 35 def article_extra_toolbar_buttons(content)
36 - if content.kind_of?(VideoPlugin::VideoGallery)  
37 - url = url_for(:action => 'new', :type=>'VideoPlugin::Video', :controller=>'cms', :parent_id => content.id)  
38 - {:title => _('New Video'), :url => url, :icon => 'button with-text icon-new'}  
39 - end 36 + return [] if !content.kind_of?(VideoPlugin::VideoGallery)
  37 + {
  38 + :id=>"new-video-btn",
  39 + :class=>"button with-text icon-new",
  40 + :url=> {:action => 'new', :type=>'VideoPlugin::Video', :controller=>'cms', :parent_id => content.id},
  41 + :title=>_("New Video"),
  42 + :icon => :new
  43 + }
40 end 44 end
41 45
42 end 46 end
plugins/video/views/content_viewer/video_plugin/_video_gallery.html.erb
@@ -11,4 +11,4 @@ @@ -11,4 +11,4 @@
11 <em><%= _('(empty video gallery)') %></em> 11 <em><%= _('(empty video gallery)') %></em>
12 <% else %> 12 <% else %>
13 <%= list_videos(:contents=>video_gallery.children) %> 13 <%= list_videos(:contents=>video_gallery.children) %>
14 -<% end %>  
15 \ No newline at end of file 14 \ No newline at end of file
  15 +<% end %>
public/designs/themes/noosfero/style.css
@@ -48,3 +48,9 @@ @@ -48,3 +48,9 @@
48 width: 80px; 48 width: 80px;
49 } 49 }
50 50
  51 +.action-profile-send_mail .send-mail-recipients {
  52 + color: #888888;
  53 + padding: 10px;
  54 + width: 475px;
  55 + line-height: 15px;
  56 +}
public/javascripts/comment_order.js
@@ -10,10 +10,9 @@ function send_order(order, url) { @@ -10,10 +10,9 @@ function send_order(order, url) {
10 }); 10 });
11 } 11 }
12 12
13 -  
14 jQuery(document).ready(function(){ 13 jQuery(document).ready(function(){
15 jQuery("#comment_order").change(function(){ 14 jQuery("#comment_order").change(function(){
16 - var url = jQuery("#page_url").val(); 15 + var url = window.location.href;
17 send_order(this.value, url); 16 send_order(this.value, url);
18 }); 17 });
19 -});  
20 \ No newline at end of file 18 \ No newline at end of file
  19 +});
public/javascripts/profile_members.js 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +(function($) {
  2 +
  3 + //Autocomplete to list members
  4 + $('#filter-name-autocomplete').autocomplete({
  5 + minLength:2,
  6 + source:function(request,response){
  7 + $.ajax({
  8 + url:document.location.pathname+'/search_members',
  9 + dataType:'json',
  10 + data:{
  11 + filter_name:request.term
  12 + },
  13 + success:response
  14 + });
  15 + }
  16 + });
  17 +})(jQuery);
  18 +
  19 +
  20 +function toggle(source) {
  21 + checkboxes = document.getElementsByName('members_filtered[]');
  22 + for(var i=0, n=checkboxes.length;i<n;i++) {
  23 + checkboxes[i].checked = source.checked;
  24 + }
  25 +}
public/stylesheets/profile-list.scss
@@ -207,3 +207,23 @@ @@ -207,3 +207,23 @@
207 height: auto; 207 height: auto;
208 font-size: 12px; 208 font-size: 12px;
209 } 209 }
  210 +.action-profile-members .profile_link{
  211 + position: relative;
  212 +}
  213 +.action-profile-members .profile_link span.new-profile:last-child{
  214 + position: absolute;
  215 + top: 3px;
  216 + right: 2px;
  217 + text-transform: uppercase;
  218 + color: #FFF;
  219 + font-size: 9px;
  220 + background: #66CC33;
  221 + padding: 2px;
  222 + display: block;
  223 + width: 35px;
  224 + font-weight: 700;
  225 +}
  226 +.action-profile-members .profile_link .fn{
  227 + font-style: normal;
  228 + color: #000;
  229 +}
script/apacheconf
@@ -17,7 +17,6 @@ when &#39;virtualhosts&#39; @@ -17,7 +17,6 @@ when &#39;virtualhosts&#39;
17 puts " #{server_directive} #{domain.name}" 17 puts " #{server_directive} #{domain.name}"
18 server_directive = 'ServerAlias' 18 server_directive = 'ServerAlias'
19 end 19 end
20 - puts " Include /usr/share/noosfero/util/chat/apache/xmpp.conf"  
21 puts " Include /etc/noosfero/apache/virtualhost.conf" 20 puts " Include /etc/noosfero/apache/virtualhost.conf"
22 puts "</VirtualHost>" 21 puts "</VirtualHost>"
23 end 22 end