Commit 4d9daa44dbf61490640b32a8fb9f6f49f0f8b152
Exists in
staging
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
RELEASING.md
... | ... | @@ -3,37 +3,30 @@ Noosfero release tasks |
3 | 3 | |
4 | 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 | 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 | 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 | 19 | * Make sure all tests pass |
25 | -* Write release notes at the version's wiki topic | |
26 | 20 | * Generate packages with `rake noosfero:release[(stable|test)]`. This task will: |
27 | 21 | * Update the version in lib/noosfero.rb and debian/changelog. |
28 | 22 | * Create the tarbal and the deb pkg under pkg/ directory. |
29 | 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 | 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 | 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 | 83 | |
84 | 84 | def save |
85 | 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 | 89 | end |
93 | 90 | |
94 | 91 | def boxes_editor? | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -32,7 +32,8 @@ class CmsController < MyProfileController |
32 | 32 | end |
33 | 33 | |
34 | 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 | 37 | user && user.can_post_content?(profile, parent) |
37 | 38 | end |
38 | 39 | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
... | ... | @@ -2,8 +2,27 @@ class ProfileMembersController < MyProfileController |
2 | 2 | protect 'manage_memberships', :profile |
3 | 3 | |
4 | 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 | 26 | end |
8 | 27 | |
9 | 28 | def update_roles |
... | ... | @@ -156,4 +175,13 @@ class ProfileMembersController < MyProfileController |
156 | 175 | end |
157 | 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 | 187 | end | ... | ... |
app/controllers/public/account_controller.rb
... | ... | @@ -198,7 +198,7 @@ class AccountController < ApplicationController |
198 | 198 | if request.post? |
199 | 199 | begin |
200 | 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 | 202 | return false |
203 | 203 | end |
204 | 204 | ... | ... |
app/controllers/public/content_viewer_controller.rb
... | ... | @@ -68,11 +68,7 @@ class ContentViewerController < ApplicationController |
68 | 68 | process_comments(params) |
69 | 69 | |
70 | 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 | 72 | end |
77 | 73 | |
78 | 74 | if params[:slideshow] |
... | ... | @@ -209,8 +205,6 @@ class ContentViewerController < ApplicationController |
209 | 205 | |
210 | 206 | def rendered_file_download(view = nil) |
211 | 207 | if @page.download? view |
212 | - headers['Content-Type'] = @page.mime_type | |
213 | - headers.merge! @page.download_headers | |
214 | 208 | data = @page.data |
215 | 209 | |
216 | 210 | # TODO test the condition |
... | ... | @@ -218,7 +212,12 @@ class ContentViewerController < ApplicationController |
218 | 212 | raise "No data for file" |
219 | 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 | 221 | return true |
223 | 222 | end |
224 | 223 | |
... | ... | @@ -244,8 +243,12 @@ class ContentViewerController < ApplicationController |
244 | 243 | |
245 | 244 | def get_posts(year = nil, month = nil) |
246 | 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 | 252 | else |
250 | 253 | return @page.posts |
251 | 254 | end |
... | ... | @@ -276,8 +279,12 @@ class ContentViewerController < ApplicationController |
276 | 279 | @comments = @page.comments.without_spam |
277 | 280 | @comments = @plugins.filter(:unavailable_comments, @comments) |
278 | 281 | @comments_count = @comments.count |
279 | - @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] ) | |
280 | 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 | 288 | end |
282 | 289 | |
283 | 290 | private | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -155,6 +155,18 @@ class ProfileController < PublicController |
155 | 155 | end |
156 | 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 | 170 | def unblock |
159 | 171 | if current_user.person.is_admin?(profile.environment) |
160 | 172 | profile.unblock |
... | ... | @@ -362,6 +374,7 @@ class ProfileController < PublicController |
362 | 374 | def send_mail |
363 | 375 | @mailing = profile.mailings.build(params[:mailing]) |
364 | 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 | 378 | if request.post? |
366 | 379 | @mailing.locale = locale |
367 | 380 | @mailing.person = user | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -150,14 +150,8 @@ module ApplicationHelper |
150 | 150 | link_to text, profile_path(:profile => profile) , options |
151 | 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 | 155 | end |
162 | 156 | |
163 | 157 | def link_if_permitted(link, permission = nil, target = nil) |
... | ... | @@ -556,14 +550,25 @@ module ApplicationHelper |
556 | 550 | trigger_class = 'enterprise-trigger' |
557 | 551 | end |
558 | 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 | 564 | links = links_for_balloon(profile) |
561 | 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 | 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 | 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 | 572 | profile.url, |
568 | 573 | :class => 'profile_link url', |
569 | 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 | 716 | class NoosferoFormBuilder < ActionView::Helpers::FormBuilder |
712 | 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 | 720 | # try to guess an id if none given |
716 | 721 | if field_id.nil? |
717 | 722 | field_html =~ /id=['"]([^'"]*)['"]/ |
... | ... | @@ -1040,10 +1045,11 @@ module ApplicationHelper |
1040 | 1045 | end |
1041 | 1046 | |
1042 | 1047 | def search_contents_menu |
1048 | + host = environment.default_hostname | |
1043 | 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 | 1054 | if logged_in? |
1049 | 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 | 1061 | alias :browse_contents_menu :search_contents_menu |
1056 | 1062 | |
1057 | 1063 | def search_people_menu |
1064 | + host = environment.default_hostname | |
1058 | 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 | 1070 | if logged_in? |
1064 | 1071 | links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})}) |
... | ... | @@ -1071,10 +1078,11 @@ module ApplicationHelper |
1071 | 1078 | alias :browse_people_menu :search_people_menu |
1072 | 1079 | |
1073 | 1080 | def search_communities_menu |
1081 | + host = environment.default_hostname | |
1074 | 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 | 1087 | if logged_in? |
1080 | 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 | 169 | _('Edit') |
170 | 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 | 198 | end | ... | ... |
app/helpers/block_helper.rb
... | ... | @@ -14,6 +14,7 @@ module BlockHelper |
14 | 14 | </td> |
15 | 15 | <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td> |
16 | 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 | 18 | </tr><tr class=\"image-title\" data-row-number='#{row_number}'> |
18 | 19 | <td colspan=\"3\"><label>#{ |
19 | 20 | content_tag('span', _('Title')) + | ... | ... |
app/helpers/boxes_helper.rb
... | ... | @@ -250,7 +250,7 @@ module BoxesHelper |
250 | 250 | end |
251 | 251 | end |
252 | 252 | |
253 | - if editable?(block) | |
253 | + if editable?(block, user) | |
254 | 254 | buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) |
255 | 255 | end |
256 | 256 | |
... | ... | @@ -296,7 +296,7 @@ module BoxesHelper |
296 | 296 | return block.movable? || user.is_admin? |
297 | 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 | 301 | end |
302 | 302 | end | ... | ... |
app/helpers/forms_helper.rb
... | ... | @@ -7,9 +7,10 @@ module FormsHelper |
7 | 7 | |
8 | 8 | def labelled_check_box( human_name, name, value = "1", checked = false, options = {} ) |
9 | 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 | 14 | end |
14 | 15 | |
15 | 16 | def labelled_text_field( human_name, name, value=nil, options={} ) | ... | ... |
app/mailers/mailing.rb
... | ... | @@ -2,7 +2,10 @@ require_dependency 'mailing_job' |
2 | 2 | |
3 | 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 | 9 | validates_presence_of :source_id, :subject, :body |
7 | 10 | belongs_to :source, :foreign_key => :source_id, :polymorphic => true |
8 | 11 | belongs_to :person | ... | ... |
app/mailers/organization_mailing.rb
... | ... | @@ -5,9 +5,17 @@ class OrganizationMailing < Mailing |
5 | 5 | end |
6 | 6 | |
7 | 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 | 16 | .where("m.person_id" => nil) |
17 | + end | |
18 | + result | |
11 | 19 | end |
12 | 20 | |
13 | 21 | def each_recipient | ... | ... |
app/models/article.rb
... | ... | @@ -8,8 +8,9 @@ class Article < ActiveRecord::Base |
8 | 8 | :accept_comments, :feed, :published, :source, :source_name, |
9 | 9 | :highlighted, :notify_comments, :display_hits, :slug, |
10 | 10 | :external_feed_builder, :display_versions, :external_link, |
11 | - :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 | 15 | acts_as_having_image |
15 | 16 | |
... | ... | @@ -83,6 +84,10 @@ class Article < ActiveRecord::Base |
83 | 84 | |
84 | 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 | 91 | has_many :article_categorizations, -> { where 'articles_categories.virtual = ?', false } |
87 | 92 | has_many :categories, :through => :article_categorizations |
88 | 93 | |
... | ... | @@ -95,7 +100,6 @@ class Article < ActiveRecord::Base |
95 | 100 | settings_items :author_name, :type => :string, :default => "" |
96 | 101 | settings_items :allow_members_to_edit, :type => :boolean, :default => false |
97 | 102 | settings_items :moderate_comments, :type => :boolean, :default => false |
98 | - settings_items :followers, :type => Array, :default => [] | |
99 | 103 | has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions' |
100 | 104 | |
101 | 105 | belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' |
... | ... | @@ -173,7 +177,6 @@ class Article < ActiveRecord::Base |
173 | 177 | end |
174 | 178 | end |
175 | 179 | |
176 | - | |
177 | 180 | def is_trackable? |
178 | 181 | self.published? && self.notifiable? && self.advertise? && self.profile.public_profile |
179 | 182 | end |
... | ... | @@ -374,6 +377,10 @@ class Article < ActiveRecord::Base |
374 | 377 | self.parent and self.parent.forum? |
375 | 378 | end |
376 | 379 | |
380 | + def person_followers_email_list | |
381 | + person_followers_emails.map{|p|p.email} | |
382 | + end | |
383 | + | |
377 | 384 | def info_from_last_update |
378 | 385 | last_comment = comments.last |
379 | 386 | if last_comment |
... | ... | @@ -383,6 +390,10 @@ class Article < ActiveRecord::Base |
383 | 390 | end |
384 | 391 | end |
385 | 392 | |
393 | + def full_path | |
394 | + profile.hostname.blank? ? "/#{profile.identifier}/#{path}" : "/#{path}" | |
395 | + end | |
396 | + | |
386 | 397 | def url |
387 | 398 | @url ||= self.profile.url.merge(:page => path.split('/')) |
388 | 399 | end |
... | ... | @@ -408,13 +419,19 @@ class Article < ActiveRecord::Base |
408 | 419 | end |
409 | 420 | |
410 | 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 | 431 | end |
415 | 432 | |
416 | 433 | def download_headers |
417 | - {} | |
434 | + { :filename => filename, :type => mime_type, :disposition => download_disposition} | |
418 | 435 | end |
419 | 436 | |
420 | 437 | def alternate_languages | ... | ... |
app/models/block.rb
... | ... | @@ -195,8 +195,8 @@ class Block < ActiveRecord::Base |
195 | 195 | nil |
196 | 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 | 200 | self.edit_modes == "all" |
201 | 201 | end |
202 | 202 | ... | ... |
app/models/comment.rb
... | ... | @@ -6,13 +6,14 @@ class Comment < ActiveRecord::Base |
6 | 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 | 11 | validates_presence_of :body |
12 | 12 | |
13 | 13 | belongs_to :source, :counter_cache => true, :polymorphic => true |
14 | 14 | alias :article :source |
15 | 15 | alias :article= :source= |
16 | + attr_accessor :follow_article | |
16 | 17 | |
17 | 18 | belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' |
18 | 19 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy |
... | ... | @@ -102,10 +103,9 @@ class Comment < ActiveRecord::Base |
102 | 103 | |
103 | 104 | after_create :new_follower |
104 | 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 | 109 | article.save |
110 | 110 | end |
111 | 111 | end |
... | ... | @@ -147,7 +147,7 @@ class Comment < ActiveRecord::Base |
147 | 147 | if !notification_emails.empty? |
148 | 148 | CommentNotifier.notification(self).deliver |
149 | 149 | end |
150 | - emails = article.followers - [author_email] | |
150 | + emails = article.person_followers_email_list - [author_email] | |
151 | 151 | if !emails.empty? |
152 | 152 | CommentNotifier.mail_to_followers(self, emails).deliver |
153 | 153 | end | ... | ... |
app/models/disabled_enterprise_message_block.rb
app/models/environment.rb
... | ... | @@ -56,6 +56,7 @@ class Environment < ActiveRecord::Base |
56 | 56 | 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'), |
57 | 57 | 'edit_appearance' => N_('Edit appearance'), |
58 | 58 | 'manage_email_templates' => N_('Manage Email Templates'), |
59 | + 'edit_raw_html_block' => N_('Edit Raw HTML block'), | |
59 | 60 | } |
60 | 61 | |
61 | 62 | module Roles | ... | ... |
app/models/highlights_block.rb
... | ... | @@ -15,6 +15,8 @@ class HighlightsBlock < Block |
15 | 15 | if !Noosfero.root.nil? and !i[:address].start_with?(Noosfero.root + '/') |
16 | 16 | i[:address] = Noosfero.root + i[:address] |
17 | 17 | end |
18 | + i[:new_window] = i[:new_window] == '1' ? true : false | |
19 | + | |
18 | 20 | begin |
19 | 21 | file = UploadedFile.find(i[:image_id]) |
20 | 22 | i[:image_src] = file.public_filename | ... | ... |
app/models/person.rb
1 | 1 | # A person is the profile of an user holding all relationships with the rest of the system |
2 | 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 | 6 | SEARCH_FILTERS = { |
10 | 7 | :order => %w[more_recent more_popular more_active], |
... | ... | @@ -19,26 +16,29 @@ class Person < Profile |
19 | 16 | acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)} |
20 | 17 | acts_as_accessor |
21 | 18 | |
22 | - scope :members_of, -> resources { | |
19 | + scope :members_of, lambda { |resources, field = ''| | |
23 | 20 | resources = Array(resources) |
21 | + joins = [:role_assignments] | |
22 | + joins << :user if User.attribute_names.include? field | |
23 | + | |
24 | 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 | 28 | scope :not_members_of, -> resources { |
29 | 29 | resources = Array(resources) |
30 | 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 | 34 | scope :by_role, -> roles { |
35 | 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 | 39 | scope :not_friends_of, -> resources { |
40 | 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 | 44 | scope :visible_for_person, lambda { |person| |
... | ... | @@ -51,8 +51,7 @@ class Person < Profile |
51 | 51 | ['( roles.key = ? AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR ( |
52 | 52 | ( ( friendships.person_id = ? ) OR (profiles.public_profile = ?)) AND (profiles.visible = ?) )', 'environment_administrator', Profile.name, person.id, person.id, true, true] |
53 | 53 | ).uniq |
54 | - } | |
55 | - | |
54 | + } | |
56 | 55 | |
57 | 56 | def has_permission_with_admin?(permission, resource) |
58 | 57 | return true if resource.blank? || resource.admins.include?(self) |
... | ... | @@ -90,7 +89,8 @@ class Person < Profile |
90 | 89 | has_many :article_followers, :dependent => :destroy |
91 | 90 | has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article |
92 | 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 | 94 | has_many :friendships, :dependent => :destroy |
95 | 95 | has_many :friends, :class_name => 'Person', :through => :friendships |
96 | 96 | |
... | ... | @@ -123,10 +123,10 @@ class Person < Profile |
123 | 123 | scope :more_popular, -> { order 'friends_count DESC' } |
124 | 124 | |
125 | 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 | 128 | scope :non_abusers, -> { |
129 | - select("DISTINCT profiles.*"). | |
129 | + distinct.select("profiles.*"). | |
130 | 130 | joins("LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'"). |
131 | 131 | where("tasks.status != 3 OR tasks.id is NULL") |
132 | 132 | } |
... | ... | @@ -135,6 +135,11 @@ class Person < Profile |
135 | 135 | scope :activated, -> { joins(:user).where('users.activation_code IS NULL AND users.activated_at IS NOT NULL') } |
136 | 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 | 143 | after_destroy do |person| |
139 | 144 | Friendship.where(friend_id: person.id).each{ |friendship| friendship.destroy } |
140 | 145 | end | ... | ... |
app/models/profile.rb
... | ... | @@ -78,6 +78,9 @@ class Profile < ActiveRecord::Base |
78 | 78 | def self.organization_member_roles(env_id) |
79 | 79 | all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? || !r.profile_id.nil?} |
80 | 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 | 84 | def self.all_roles(env_id) |
82 | 85 | Role.where(environment_id: env_id) |
83 | 86 | end |
... | ... | @@ -119,7 +122,7 @@ class Profile < ActiveRecord::Base |
119 | 122 | include Noosfero::Plugin::HotSpot |
120 | 123 | |
121 | 124 | scope :memberships_of, -> person { |
122 | - select('DISTINCT profiles.*'). | |
125 | + distinct.select('profiles.*'). | |
123 | 126 | joins(:role_assignments). |
124 | 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 | 188 | |
186 | 189 | include TimeScopes |
187 | 190 | |
188 | - def members | |
191 | + def members(by_field = '') | |
189 | 192 | scopes = plugins.dispatch_scopes(:organization_members, self) |
190 | - scopes << Person.members_of(self) | |
193 | + scopes << Person.members_of(self,by_field) | |
191 | 194 | return scopes.first if scopes.size == 1 |
192 | 195 | ScopeTool.union *scopes |
193 | 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 | 208 | end |
198 | 209 | |
199 | 210 | class << self |
... | ... | @@ -781,13 +792,13 @@ private :generate_url, :url_options |
781 | 792 | end |
782 | 793 | |
783 | 794 | # Adds a person as member of this Profile. |
784 | - def add_member(person) | |
795 | + def add_member(person, attributes={}) | |
785 | 796 | if self.has_members? |
786 | 797 | if self.closed? && members.count > 0 |
787 | 798 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) |
788 | 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 | 802 | end |
792 | 803 | person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } |
793 | 804 | remove_from_suggestion_list person |
... | ... | @@ -1164,6 +1175,10 @@ private :generate_url, :url_options |
1164 | 1175 | end |
1165 | 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 | 1182 | validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true |
1168 | 1183 | def preferred_login_redirection |
1169 | 1184 | redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login | ... | ... |
app/models/raw_html_block.rb
app/models/rss_feed.rb
app/models/uploaded_file.rb
... | ... | @@ -2,6 +2,9 @@ |
2 | 2 | # |
3 | 3 | # Limitation: only file metadata are versioned. Only the latest version |
4 | 4 | # of the file itself is kept. (FIXME?) |
5 | + | |
6 | +require 'sdbm' | |
7 | + | |
5 | 8 | class UploadedFile < Article |
6 | 9 | |
7 | 10 | attr_accessible :uploaded_data, :title |
... | ... | @@ -10,6 +13,19 @@ class UploadedFile < Article |
10 | 13 | _('File') |
11 | 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 | 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 | 31 | def title |
... | ... | @@ -106,10 +122,13 @@ class UploadedFile < Article |
106 | 122 | self.name ||= self.filename |
107 | 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 | 132 | end |
114 | 133 | |
115 | 134 | def data | ... | ... |
app/views/account/forgot_password.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <%= form_tag({:action => 'forgot_password'}, :method => 'post', :id => 'forgot-password-form') do %> |
6 | 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 | 9 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> |
10 | 10 | |
11 | 11 | <div> | ... | ... |
app/views/account/index.html.erb
app/views/blocks/highlights.html.erb
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | <div class='highlights-border'> |
4 | 4 | <div class='highlights-container'> |
5 | 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 | 7 | <%= image_tag [Noosfero.root, img[:image_src]].join, alt: img[:title] %> |
8 | 8 | <p class="highlights-label"><%= img[:title] %></p> |
9 | 9 | </a> | ... | ... |
app/views/box_organizer/_highlights_block.html.erb
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | <strong><%= _('Highlights') %></strong> |
4 | 4 | |
5 | 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 | 7 | <% @block.images.each_with_index do |image, index| %> |
8 | 8 | <%= highlights_block_config_image_fields @block, image, index %> |
9 | 9 | <% end %> | ... | ... |
app/views/cms/_drag_and_drop_note.html.erb
app/views/cms/_text_editor_sidebar.html.erb
... | ... | @@ -17,8 +17,8 @@ |
17 | 17 | :parent_id, profile, default_folder, {}, {}, |
18 | 18 | "type='Folder' or type='Gallery'" |
19 | 19 | ) %> |
20 | + <%= button(:newfolder, _('New folder'), '#', :id => 'new-folder-button') %> | |
20 | 21 | </div> |
21 | - <%= button(:newfolder, _('New folder'), '#', :id => 'new-folder-button') %> | |
22 | 22 | <p><%= file_field_tag('file', :multiple => true) %></p> |
23 | 23 | <% end %> |
24 | 24 | </div> |
... | ... | @@ -31,7 +31,7 @@ |
31 | 31 | <div id='published-media' class='text-editor-sidebar-box' data-url='<%= url_for({:controller => 'cms', :action => 'published_media_items', :profile => profile.identifier}) %>'> |
32 | 32 | <%= select_profile_folder(nil, :parent_id, profile, 'recent-media', {}, {}, |
33 | 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 | 35 | <%= render :partial => 'drag_and_drop_note' %> |
36 | 36 | <div class='items'> |
37 | 37 | <%= render :partial => 'published_media_items' %> | ... | ... |
app/views/comment/_comment_form.html.erb
... | ... | @@ -77,6 +77,10 @@ function check_captcha(button, confirm_action) { |
77 | 77 | <%= labelled_form_field(_('Title'), f.text_field(:title)) %> |
78 | 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 | 84 | <%= hidden_field_tag(:confirm, 'false') %> |
81 | 85 | <%= hidden_field_tag(:view, params[:view])%> |
82 | 86 | <%= f.hidden_field(:reply_of_id) %> | ... | ... |
app/views/content_viewer/_article_toolbar.html.erb
app/views/content_viewer/_publishing_info.html.erb
... | ... | @@ -10,6 +10,24 @@ |
10 | 10 | <%= (" - %s") % link_to_comments(@page)%> |
11 | 11 | </span> |
12 | 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 | 31 | </span> |
14 | 32 | |
15 | 33 | <% if @page.display_hits? || @page.license.present? %> | ... | ... |
app/views/content_viewer/view_page.html.erb
... | ... | @@ -81,7 +81,7 @@ |
81 | 81 | <ul class="article-comments-list"> |
82 | 82 | <% if @comments.present? %> |
83 | 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 | 85 | <% end %> |
86 | 86 | </ul> |
87 | 87 | ... | ... |
app/views/file_presenter/_generic.html.erb
... | ... | @@ -2,4 +2,4 @@ |
2 | 2 | <%= generic.abstract %> |
3 | 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 | 9 | </div> |
10 | 10 | <ul class="profile-list-<%= role %>" > |
11 | 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 | 14 | <% end %> |
14 | 15 | </ul> |
15 | 16 | ... | ... |
app/views/profile/members.html.erb
app/views/profile/send_mail.html.erb
... | ... | @@ -10,6 +10,9 @@ |
10 | 10 | </div> |
11 | 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 | 16 | <%= form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %> |
14 | 17 | |
15 | 18 | <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> | ... | ... |
app/views/profile_members/_index_buttons.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <%= button :person, _('Invite people to join'), :controller => 'invite', :action => 'invite_friends' %> |
6 | 6 | <% end %> |
7 | 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 | 9 | <% end %> |
10 | 10 | <% @plugins.dispatch(:manage_members_extra_buttons).each do |plugin_button| %> |
11 | 11 | <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url] %> | ... | ... |
... | ... | @@ -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 | 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 | 3 | <% title = @title ? @title : _('Current members') %> |
3 | 4 | <% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %> |
5 | +<%= javascript_include_tag params[:controller] %> | |
4 | 6 | |
5 | 7 | <h3><%= title %></h3> |
6 | 8 | |
7 | 9 | <table> |
10 | + <col width="1"> | |
8 | 11 | <tr> |
12 | + <th><%= check_box_tag 'checkbox-all', 1, false, :onClick => "toggle(this)" %></th> | |
9 | 13 | <th><%= _('Member') %></th> |
10 | 14 | <th><%= _('Actions') %></th> |
11 | 15 | </tr> |
16 | + | |
12 | 17 | <% collection.each do |m| %> |
13 | 18 | <tr title="<%= m.name %>"> |
19 | + <td><%= labelled_check_box('', 'members_filtered[]', m.id.to_s, false, :id => 'checkbox-'+m.identifier) %></td> | |
14 | 20 | <td><%= link_to_profile m.short_name, m.identifier, :title => m.name %> </td> |
15 | 21 | <td> |
16 | 22 | <div class="members-buttons-cell"> |
... | ... | @@ -27,3 +33,8 @@ |
27 | 33 | </tr> |
28 | 34 | <% end %> |
29 | 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 | 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 | 5 | <ul> |
6 | 6 | <% for validator in @region.validators %> |
7 | 7 | <li> |
8 | - <%= link_to_homepage validator.name, validator.identifier %> | |
8 | + <%= link_to_homepage validator.name, validator %> | |
9 | 9 | <%= link_to _('Remove validation rights'), { :action => 'remove', :id => @region.id, :validator_id => validator }, :method => 'post' %> |
10 | 10 | </li> |
11 | 11 | <% end %> | ... | ... |
app/views/search/_full_enterprise.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | @order == 'more_recent' ? enterprise.send(@order + '_label') + show_date(enterprise.created_at) : enterprise.send(@order + '_label') %> |
6 | 6 | </div> |
7 | 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 | 9 | <div class="search-enterprise-description"> |
10 | 10 | <% if enterprise.description %> |
11 | 11 | <% body_stripped = strip_tags(enterprise.description) %> | ... | ... |
app/views/search/_full_product.html.erb
... | ... | @@ -44,7 +44,7 @@ |
44 | 44 | <div class="search-product-item-second-column"> |
45 | 45 | <%= link_to_product product, :class => 'search-result-title' %> |
46 | 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 | 48 | </div> |
49 | 49 | <div class="search-product-description"> |
50 | 50 | <% if product.description %> | ... | ... |
app/views/search/_image.html.erb
... | ... | @@ -26,7 +26,7 @@ |
26 | 26 | <% end %> |
27 | 27 | <% elsif image.is_a? Gallery %> |
28 | 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 | 30 | <% if r.length > 0 %> |
31 | 31 | <% r.each_index do |i| img = r[i] %> |
32 | 32 | <%= link_to '', img.view_url, :class => "search-image-pic pic-num#{i+1}", |
... | ... | @@ -47,6 +47,8 @@ |
47 | 47 | <% else %> |
48 | 48 | <div class="search-no-image"><span><%= _('No image') %></span></div> |
49 | 49 | <% end %> |
50 | + <% elsif image.first_image.present? %> | |
51 | + <img src="<%= image.first_image %>" class="automatic-abstract-thumb search-image-pic"> | |
50 | 52 | <% else %> |
51 | 53 | <div class="search-content-type-icon icon-content-<%=image.class.to_s.underscore.dasherize%>"></div> |
52 | 54 | <% end %> | ... | ... |
app/views/user_mailer/activation_code.text.erb
1 | 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 | 5 | <%= _("Greetings,") %> |
6 | 6 | |
7 | 7 | -- |
8 | 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 @@ |
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 @@ |
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 @@ |
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 | 11 | # |
12 | 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 | 16 | # These are extensions that must be enabled in order to support this database |
17 | 17 | enable_extension "plpgsql" |
... | ... | @@ -88,9 +88,9 @@ ActiveRecord::Schema.define(version: 20151221105330) do |
88 | 88 | t.integer "profile_id" |
89 | 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 | 94 | t.datetime "since" |
95 | 95 | t.datetime "created_at" |
96 | 96 | t.datetime "updated_at" |
... | ... | @@ -699,6 +699,7 @@ ActiveRecord::Schema.define(version: 20151221105330) do |
699 | 699 | t.string "locale" |
700 | 700 | t.datetime "created_at" |
701 | 701 | t.datetime "updated_at" |
702 | + t.text "data" | |
702 | 703 | end |
703 | 704 | |
704 | 705 | create_table "mark_comment_as_read_plugin", force: :cascade do |t| |
... | ... | @@ -1071,12 +1072,14 @@ ActiveRecord::Schema.define(version: 20151221105330) do |
1071 | 1072 | end |
1072 | 1073 | |
1073 | 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 | 1083 | end |
1081 | 1084 | |
1082 | 1085 | create_table "roles", force: :cascade do |t| | ... | ... |
debian/apache2/virtualhost.conf
... | ... | @@ -8,6 +8,19 @@ DocumentRoot "/usr/share/noosfero/public" |
8 | 8 | |
9 | 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 | 24 | # Rewrite index to check for static index.html |
12 | 25 | RewriteRule ^/$ /index.html [QSA] |
13 | 26 | ... | ... |
debian/changelog
debian/dbinstall
... | ... | @@ -5,8 +5,6 @@ set -e |
5 | 5 | # dbconfig-common uses "pgsql", but we want "postgresql" |
6 | 6 | sed -i -e 's/adapter: pgsql/adapter: postgresql/' /etc/noosfero/database.yml |
7 | 7 | |
8 | -/etc/init.d/noosfero setup | |
9 | - | |
10 | 8 | cd /usr/share/noosfero && su noosfero -c "rake db:schema:load RAILS_ENV=production" |
11 | 9 | cd /usr/share/noosfero && su noosfero -c "rake db:migrate RAILS_ENV=production SCHEMA=/dev/null" |
12 | 10 | cd /usr/share/noosfero && su noosfero -c "rake db:data:minimal RAILS_ENV=production" | ... | ... |
debian/dbupgrade
debian/noosfero.links
1 | 1 | var/tmp/noosfero usr/share/noosfero/tmp |
2 | 2 | var/log/noosfero usr/share/noosfero/log |
3 | +var/cache/noosfero usr/share/noosfero/cache | |
3 | 4 | etc/noosfero/database.yml usr/share/noosfero/config/database.yml |
4 | 5 | etc/noosfero/unicorn.rb usr/share/noosfero/config/unicorn.rb |
5 | 6 | etc/noosfero/plugins usr/share/noosfero/config/plugins | ... | ... |
debian/noosfero.postinst
... | ... | @@ -68,10 +68,17 @@ if [ ! -z "$RET" ]; then |
68 | 68 | export NOOSFERO_DOMAIN="$RET" |
69 | 69 | fi |
70 | 70 | |
71 | +/etc/init.d/noosfero setup | |
72 | + | |
71 | 73 | # dbconfig-common magic |
72 | 74 | . /usr/share/dbconfig-common/dpkg/postinst |
73 | 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 | 82 | # stop debconf to avoid the problem with infinite hanging, cfe |
76 | 83 | # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=295477 |
77 | 84 | db_stop | ... | ... |
debian/update-noosfero-apache
... | ... | @@ -17,13 +17,13 @@ if test -x /usr/share/noosfero/script/apacheconf; then |
17 | 17 | if ! test -e "$apache_site"; then |
18 | 18 | echo "Generating apache virtual host ..." |
19 | 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 | 27 | fi |
28 | 28 | |
29 | 29 | echo 'Noosfero Apache configuration updated.' | ... | ... |
etc/init.d/noosfero
... | ... | @@ -86,6 +86,13 @@ do_setup() { |
86 | 86 | chmod 750 /var/tmp/noosfero |
87 | 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 | 96 | # symlink the directories into Noosfero directory |
90 | 97 | if [ ! -e $NOOSFERO_DIR/tmp ]; then |
91 | 98 | ln -s /var/tmp/noosfero $NOOSFERO_DIR/tmp |
... | ... | @@ -96,6 +103,9 @@ do_setup() { |
96 | 103 | if [ ! -e $NOOSFERO_DIR/log ]; then |
97 | 104 | ln -s /var/log/noosfero $NOOSFERO_DIR/log |
98 | 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 | 111 | do_start() { | ... | ... |
features/admin_categories.feature
... | ... | @@ -45,7 +45,7 @@ Feature: manage categories |
45 | 45 | And I should see "Steak" |
46 | 46 | When I follow "Hide" |
47 | 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 | 50 | @selenium |
51 | 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 | 44 | And I follow "Edit" within ".block-outer .categories-block" |
45 | 45 | And I check "Product" |
46 | 46 | And I press "Save" |
47 | + And I go to / | |
47 | 48 | Then I should see "Food" |
48 | 49 | And I should see "Book" |
49 | 50 | And "Vegetarian" should not be visible within "span#category-name" |
... | ... | @@ -62,6 +63,7 @@ Feature: categories_block |
62 | 63 | And I follow "Edit" within ".block-outer .categories-block" |
63 | 64 | And I check "Product" |
64 | 65 | And I press "Save" |
66 | + And I go to / | |
65 | 67 | Then I should see "Book" |
66 | 68 | And "Literature" should not be visible within "span#category-name" |
67 | 69 | When I follow "block_2_category_2" | ... | ... |
features/comment.feature
... | ... | @@ -96,4 +96,4 @@ Feature: comment |
96 | 96 | Scenario: hide post a comment button when clicked |
97 | 97 | Given I am on /booking/article-to-comment |
98 | 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 | 27 | Then I should not see "Beans" |
28 | 28 | And I should not see "Potatoes" |
29 | 29 | When I follow "Show" |
30 | + And I wait 0.5 seconds for Services show animation to finish | |
31 | + And I follow "Show" | |
30 | 32 | Then I should see "Beans" |
31 | 33 | And I should see "Potatoes" | ... | ... |
features/manage_users.feature
... | ... | @@ -15,7 +15,7 @@ Background: |
15 | 15 | Scenario: deactive user |
16 | 16 | Given I follow "Deactivate user" within "tr[title='Joao Silva']" |
17 | 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 | 20 | @selenium |
21 | 21 | Scenario: activate user |
... | ... | @@ -23,7 +23,7 @@ Background: |
23 | 23 | And I confirm the browser dialog |
24 | 24 | And I follow "Activate user" within "tr[title='Paulo Santos']" |
25 | 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 | 28 | @selenium |
29 | 29 | Scenario: remove user |
... | ... | @@ -36,7 +36,7 @@ Background: |
36 | 36 | Scenario: admin user |
37 | 37 | Given I follow "Set admin role" within "tr[title='Joao Silva']" |
38 | 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 | 41 | @selenium |
42 | 42 | Scenario: unadmin user |
... | ... | @@ -44,4 +44,4 @@ Background: |
44 | 44 | And I confirm the browser dialog |
45 | 45 | And I follow "Reset admin role" within "tr[title='Paulo Santos']" |
46 | 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
features/send_email_to_organization_members.feature
... | ... | @@ -31,7 +31,8 @@ Feature: send emails to organization members |
31 | 31 | Scenario: Send e-mail to members |
32 | 32 | Given I am logged in as "joaosilva" |
33 | 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 | 36 | And I fill in "Subject" with "Hello, member!" |
36 | 37 | And I fill in "Body" with "We have some news" |
37 | 38 | When I press "Send" |
... | ... | @@ -40,7 +41,8 @@ Feature: send emails to organization members |
40 | 41 | Scenario: Not send e-mail to members if subject is blank |
41 | 42 | Given I am logged in as "joaosilva" |
42 | 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 | 46 | And I fill in "Body" with "We have some news" |
45 | 47 | When I press "Send" |
46 | 48 | Then I should be on /profile/sample-community/send_mail |
... | ... | @@ -48,7 +50,8 @@ Feature: send emails to organization members |
48 | 50 | Scenario: Not send e-mail to members if body is blank |
49 | 51 | Given I am logged in as "joaosilva" |
50 | 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 | 55 | And I fill in "Subject" with "Hello, user!" |
53 | 56 | When I press "Send" |
54 | 57 | Then I should be on /profile/sample-community/send_mail |
... | ... | @@ -56,7 +59,8 @@ Feature: send emails to organization members |
56 | 59 | Scenario: Cancel creation of mailing |
57 | 60 | Given I am logged in as "joaosilva" |
58 | 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 | 64 | When I follow "Cancel e-mail" |
61 | 65 | Then I should be on Sample Community's members management |
62 | 66 | ... | ... |
features/step_definitions/custom_web_steps.rb
1 | 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 | 3 | end |
6 | 4 | |
7 | 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 | 7 | end |
12 | 8 | |
13 | 9 | Then /^I should see "([^"]*)" link$/ do |text| |
... | ... | @@ -22,14 +18,14 @@ When /^I should see "([^\"]+)" linking to "([^\"]+)"$/ do |text, href| |
22 | 18 | page.should have_xpath("//a[@href='#{href}']") |
23 | 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 | 29 | end |
34 | 30 | |
35 | 31 | When /^I reload and wait for the page$/ do | ... | ... |
features/step_definitions/web_steps.rb
... | ... | @@ -7,7 +7,7 @@ |
7 | 7 | |
8 | 8 | require 'uri' |
9 | 9 | require 'cgi' |
10 | -require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths")) | |
10 | +require_relative '../support/paths' | |
11 | 11 | |
12 | 12 | module WithinHelpers |
13 | 13 | def with_scope(locator) |
... | ... | @@ -39,37 +39,15 @@ end |
39 | 39 | |
40 | 40 | When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector| |
41 | 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 | 49 | end |
50 | + target.click | |
73 | 51 | end |
74 | 52 | end |
75 | 53 | ... | ... |
features/support/debug.rb
features/support/env.rb
... | ... | @@ -65,5 +65,13 @@ Before do |
65 | 65 | fixtures_folder = Rails.root.join('test', 'fixtures') |
66 | 66 | fixtures = ['environments', 'roles'] |
67 | 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 | 76 | end |
69 | 77 | ... | ... |
gitignore.example
lib/file_presenter.rb
lib/noosfero/api/v1/articles.rb
... | ... | @@ -165,6 +165,37 @@ module Noosfero |
165 | 165 | end |
166 | 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 | 199 | desc 'Return the children of a article identified by id' do |
169 | 200 | detail 'Get all children articles of a specific article' |
170 | 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 | 2 | |
3 | 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 | 9 | end |
10 | 10 | |
11 | 11 | validate :verify_target_archived | ... | ... |
... | ... | @@ -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 | 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 | 8 | end | ... | ... |
plugins/organization_ratings/features/rate_community.feature
... | ... | @@ -33,4 +33,4 @@ Feature: rate_community |
33 | 33 | Given I am on mycommunity's homepage |
34 | 34 | When I follow "Rate this Community" |
35 | 35 | Then I should see "Joao Silva" within ".star-profile-name" |
36 | - And I should see Joao Silva's profile image | |
37 | 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 @@ |
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
plugins/organization_ratings/public/organization_rating_management.js
... | ... | @@ -9,8 +9,8 @@ |
9 | 9 | |
10 | 10 | |
11 | 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 | 21 | |
22 | 22 | verifyHoursTimerDisable: function() { |
23 | 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 | 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 | 14 | } |
15 | 15 | |
16 | 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 | 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 | 24 | .small-star-negative, .small-star-positive { |
... | ... | @@ -31,11 +31,11 @@ |
31 | 31 | } |
32 | 32 | |
33 | 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 | 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 | 41 | .medium-star-negative, .medium-star-positive { |
... | ... | @@ -48,11 +48,11 @@ |
48 | 48 | } |
49 | 49 | |
50 | 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 | 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 | 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 | 280 | assert_includes block.roles, Profile::Roles.moderator(owner.environment.id) |
281 | 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 | 298 | protected |
284 | 299 | include NoosferoTestHelper |
285 | 300 | ... | ... |
plugins/pg_search/test/unit/pg_search_plugin_test.rb
... | ... | @@ -25,7 +25,8 @@ class PgSearchPluginTest < ActiveSupport::TestCase |
25 | 25 | profile1 = fast_create(Profile, :identifier => 'profile1', :name => 'debugger') |
26 | 26 | profile2 = fast_create(Profile, :identifier => 'profile2', :name => 'profile admin debugger') |
27 | 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 | 30 | end |
30 | 31 | |
31 | 32 | should 'locate profile escaping special characters' do | ... | ... |
plugins/site_tour/lib/ext/person.rb
plugins/stoa/test/functional/account_controller_test.rb
plugins/sub_organizations/views/sub_organizations_plugin_profile/_full_related_organizations.html.erb
... | ... | @@ -10,7 +10,7 @@ |
10 | 10 | <%= profile_image_link organization, :big, 'div' %> |
11 | 11 | </div> |
12 | 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 | 14 | <div class="related-organizations-description"> |
15 | 15 | <% if organization.description %> |
16 | 16 | <% body_stripped = strip_tags(organization.description) %> | ... | ... |
plugins/video/lib/video_plugin.rb
... | ... | @@ -33,10 +33,14 @@ class VideoPlugin < Noosfero::Plugin |
33 | 33 | end |
34 | 34 | |
35 | 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 | 44 | end |
41 | 45 | |
42 | 46 | end | ... | ... |
plugins/video/views/content_viewer/video_plugin/_video_gallery.html.erb
public/designs/themes/noosfero/style.css
public/javascripts/comment_order.js
... | ... | @@ -10,10 +10,9 @@ function send_order(order, url) { |
10 | 10 | }); |
11 | 11 | } |
12 | 12 | |
13 | - | |
14 | 13 | jQuery(document).ready(function(){ |
15 | 14 | jQuery("#comment_order").change(function(){ |
16 | - var url = jQuery("#page_url").val(); | |
15 | + var url = window.location.href; | |
17 | 16 | send_order(this.value, url); |
18 | 17 | }); |
19 | -}); | |
20 | 18 | \ No newline at end of file |
19 | +}); | ... | ... |
... | ... | @@ -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 | 207 | height: auto; |
208 | 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 | 17 | puts " #{server_directive} #{domain.name}" |
18 | 18 | server_directive = 'ServerAlias' |
19 | 19 | end |
20 | - puts " Include /usr/share/noosfero/util/chat/apache/xmpp.conf" | |
21 | 20 | puts " Include /etc/noosfero/apache/virtualhost.conf" |
22 | 21 | puts "</VirtualHost>" |
23 | 22 | end | ... | ... |