Commit 4d9daa44dbf61490640b32a8fb9f6f49f0f8b152
Exists in
staging
and in
1 other branch
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.
.travis.yml
@@ -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 |
RELEASING.md
@@ -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 < ApplicationController | @@ -198,7 +198,7 @@ class AccountController < 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 < ApplicationController | @@ -68,11 +68,7 @@ class ContentViewerController < 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 < ApplicationController | @@ -209,8 +205,6 @@ class ContentViewerController < 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 < ApplicationController | @@ -218,7 +212,12 @@ class ContentViewerController < 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 < ApplicationController | @@ -244,8 +243,12 @@ class ContentViewerController < 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 < ApplicationController | @@ -276,8 +279,12 @@ class ContentViewerController < 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 < PublicController | @@ -155,6 +155,18 @@ class ProfileController < 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 < PublicController | @@ -362,6 +374,7 @@ class ProfileController < 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 'mailing_job' | @@ -2,7 +2,10 @@ require_dependency 'mailing_job' | ||
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 < Mailing | @@ -5,9 +5,17 @@ class OrganizationMailing < 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 < ActiveRecord::Base | @@ -8,8 +8,9 @@ class Article < 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 < ActiveRecord::Base | @@ -83,6 +84,10 @@ class Article < 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 < ActiveRecord::Base | @@ -95,7 +100,6 @@ class Article < 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 < ActiveRecord::Base | @@ -173,7 +177,6 @@ class Article < 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 < ActiveRecord::Base | @@ -374,6 +377,10 @@ class Article < 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 < ActiveRecord::Base | @@ -383,6 +390,10 @@ class Article < 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 < ActiveRecord::Base | @@ -408,13 +419,19 @@ class Article < 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 < ActiveRecord::Base | @@ -195,8 +195,8 @@ class Block < 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 < ActiveRecord::Base | @@ -6,13 +6,14 @@ class Comment < 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 < ActiveRecord::Base | @@ -102,10 +103,9 @@ class Comment < 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 < ActiveRecord::Base | @@ -147,7 +147,7 @@ class Comment < 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
app/models/environment.rb
@@ -56,6 +56,7 @@ class Environment < ActiveRecord::Base | @@ -56,6 +56,7 @@ class Environment < 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 < Block | @@ -15,6 +15,8 @@ class HighlightsBlock < 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 < Profile | @@ -19,26 +16,29 @@ class Person < 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 < Profile | @@ -51,8 +51,7 @@ class Person < 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 < Profile | @@ -90,7 +89,8 @@ class Person < 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 < Profile | @@ -123,10 +123,10 @@ class Person < 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 < Profile | @@ -135,6 +135,11 @@ class Person < 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 < ActiveRecord::Base | @@ -78,6 +78,9 @@ class Profile < 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 < ActiveRecord::Base | @@ -119,7 +122,7 @@ class Profile < 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 < ActiveRecord::Base | @@ -185,15 +188,23 @@ class Profile < 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
app/models/rss_feed.rb
@@ -65,6 +65,10 @@ class RssFeed < Article | @@ -65,6 +65,10 @@ class RssFeed < 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 < Article | @@ -10,6 +13,19 @@ class UploadedFile < 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 < Article | @@ -106,10 +122,13 @@ class UploadedFile < 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
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
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/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] %> |
@@ -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 |
@@ -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
db/schema.rb
@@ -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 "/usr/share/noosfero/public" | @@ -8,6 +8,19 @@ DocumentRoot "/usr/share/noosfero/public" | ||
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
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 "$RET" ]; then | @@ -68,10 +68,17 @@ if [ ! -z "$RET" ]; 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 "([^\"]+)" linking to "([^\"]+)"$/ do |text, href| | @@ -22,14 +18,14 @@ When /^I should see "([^\"]+)" linking to "([^\"]+)"$/ 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
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
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
lib/noosfero/vote_ext.rb
@@ -2,10 +2,10 @@ require_dependency 'models/vote' | @@ -2,10 +2,10 @@ require_dependency 'models/vote' | ||
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 |
@@ -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 < Noosfero::Plugin | @@ -73,8 +73,8 @@ class OrganizationRatingsPlugin < 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
plugins/people_block/test/unit/members_block_test.rb
@@ -280,6 +280,21 @@ class MembersBlockTest < ActionView::TestCase | @@ -280,6 +280,21 @@ class MembersBlockTest < 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 < ActiveSupport::TestCase | @@ -25,7 +25,8 @@ class PgSearchPluginTest < 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
plugins/stoa/test/functional/account_controller_test.rb
@@ -15,6 +15,7 @@ class AccountControllerTest < ActionController::TestCase | @@ -15,6 +15,7 @@ class AccountControllerTest < 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 < Noosfero::Plugin | @@ -33,10 +33,14 @@ class VideoPlugin < 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
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 | +}); |
@@ -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 'virtualhosts' | @@ -17,7 +17,6 @@ when 'virtualhosts' | ||
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 |