Commit 12d4acaed8f73427008977442e70c744d034f576
Exists in
master
and in
29 other branches
Merge branch 'next_colivre' into ActionItem2871
Showing
236 changed files
with
5968 additions
and
662 deletions
Show diff stats
COPYRIGHT
@@ -4,8 +4,9 @@ Copyright (c) 2007-2009, | @@ -4,8 +4,9 @@ Copyright (c) 2007-2009, | ||
4 | Cáritas Brasileira <http://www.caritasbrasileira.org/> | 4 | Cáritas Brasileira <http://www.caritasbrasileira.org/> |
5 | Copyright (c) 2007-2009, | 5 | Copyright (c) 2007-2009, |
6 | Ynternet.org Foundation <http://www.ynternet.org/> | 6 | Ynternet.org Foundation <http://www.ynternet.org/> |
7 | -Copyright (c) 2008-2009, | 7 | +Copyright (c) 2008-2013, |
8 | Colivre <http://www.colivre.coop.br/> | 8 | Colivre <http://www.colivre.coop.br/> |
9 | +Copyright (c) the Noosfero contributors. See AUTHORS | ||
9 | 10 | ||
10 | This program is free software: you can redistribute it and/or modify | 11 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by | 12 | it under the terms of the GNU Affero General Public License as published by |
HACKING
@@ -52,3 +52,12 @@ If you write such script for your own OS, *please* share it with us at the | @@ -52,3 +52,12 @@ If you write such script for your own OS, *please* share it with us at the | ||
52 | development mailing list so that we can include it in the official repository. | 52 | development mailing list so that we can include it in the official repository. |
53 | This way other people using the same OS will have to put less effort to develop | 53 | This way other people using the same OS will have to put less effort to develop |
54 | Noosfero. | 54 | Noosfero. |
55 | + | ||
56 | +== Submitting your changes back | ||
57 | + | ||
58 | +For now please read: | ||
59 | + | ||
60 | +- Coding conventions | ||
61 | + http://noosfero.org/Development/CodingConventions | ||
62 | +- Patch guidelines | ||
63 | + http://noosfero.org/Development/PatchGuidelines |
HACKING.rails235
@@ -1,13 +0,0 @@ | @@ -1,13 +0,0 @@ | ||
1 | -This is a draft of how to create a environment to Rails 2.3.5 to Noosfero | ||
2 | -development. | ||
3 | - | ||
4 | -Install dependencies: | ||
5 | - | ||
6 | -gem install rails -v 2.3.5 | ||
7 | -gem install i18n | ||
8 | -gem install will_paginate -v 2.3.12 | ||
9 | -gem install cucumber | ||
10 | - | ||
11 | -Creating initial environment: | ||
12 | - | ||
13 | -rake db:schema:load |
INSTALL.chat
@@ -6,7 +6,7 @@ To configure XMPP/BOSH in Noosfero you need: | @@ -6,7 +6,7 @@ To configure XMPP/BOSH in Noosfero you need: | ||
6 | * SystemTimer - http://ph7spot.com/musings/system-timer | 6 | * SystemTimer - http://ph7spot.com/musings/system-timer |
7 | * Pidgin data files - http://www.pidgin.im/ | 7 | * Pidgin data files - http://www.pidgin.im/ |
8 | 8 | ||
9 | -If you use Debian Wheezy: | 9 | +If you use Debian 6.0 (squeeze): |
10 | 10 | ||
11 | # apt-get install librestclient-ruby pidgin-data ruby1.8-dev | 11 | # apt-get install librestclient-ruby pidgin-data ruby1.8-dev |
12 | # gem install SystemTimer | 12 | # gem install SystemTimer |
README
1 | -noosfero - a web-based social platform | 1 | +Noosfero - a web-based social platform |
2 | ====================================== | 2 | ====================================== |
3 | 3 | ||
4 | -:: About the project | 4 | +http://www.noosfero.org/ |
5 | 5 | ||
6 | -Homepage: http://www.noosfero.org/ | 6 | +Documentation |
7 | +------------- | ||
7 | 8 | ||
8 | -:: Authors and copyright | 9 | +The following documentation is available: |
9 | 10 | ||
10 | -Authors: see file AUTHORS | ||
11 | -Copyright information: see file COPYRIGHT | ||
12 | -Full license text; see file COPYING | 11 | +File Purpose |
12 | +~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
13 | +INSTALL install instructions | ||
14 | +INSTALL.awstats install instructions - access statistics service | ||
15 | +INSTALL.chat install instructions - chat service | ||
16 | +INSTALL.email install instructions - email service | ||
17 | +INSTALL.multitenancy install instructions - multiple sites | ||
18 | +INSTALL.varnish install instructions - varnish HTTP caching (recommended) | ||
19 | +HACKING development instruction | ||
20 | +RELEASING instructions for doing releases | ||
21 | +doc/noosfero/* user documentation (available through the app itself) | ||
22 | + | ||
23 | + | ||
24 | +Authors and copyright | ||
25 | +--------------------- | ||
26 | + | ||
27 | +Authorship and copyright information is available in the files listed below. | ||
28 | + | ||
29 | +File Purpose | ||
30 | +~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
31 | +AUTHORS list of authors (updated at each release) | ||
32 | +COPYRIGHT Copyright statement for the project | ||
33 | +COPYING Full text of the project license |
app/controllers/my_profile/cms_controller.rb
@@ -144,10 +144,15 @@ class CmsController < MyProfileController | @@ -144,10 +144,15 @@ class CmsController < MyProfileController | ||
144 | 144 | ||
145 | post_only :set_home_page | 145 | post_only :set_home_page |
146 | def set_home_page | 146 | def set_home_page |
147 | - @article = profile.articles.find(params[:id]) | ||
148 | - profile.home_page = @article | ||
149 | - profile.save(false) | ||
150 | - session[:notice] = _('"%s" configured as home page.') % @article.name | 147 | + article = params[:id].nil? ? nil : profile.articles.find(params[:id]) |
148 | + profile.update_attribute(:home_page, article) | ||
149 | + | ||
150 | + if article.nil? | ||
151 | + session[:notice] = _('Homepage reseted.') | ||
152 | + else | ||
153 | + session[:notice] = _('"%s" configured as homepage.') % article.name | ||
154 | + end | ||
155 | + | ||
151 | redirect_to (request.referer || profile.url) | 156 | redirect_to (request.referer || profile.url) |
152 | end | 157 | end |
153 | 158 | ||
@@ -267,7 +272,10 @@ class CmsController < MyProfileController | @@ -267,7 +272,10 @@ class CmsController < MyProfileController | ||
267 | @back_to = params[:back_to] || request.referer || url_for(profile.public_profile_url) | 272 | @back_to = params[:back_to] || request.referer || url_for(profile.public_profile_url) |
268 | @task = SuggestArticle.new(params[:task]) | 273 | @task = SuggestArticle.new(params[:task]) |
269 | if request.post? | 274 | if request.post? |
270 | - @task.target = profile | 275 | + @task.target = profile |
276 | + @task.ip_address = request.remote_ip | ||
277 | + @task.user_agent = request.user_agent | ||
278 | + @task.referrer = request.referrer | ||
271 | if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save | 279 | if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save |
272 | session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') | 280 | session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') |
273 | redirect_to @back_to | 281 | redirect_to @back_to |
app/controllers/my_profile/memberships_controller.rb
@@ -9,9 +9,10 @@ class MembershipsController < MyProfileController | @@ -9,9 +9,10 @@ class MembershipsController < MyProfileController | ||
9 | def new_community | 9 | def new_community |
10 | @community = Community.new(params[:community]) | 10 | @community = Community.new(params[:community]) |
11 | @community.environment = environment | 11 | @community.environment = environment |
12 | + @back_to = params[:back_to] || url_for(:action => 'index') | ||
12 | if request.post? && @community.valid? | 13 | if request.post? && @community.valid? |
13 | @community = Community.create_after_moderation(user, {:environment => environment}.merge(params[:community])) | 14 | @community = Community.create_after_moderation(user, {:environment => environment}.merge(params[:community])) |
14 | - redirect_to :action => 'index' | 15 | + redirect_to @back_to |
15 | return | 16 | return |
16 | end | 17 | end |
17 | end | 18 | end |
app/controllers/my_profile/profile_editor_controller.rb
@@ -4,7 +4,7 @@ class ProfileEditorController < MyProfileController | @@ -4,7 +4,7 @@ class ProfileEditorController < MyProfileController | ||
4 | protect 'destroy_profile', :profile, :only => [:destroy_profile] | 4 | protect 'destroy_profile', :profile, :only => [:destroy_profile] |
5 | 5 | ||
6 | def index | 6 | def index |
7 | - @pending_tasks = Task.to(profile).pending.select{|i| user.has_permission?(i.permission, profile)} | 7 | + @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)} |
8 | end | 8 | end |
9 | 9 | ||
10 | helper :profile | 10 | helper :profile |
app/controllers/my_profile/spam_controller.rb
@@ -14,9 +14,15 @@ class SpamController < MyProfileController | @@ -14,9 +14,15 @@ class SpamController < MyProfileController | ||
14 | if params[:remove_comment] | 14 | if params[:remove_comment] |
15 | profile.comments_received.find(params[:remove_comment]).destroy | 15 | profile.comments_received.find(params[:remove_comment]).destroy |
16 | end | 16 | end |
17 | + if params[:remove_task] | ||
18 | + Task.to(profile).find_by_id(params[:remove_task]).destroy | ||
19 | + end | ||
17 | if params[:mark_comment_as_ham] | 20 | if params[:mark_comment_as_ham] |
18 | profile.comments_received.find(params[:mark_comment_as_ham]).ham! | 21 | profile.comments_received.find(params[:mark_comment_as_ham]).ham! |
19 | end | 22 | end |
23 | + if params[:mark_task_as_ham] && (t = Task.to(profile).find_by_id(params[:mark_task_as_ham])) | ||
24 | + t.ham! | ||
25 | + end | ||
20 | if request.xhr? | 26 | if request.xhr? |
21 | json_response(true) | 27 | json_response(true) |
22 | else | 28 | else |
@@ -28,7 +34,8 @@ class SpamController < MyProfileController | @@ -28,7 +34,8 @@ class SpamController < MyProfileController | ||
28 | return | 34 | return |
29 | end | 35 | end |
30 | 36 | ||
31 | - @spam = profile.comments_received.spam.paginate({:page => params[:page]}) | 37 | + @comment_spam = profile.comments_received.spam.paginate({:page => params[:comments_page]}) |
38 | + @task_spam = Task.to(profile).spam.paginate({:page => params[:tasks_page]}) | ||
32 | end | 39 | end |
33 | 40 | ||
34 | protected | 41 | protected |
app/controllers/my_profile/tasks_controller.rb
@@ -4,12 +4,12 @@ class TasksController < MyProfileController | @@ -4,12 +4,12 @@ class TasksController < MyProfileController | ||
4 | 4 | ||
5 | def index | 5 | def index |
6 | @filter = params[:filter_type].blank? ? nil : params[:filter_type] | 6 | @filter = params[:filter_type].blank? ? nil : params[:filter_type] |
7 | - @tasks = Task.to(profile).pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | 7 | + @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) |
8 | @failed = params ? params[:failed] : {} | 8 | @failed = params ? params[:failed] : {} |
9 | end | 9 | end |
10 | 10 | ||
11 | def processed | 11 | def processed |
12 | - @tasks = Task.to(profile).closed.sort_by(&:created_at) | 12 | + @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) |
13 | end | 13 | end |
14 | 14 | ||
15 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] | 15 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] |
@@ -57,7 +57,7 @@ class TasksController < MyProfileController | @@ -57,7 +57,7 @@ class TasksController < MyProfileController | ||
57 | end | 57 | end |
58 | 58 | ||
59 | def list_requested | 59 | def list_requested |
60 | - @tasks = Task.find_all_by_requestor_id(profile.id) | 60 | + @tasks = Task.without_spam.find_all_by_requestor_id(profile.id) |
61 | end | 61 | end |
62 | 62 | ||
63 | def ticket_details | 63 | def ticket_details |
app/controllers/public/content_viewer_controller.rb
@@ -53,7 +53,9 @@ class ContentViewerController < ApplicationController | @@ -53,7 +53,9 @@ class ContentViewerController < ApplicationController | ||
53 | # At this point the page will be showed | 53 | # At this point the page will be showed |
54 | @page.hit | 54 | @page.hit |
55 | 55 | ||
56 | - unless @page.mime_type == 'text/html' || (@page.image? && params[:view]) | 56 | + @page = FilePresenter.for @page |
57 | + | ||
58 | + unless @page.mime_type == 'text/html' || params[:view] | ||
57 | headers['Content-Type'] = @page.mime_type | 59 | headers['Content-Type'] = @page.mime_type |
58 | data = @page.data | 60 | data = @page.data |
59 | 61 |
app/controllers/public/profile_controller.rb
@@ -206,10 +206,50 @@ class ProfileController < PublicController | @@ -206,10 +206,50 @@ class ProfileController < PublicController | ||
206 | end | 206 | end |
207 | 207 | ||
208 | def view_more_network_activities | 208 | def view_more_network_activities |
209 | - @activities = @profile.tracked_notifications.paginate(:per_page => 10, :page => params[:page]) | 209 | + @activities = @profile.tracked_notifications.paginate(:per_page => 10, :page => params[:page]) |
210 | render :partial => 'profile_network_activities', :locals => {:network_activities => @activities} | 210 | render :partial => 'profile_network_activities', :locals => {:network_activities => @activities} |
211 | end | 211 | end |
212 | 212 | ||
213 | + def more_comments | ||
214 | + activity = ActionTracker::Record.find(:first, :conditions => {:id => params[:activity], :user_id => @profile}) | ||
215 | + comments_count = activity.comments.count | ||
216 | + comment_page = (params[:comment_page] || 1).to_i | ||
217 | + comments_per_page = 5 | ||
218 | + no_more_pages = comments_count <= comment_page * comments_per_page | ||
219 | + | ||
220 | + render :update do |page| | ||
221 | + page.insert_html :bottom, 'profile-wall-activities-comments-'+params[:activity], | ||
222 | + :partial => 'comment', :collection => activity.comments.paginate(:per_page => comments_per_page, :page => comment_page) | ||
223 | + | ||
224 | + if no_more_pages | ||
225 | + page.remove 'profile-wall-activities-comments-more-'+params[:activity] | ||
226 | + else | ||
227 | + page.replace_html 'profile-wall-activities-comments-more-'+params[:activity], | ||
228 | + :partial => 'more_comments', :locals => {:activity => activity, :comment_page => comment_page} | ||
229 | + end | ||
230 | + end | ||
231 | + end | ||
232 | + | ||
233 | + def more_replies | ||
234 | + activity = Scrap.find(:first, :conditions => {:id => params[:activity], :receiver_id => @profile, :scrap_id => nil}) | ||
235 | + comments_count = activity.replies.count | ||
236 | + comment_page = (params[:comment_page] || 1).to_i | ||
237 | + comments_per_page = 5 | ||
238 | + no_more_pages = comments_count <= comment_page * comments_per_page | ||
239 | + | ||
240 | + render :update do |page| | ||
241 | + page.insert_html :bottom, 'profile-wall-activities-comments-'+params[:activity], | ||
242 | + :partial => 'profile_scrap', :collection => activity.replies.paginate(:per_page => comments_per_page, :page => comment_page), :as => :scrap | ||
243 | + | ||
244 | + if no_more_pages | ||
245 | + page.remove 'profile-wall-activities-comments-more-'+params[:activity] | ||
246 | + else | ||
247 | + page.replace_html 'profile-wall-activities-comments-more-'+params[:activity], | ||
248 | + :partial => 'more_replies', :locals => {:activity => activity, :comment_page => comment_page} | ||
249 | + end | ||
250 | + end | ||
251 | + end | ||
252 | + | ||
213 | def remove_scrap | 253 | def remove_scrap |
214 | begin | 254 | begin |
215 | scrap = current_user.person.scraps(params[:scrap_id]) | 255 | scrap = current_user.person.scraps(params[:scrap_id]) |
@@ -343,6 +383,7 @@ class ProfileController < PublicController | @@ -343,6 +383,7 @@ class ProfileController < PublicController | ||
343 | end | 383 | end |
344 | end | 384 | end |
345 | 385 | ||
386 | + | ||
346 | protected | 387 | protected |
347 | 388 | ||
348 | def check_access_to_profile | 389 | def check_access_to_profile |
@@ -393,4 +434,5 @@ class ProfileController < PublicController | @@ -393,4 +434,5 @@ class ProfileController < PublicController | ||
393 | def relations_to_include | 434 | def relations_to_include |
394 | [:image, :domains, :preferred_domain, :environment] | 435 | [:image, :domains, :preferred_domain, :environment] |
395 | end | 436 | end |
437 | + | ||
396 | end | 438 | end |
app/helpers/application_helper.rb
@@ -558,6 +558,9 @@ module ApplicationHelper | @@ -558,6 +558,9 @@ module ApplicationHelper | ||
558 | # displays a link to the profile homepage with its image (as generated by | 558 | # displays a link to the profile homepage with its image (as generated by |
559 | # #profile_image) and its name below it. | 559 | # #profile_image) and its name below it. |
560 | def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil ) | 560 | def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil ) |
561 | + if content = @plugins.dispatch_first(:profile_image_link, profile, size, tag, extra_info) | ||
562 | + return instance_eval(&content) | ||
563 | + end | ||
561 | name = profile.short_name | 564 | name = profile.short_name |
562 | if profile.person? | 565 | if profile.person? |
563 | url = url_for(profile.check_friendship_url) | 566 | url = url_for(profile.check_friendship_url) |
@@ -574,16 +577,16 @@ module ApplicationHelper | @@ -574,16 +577,16 @@ module ApplicationHelper | ||
574 | extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) | 577 | extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) |
575 | links = links_for_balloon(profile) | 578 | links = links_for_balloon(profile) |
576 | content_tag('div', content_tag(tag, | 579 | content_tag('div', content_tag(tag, |
577 | - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") + | ||
578 | - link_to( | ||
579 | - content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + | ||
580 | - content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + | ||
581 | - extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ), | ||
582 | - profile.url, | ||
583 | - :class => 'profile_link url', | ||
584 | - :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, | ||
585 | - :title => profile.name ), | ||
586 | - :class => 'vcard'), :class => 'common-profile-list-block') | 580 | + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") + |
581 | + link_to( | ||
582 | + content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + | ||
583 | + content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + | ||
584 | + extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ), | ||
585 | + profile.url, | ||
586 | + :class => 'profile_link url', | ||
587 | + :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, | ||
588 | + :title => profile.name ), | ||
589 | + :class => 'vcard'), :class => 'common-profile-list-block') | ||
587 | end | 590 | end |
588 | 591 | ||
589 | def gravatar_url_for(email, options = {}) | 592 | def gravatar_url_for(email, options = {}) |
@@ -1113,15 +1116,34 @@ module ApplicationHelper | @@ -1113,15 +1116,34 @@ module ApplicationHelper | ||
1113 | result | 1116 | result |
1114 | end | 1117 | end |
1115 | 1118 | ||
1116 | - def manage_enterprises | ||
1117 | - if user && !user.enterprises.empty? | ||
1118 | - enterprises_link = user.enterprises.map do |enterprise| | ||
1119 | - link_to(content_tag('strong', [_('<span>Manage</span> %s') % enterprise.short_name(25)]), @environment.top_url + "/myprofile/#{enterprise.identifier}", :class => "icon-menu-"+enterprise.class.identification.underscore, :title => [_('Manage %s') % enterprise.short_name]) | 1119 | + def manage_link(list, kind) |
1120 | + if list.present? | ||
1121 | + link_to_all = nil | ||
1122 | + if list.count > 5 | ||
1123 | + list = list.first(5) | ||
1124 | + link_to_all = link_to(content_tag('strong', _('See all')), :controller => 'memberships', :profile => current_user.login) | ||
1125 | + end | ||
1126 | + link = list.map do |element| | ||
1127 | + link_to(content_tag('strong', [_('<span>Manage</span> %s') % element.short_name(25)]), @environment.top_url + "/myprofile/#{element.identifier}", :class => "icon-menu-"+element.class.identification.underscore, :title => [_('Manage %s') % element.short_name]) | ||
1120 | end | 1128 | end |
1121 | - render :partial => 'shared/manage_enterprises', :locals => {:enterprises_link => enterprises_link} | 1129 | + if link_to_all |
1130 | + link << link_to_all | ||
1131 | + end | ||
1132 | + render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s} | ||
1122 | end | 1133 | end |
1123 | end | 1134 | end |
1124 | 1135 | ||
1136 | + def manage_enterprises | ||
1137 | + return unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu) | ||
1138 | + manage_link(user.enterprises, :enterprises) | ||
1139 | + end | ||
1140 | + | ||
1141 | + def manage_communities | ||
1142 | + return unless user && user.environment.enabled?(:display_my_communities_on_user_menu) | ||
1143 | + administered_communities = user.communities.more_popular.select {|c| c.admins.include? user} | ||
1144 | + manage_link(administered_communities, :communities) | ||
1145 | + end | ||
1146 | + | ||
1125 | def usermenu_logged_in | 1147 | def usermenu_logged_in |
1126 | pending_tasks_count = '' | 1148 | pending_tasks_count = '' |
1127 | count = user ? Task.to(user).pending.count : -1 | 1149 | count = user ? Task.to(user).pending.count : -1 |
@@ -1133,6 +1155,7 @@ module ApplicationHelper | @@ -1133,6 +1155,7 @@ module ApplicationHelper | ||
1133 | render_environment_features(:usermenu) + | 1155 | render_environment_features(:usermenu) + |
1134 | link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', @environment.top_url + '/admin', :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') + | 1156 | link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', @environment.top_url + '/admin', :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') + |
1135 | manage_enterprises.to_s + | 1157 | manage_enterprises.to_s + |
1158 | + manage_communities.to_s + | ||
1136 | link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', @environment.top_url + '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) + | 1159 | link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', @environment.top_url + '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) + |
1137 | pending_tasks_count + | 1160 | pending_tasks_count + |
1138 | link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) | 1161 | link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) |
@@ -1401,8 +1424,8 @@ module ApplicationHelper | @@ -1401,8 +1424,8 @@ module ApplicationHelper | ||
1401 | end | 1424 | end |
1402 | 1425 | ||
1403 | def filter_html(html, source) | 1426 | def filter_html(html, source) |
1404 | - if @plugins | ||
1405 | - html = convert_macro(html, source) | 1427 | + if @plugins && source && source.has_macro? |
1428 | + html = convert_macro(html, source) unless @plugins.enabled_macros.blank? | ||
1406 | #TODO This parse should be done through the macro infra, but since there | 1429 | #TODO This parse should be done through the macro infra, but since there |
1407 | # are old things that do not support it we are keeping this hot spot. | 1430 | # are old things that do not support it we are keeping this hot spot. |
1408 | html = @plugins.pipeline(:parse_content, html, source).first | 1431 | html = @plugins.pipeline(:parse_content, html, source).first |
app/helpers/blog_helper.rb
@@ -42,7 +42,7 @@ module BlogHelper | @@ -42,7 +42,7 @@ module BlogHelper | ||
42 | 42 | ||
43 | def display_post(article, format = 'full') | 43 | def display_post(article, format = 'full') |
44 | no_comments = (format == 'full') ? false : true | 44 | no_comments = (format == 'full') ? false : true |
45 | - html = send("display_#{format}_format", article).html_safe | 45 | + html = send("display_#{format}_format", FilePresenter.for(article)).html_safe |
46 | 46 | ||
47 | article_title(article, :no_comments => no_comments) + html | 47 | article_title(article, :no_comments => no_comments) + html |
48 | end | 48 | end |
app/helpers/boxes_helper.rb
@@ -100,9 +100,7 @@ module BoxesHelper | @@ -100,9 +100,7 @@ module BoxesHelper | ||
100 | options[:title] = _("This block is invisible. Your visitors will not see it.") | 100 | options[:title] = _("This block is invisible. Your visitors will not see it.") |
101 | end | 101 | end |
102 | 102 | ||
103 | - if @controller.send(:content_editor?) | ||
104 | - result = filter_html(result, block) | ||
105 | - end | 103 | + result = filter_html(result, block) |
106 | 104 | ||
107 | box_decorator.block_target(block.box, block) + | 105 | box_decorator.block_target(block.box, block) + |
108 | content_tag('div', | 106 | content_tag('div', |
app/helpers/categories_helper.rb
@@ -3,10 +3,21 @@ module CategoriesHelper | @@ -3,10 +3,21 @@ module CategoriesHelper | ||
3 | 3 | ||
4 | COLORS = [ | 4 | COLORS = [ |
5 | [ N_('Do not display at the menu'), nil ], | 5 | [ N_('Do not display at the menu'), nil ], |
6 | - [ N_('Orange'), 1 ], | ||
7 | - [ N_('Green'), 2 ], | ||
8 | - [ N_('Purple'), 3 ], | ||
9 | - [ N_('Red'), 4 ], | 6 | + [ N_('Orange'), 1], |
7 | + [ N_('Green'), 2], | ||
8 | + [ N_('Purple'), 3], | ||
9 | + [ N_('Red'), 4], | ||
10 | + [ N_('Dark Green'), 5], | ||
11 | + [ N_('Blue Oil'), 6], | ||
12 | + [ N_('Blue'), 7], | ||
13 | + [ N_('Brown'), 8], | ||
14 | + [ N_('Light Green'), 9], | ||
15 | + [ N_('Light Blue'), 10], | ||
16 | + [ N_('Dark Blue'), 11], | ||
17 | + [ N_('Blue Pool'), 12], | ||
18 | + [ N_('Beige'), 13], | ||
19 | + [ N_('Yellow'), 14], | ||
20 | + [ N_('Light Brown'), 15] | ||
10 | ] | 21 | ] |
11 | 22 | ||
12 | TYPES = [ | 23 | TYPES = [ |
app/helpers/cms_helper.rb
@@ -33,7 +33,7 @@ module CmsHelper | @@ -33,7 +33,7 @@ module CmsHelper | ||
33 | link_to article_name, {:action => 'view', :id => article.id}, :class => icon_for_article(article) | 33 | link_to article_name, {:action => 'view', :id => article.id}, :class => icon_for_article(article) |
34 | else | 34 | else |
35 | if article.image? | 35 | if article.image? |
36 | - image_tag(icon_for_article(article)) + link_to(article_name, article.url) | 36 | + image_tag(icon_for_article(article)) + link_to(article_name, article.url) |
37 | else | 37 | else |
38 | link_to article_name, article.url, :class => icon_for_article(article) | 38 | link_to article_name, article.url, :class => icon_for_article(article) |
39 | end | 39 | end |
app/helpers/content_viewer_helper.rb
@@ -17,7 +17,7 @@ module ContentViewerHelper | @@ -17,7 +17,7 @@ module ContentViewerHelper | ||
17 | title = article.display_title if article.kind_of?(UploadedFile) && article.image? | 17 | title = article.display_title if article.kind_of?(UploadedFile) && article.image? |
18 | title = article.title if title.blank? | 18 | title = article.title if title.blank? |
19 | title = content_tag('h1', h(title), :class => 'title') | 19 | title = content_tag('h1', h(title), :class => 'title') |
20 | - if article.belongs_to_blog? | 20 | + if article.belongs_to_blog? || article.belongs_to_forum? |
21 | unless args[:no_link] | 21 | unless args[:no_link] |
22 | title = content_tag('h1', link_to(article.name, article.url), :class => 'title') | 22 | title = content_tag('h1', link_to(article.name, article.url), :class => 'title') |
23 | end | 23 | end |
app/helpers/folder_helper.rb
@@ -21,6 +21,7 @@ module FolderHelper | @@ -21,6 +21,7 @@ module FolderHelper | ||
21 | end | 21 | end |
22 | 22 | ||
23 | def display_article_in_listing(article, recursive = false, level = 0) | 23 | def display_article_in_listing(article, recursive = false, level = 0) |
24 | + article = FilePresenter.for article | ||
24 | article_link = if article.image? | 25 | article_link = if article.image? |
25 | link_to(' ' * (level * 4) + image_tag(icon_for_article(article)) + short_filename(article.name), article.url.merge(:view => true)) | 26 | link_to(' ' * (level * 4) + image_tag(icon_for_article(article)) + short_filename(article.name), article.url.merge(:view => true)) |
26 | else | 27 | else |
@@ -40,12 +41,15 @@ module FolderHelper | @@ -40,12 +41,15 @@ module FolderHelper | ||
40 | end | 41 | end |
41 | 42 | ||
42 | def icon_for_article(article) | 43 | def icon_for_article(article) |
43 | - icon = article.class.icon_name(article) | 44 | + article = FilePresenter.for article |
45 | + icon = article.respond_to?(:icon_name) ? | ||
46 | + article.icon_name : | ||
47 | + article.class.icon_name(article) | ||
44 | if (icon =~ /\//) | 48 | if (icon =~ /\//) |
45 | icon | 49 | icon |
46 | else | 50 | else |
47 | - klasses = 'icon icon-' + icon | ||
48 | - if article.kind_of?(UploadedFile) | 51 | + klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ') |
52 | + if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) | ||
49 | klasses += ' icon-upload-file' | 53 | klasses += ' icon-upload-file' |
50 | end | 54 | end |
51 | klasses | 55 | klasses |
app/helpers/sweeper_helper.rb
@@ -44,4 +44,30 @@ module SweeperHelper | @@ -44,4 +44,30 @@ module SweeperHelper | ||
44 | def expire_profile_index(profile) | 44 | def expire_profile_index(profile) |
45 | expire_timeout_fragment(profile.relationships_cache_key) | 45 | expire_timeout_fragment(profile.relationships_cache_key) |
46 | end | 46 | end |
47 | + | ||
48 | + def expire_blocks_cache(context, causes) | ||
49 | + if context.kind_of?(Profile) | ||
50 | + profile = context | ||
51 | + environment = profile.environment | ||
52 | + else | ||
53 | + environment = context | ||
54 | + profile = nil | ||
55 | + end | ||
56 | + | ||
57 | + blocks_to_expire = [] | ||
58 | + if profile | ||
59 | + profile.blocks.each {|block| | ||
60 | + conditions = block.class.expire_on | ||
61 | + blocks_to_expire << block unless (conditions[:profile] & causes).empty? | ||
62 | + } | ||
63 | + end | ||
64 | + environment.blocks.each {|block| | ||
65 | + conditions = block.class.expire_on | ||
66 | + blocks_to_expire << block unless (conditions[:environment] & causes).empty? | ||
67 | + } | ||
68 | + | ||
69 | + blocks_to_expire.uniq! | ||
70 | + BlockSweeper.expire_blocks(blocks_to_expire) | ||
71 | + end | ||
72 | + | ||
47 | end | 73 | end |
app/models/article.rb
@@ -2,6 +2,8 @@ require 'hpricot' | @@ -2,6 +2,8 @@ require 'hpricot' | ||
2 | 2 | ||
3 | class Article < ActiveRecord::Base | 3 | class Article < ActiveRecord::Base |
4 | 4 | ||
5 | + acts_as_having_image | ||
6 | + | ||
5 | SEARCHABLE_FIELDS = { | 7 | SEARCHABLE_FIELDS = { |
6 | :name => 10, | 8 | :name => 10, |
7 | :abstract => 3, | 9 | :abstract => 3, |
@@ -154,8 +156,12 @@ class Article < ActiveRecord::Base | @@ -154,8 +156,12 @@ class Article < ActiveRecord::Base | ||
154 | end | 156 | end |
155 | end | 157 | end |
156 | 158 | ||
159 | + def css_class_list | ||
160 | + [self.class.name.underscore.dasherize] | ||
161 | + end | ||
162 | + | ||
157 | def css_class_name | 163 | def css_class_name |
158 | - self.class.name.underscore.dasherize | 164 | + [css_class_list].flatten.compact.join(' ') |
159 | end | 165 | end |
160 | 166 | ||
161 | def pending_categorizations | 167 | def pending_categorizations |
@@ -310,6 +316,10 @@ class Article < ActiveRecord::Base | @@ -310,6 +316,10 @@ class Article < ActiveRecord::Base | ||
310 | def belongs_to_blog? | 316 | def belongs_to_blog? |
311 | self.parent and self.parent.blog? | 317 | self.parent and self.parent.blog? |
312 | end | 318 | end |
319 | + | ||
320 | + def belongs_to_forum? | ||
321 | + self.parent and self.parent.forum? | ||
322 | + end | ||
313 | 323 | ||
314 | def info_from_last_update | 324 | def info_from_last_update |
315 | last_comment = comments.last | 325 | last_comment = comments.last |
@@ -325,7 +335,7 @@ class Article < ActiveRecord::Base | @@ -325,7 +335,7 @@ class Article < ActiveRecord::Base | ||
325 | end | 335 | end |
326 | 336 | ||
327 | def view_url | 337 | def view_url |
328 | - @view_url ||= image? ? url.merge(:view => true) : url | 338 | + @view_url ||= is_a?(UploadedFile) ? url.merge(:view => true) : url |
329 | end | 339 | end |
330 | 340 | ||
331 | def comment_url_structure(comment, action = :edit) | 341 | def comment_url_structure(comment, action = :edit) |
@@ -673,6 +683,10 @@ class Article < ActiveRecord::Base | @@ -673,6 +683,10 @@ class Article < ActiveRecord::Base | ||
673 | 683 | ||
674 | delegate :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true | 684 | delegate :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true |
675 | 685 | ||
686 | + def has_macro? | ||
687 | + true | ||
688 | + end | ||
689 | + | ||
676 | private | 690 | private |
677 | 691 | ||
678 | def sanitize_tag_list | 692 | def sanitize_tag_list |
app/models/article_block.rb
@@ -12,7 +12,7 @@ class ArticleBlock < Block | @@ -12,7 +12,7 @@ class ArticleBlock < Block | ||
12 | block = self | 12 | block = self |
13 | lambda do | 13 | lambda do |
14 | block_title(block.title) + | 14 | block_title(block.title) + |
15 | - (block.article ? article_to_html(block.article, | 15 | + (block.article ? article_to_html(FilePresenter.for(block.article), |
16 | :gallery_view => false, | 16 | :gallery_view => false, |
17 | :inside_block => block, # For Blogs and folders | 17 | :inside_block => block, # For Blogs and folders |
18 | :format => block.visualization_format # For Articles and contents | 18 | :format => block.visualization_format # For Articles and contents |
@@ -23,7 +23,7 @@ class ArticleBlock < Block | @@ -23,7 +23,7 @@ class ArticleBlock < Block | ||
23 | def article_id | 23 | def article_id |
24 | self.settings[:article_id] | 24 | self.settings[:article_id] |
25 | end | 25 | end |
26 | - | 26 | + |
27 | def article_id= value | 27 | def article_id= value |
28 | self.settings[:article_id] = value.blank? ? nil : value.to_i | 28 | self.settings[:article_id] = value.blank? ? nil : value.to_i |
29 | end | 29 | end |
@@ -63,4 +63,9 @@ class ArticleBlock < Block | @@ -63,4 +63,9 @@ class ArticleBlock < Block | ||
63 | end | 63 | end |
64 | 64 | ||
65 | settings_items :visualization_format, :type => :string, :default => 'short' | 65 | settings_items :visualization_format, :type => :string, :default => 'short' |
66 | + | ||
67 | + def self.expire_on | ||
68 | + { :profile => [:article], :environment => [:article] } | ||
69 | + end | ||
70 | + | ||
66 | end | 71 | end |
app/models/block.rb
@@ -138,4 +138,19 @@ class Block < ActiveRecord::Base | @@ -138,4 +138,19 @@ class Block < ActiveRecord::Base | ||
138 | 4.hours | 138 | 4.hours |
139 | end | 139 | end |
140 | 140 | ||
141 | + def has_macro? | ||
142 | + false | ||
143 | + end | ||
144 | + | ||
145 | + # Override in your subclasses. | ||
146 | + # Define which events and context should cause the block cache to expire | ||
147 | + # Possible events are: :article, :profile, :friendship, :category | ||
148 | + # Possible contexts are: :profile, :environment | ||
149 | + def self.expire_on | ||
150 | + { | ||
151 | + :profile => [], | ||
152 | + :environment => [] | ||
153 | + } | ||
154 | + end | ||
155 | + | ||
141 | end | 156 | end |
app/models/blog_archives_block.rb
@@ -45,4 +45,7 @@ class BlogArchivesBlock < Block | @@ -45,4 +45,7 @@ class BlogArchivesBlock < Block | ||
45 | content_tag('div', link_to(_('Subscribe RSS Feed'), owner_blog.feed.url), :class => 'subscribe-feed') | 45 | content_tag('div', link_to(_('Subscribe RSS Feed'), owner_blog.feed.url), :class => 'subscribe-feed') |
46 | end | 46 | end |
47 | 47 | ||
48 | + def self.expire_on | ||
49 | + { :profile => [:article], :environment => [:article] } | ||
50 | + end | ||
48 | end | 51 | end |
app/models/categories_block.rb
app/models/category.rb
@@ -12,7 +12,7 @@ class Category < ActiveRecord::Base | @@ -12,7 +12,7 @@ class Category < ActiveRecord::Base | ||
12 | validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('%{fn} is already being used by another category.').fix_i18n | 12 | validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('%{fn} is already being used by another category.').fix_i18n |
13 | belongs_to :environment | 13 | belongs_to :environment |
14 | 14 | ||
15 | - validates_inclusion_of :display_color, :in => [ 1, 2, 3, 4, nil ] | 15 | + validates_inclusion_of :display_color, :in => 1..15, :allow_nil => true |
16 | validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('%{fn} was already assigned to another category.').fix_i18n | 16 | validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('%{fn} was already assigned to another category.').fix_i18n |
17 | 17 | ||
18 | # Finds all top level categories for a given environment. | 18 | # Finds all top level categories for a given environment. |
app/models/comment.rb
@@ -16,9 +16,7 @@ class Comment < ActiveRecord::Base | @@ -16,9 +16,7 @@ class Comment < ActiveRecord::Base | ||
16 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy | 16 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy |
17 | belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id' | 17 | belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id' |
18 | 18 | ||
19 | - named_scope :without_spam, :conditions => ['spam IS NULL OR spam = ?', false] | ||
20 | named_scope :without_reply, :conditions => ['reply_of_id IS NULL'] | 19 | named_scope :without_reply, :conditions => ['reply_of_id IS NULL'] |
21 | - named_scope :spam, :conditions => ['spam = ?', true] | ||
22 | 20 | ||
23 | # unauthenticated authors: | 21 | # unauthenticated authors: |
24 | validates_presence_of :name, :if => (lambda { |record| !record.email.blank? }) | 22 | validates_presence_of :name, :if => (lambda { |record| !record.email.blank? }) |
@@ -108,6 +106,17 @@ class Comment < ActiveRecord::Base | @@ -108,6 +106,17 @@ class Comment < ActiveRecord::Base | ||
108 | 106 | ||
109 | include Noosfero::Plugin::HotSpot | 107 | include Noosfero::Plugin::HotSpot |
110 | 108 | ||
109 | + include Spammable | ||
110 | + | ||
111 | + def after_spam! | ||
112 | + SpammerLogger.log(ip_address, self) | ||
113 | + Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) | ||
114 | + end | ||
115 | + | ||
116 | + def after_ham! | ||
117 | + Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham)) | ||
118 | + end | ||
119 | + | ||
111 | def verify_and_notify | 120 | def verify_and_notify |
112 | check_for_spam | 121 | check_for_spam |
113 | unless spam? | 122 | unless spam? |
@@ -115,10 +124,6 @@ class Comment < ActiveRecord::Base | @@ -115,10 +124,6 @@ class Comment < ActiveRecord::Base | ||
115 | end | 124 | end |
116 | end | 125 | end |
117 | 126 | ||
118 | - def check_for_spam | ||
119 | - plugins.dispatch(:check_comment_for_spam, self) | ||
120 | - end | ||
121 | - | ||
122 | def notify_by_mail | 127 | def notify_by_mail |
123 | if source.kind_of?(Article) && article.notify_comments? | 128 | if source.kind_of?(Article) && article.notify_comments? |
124 | if !notification_emails.empty? | 129 | if !notification_emails.empty? |
@@ -205,37 +210,6 @@ class Comment < ActiveRecord::Base | @@ -205,37 +210,6 @@ class Comment < ActiveRecord::Base | ||
205 | @rejected = true | 210 | @rejected = true |
206 | end | 211 | end |
207 | 212 | ||
208 | - def spam? | ||
209 | - !spam.nil? && spam | ||
210 | - end | ||
211 | - | ||
212 | - def ham? | ||
213 | - !spam.nil? && !spam | ||
214 | - end | ||
215 | - | ||
216 | - def spam! | ||
217 | - self.spam = true | ||
218 | - self.save! | ||
219 | - SpammerLogger.log(ip_address, self) | ||
220 | - Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) | ||
221 | - self | ||
222 | - end | ||
223 | - | ||
224 | - def ham! | ||
225 | - self.spam = false | ||
226 | - self.save! | ||
227 | - Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham)) | ||
228 | - self | ||
229 | - end | ||
230 | - | ||
231 | - def marked_as_spam | ||
232 | - plugins.dispatch(:comment_marked_as_spam, self) | ||
233 | - end | ||
234 | - | ||
235 | - def marked_as_ham | ||
236 | - plugins.dispatch(:comment_marked_as_ham, self) | ||
237 | - end | ||
238 | - | ||
239 | def need_moderation? | 213 | def need_moderation? |
240 | article.moderate_comments? && (author.nil? || article.author != author) | 214 | article.moderate_comments? && (author.nil? || article.author != author) |
241 | end | 215 | end |
app/models/environment.rb
@@ -127,7 +127,9 @@ class Environment < ActiveRecord::Base | @@ -127,7 +127,9 @@ class Environment < ActiveRecord::Base | ||
127 | 'captcha_for_logged_users' => _('Ask captcha when a logged user comments too'), | 127 | 'captcha_for_logged_users' => _('Ask captcha when a logged user comments too'), |
128 | 'skip_new_user_email_confirmation' => _('Skip e-mail confirmation for new users'), | 128 | 'skip_new_user_email_confirmation' => _('Skip e-mail confirmation for new users'), |
129 | 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), | 129 | 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), |
130 | - 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login') | 130 | + 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login'), |
131 | + 'display_my_communities_on_user_menu' => _('Display on menu the list of communities the user can manage'), | ||
132 | + 'display_my_enterprises_on_user_menu' => _('Display on menu the list of enterprises the user can manage') | ||
131 | } | 133 | } |
132 | end | 134 | end |
133 | 135 |
app/models/link_list_block.rb
@@ -33,6 +33,12 @@ class LinkListBlock < Block | @@ -33,6 +33,12 @@ class LinkListBlock < Block | ||
33 | ['chat', N_('Chat')] | 33 | ['chat', N_('Chat')] |
34 | ] | 34 | ] |
35 | 35 | ||
36 | + TARGET_OPTIONS = [ | ||
37 | + [N_('Same page'), '_self'], | ||
38 | + [N_('New tab'), '_blank'], | ||
39 | + [N_('New window'), '_new'], | ||
40 | + ] | ||
41 | + | ||
36 | settings_items :links, Array, :default => [] | 42 | settings_items :links, Array, :default => [] |
37 | 43 | ||
38 | before_save do |block| | 44 | before_save do |block| |
@@ -57,7 +63,7 @@ class LinkListBlock < Block | @@ -57,7 +63,7 @@ class LinkListBlock < Block | ||
57 | def link_html(link) | 63 | def link_html(link) |
58 | klass = 'icon-' + link[:icon] if link[:icon] | 64 | klass = 'icon-' + link[:icon] if link[:icon] |
59 | sanitize_link( | 65 | sanitize_link( |
60 | - link_to(link[:name], expand_address(link[:address]), :class => klass) | 66 | + link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass) |
61 | ) | 67 | ) |
62 | end | 68 | end |
63 | 69 |
app/models/raw_html_block.rb
@@ -10,4 +10,7 @@ class RawHTMLBlock < Block | @@ -10,4 +10,7 @@ class RawHTMLBlock < Block | ||
10 | (title.blank? ? '' : block_title(title)).html_safe + html.to_s.html_safe | 10 | (title.blank? ? '' : block_title(title)).html_safe + html.to_s.html_safe |
11 | end | 11 | end |
12 | 12 | ||
13 | + def has_macro? | ||
14 | + true | ||
15 | + end | ||
13 | end | 16 | end |
app/models/recent_documents_block.rb
app/models/spammer_logger.rb
@@ -6,6 +6,8 @@ class SpammerLogger < Logger | @@ -6,6 +6,8 @@ class SpammerLogger < Logger | ||
6 | if object | 6 | if object |
7 | if object.kind_of?(Comment) | 7 | if object.kind_of?(Comment) |
8 | @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n" | 8 | @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n" |
9 | + elsif object.kind_of?(SuggestArticle) | ||
10 | + @logger << "[#{Time.now.strftime('%F %T %z')}] SuggestArticle-id: #{object.id} IP: #{spammer_ip}\n" | ||
9 | end | 11 | end |
10 | else | 12 | else |
11 | @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n" | 13 | @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n" |
app/models/suggest_article.rb
@@ -11,6 +11,17 @@ class SuggestArticle < Task | @@ -11,6 +11,17 @@ class SuggestArticle < Task | ||
11 | settings_items :source, :type => String | 11 | settings_items :source, :type => String |
12 | settings_items :source_name, :type => String | 12 | settings_items :source_name, :type => String |
13 | settings_items :highlighted, :type => :boolean, :default => false | 13 | settings_items :highlighted, :type => :boolean, :default => false |
14 | + settings_items :ip_address, :type => String | ||
15 | + settings_items :user_agent, :type => String | ||
16 | + settings_items :referrer, :type => String | ||
17 | + | ||
18 | + after_create :schedule_spam_checking | ||
19 | + | ||
20 | + def schedule_spam_checking | ||
21 | + self.delay.check_for_spam | ||
22 | + end | ||
23 | + | ||
24 | + include Noosfero::Plugin::HotSpot | ||
14 | 25 | ||
15 | def sender | 26 | def sender |
16 | "#{name} (#{email})" | 27 | "#{name} (#{email})" |
@@ -61,4 +72,12 @@ class SuggestArticle < Task | @@ -61,4 +72,12 @@ class SuggestArticle < Task | ||
61 | _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name } | 72 | _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name } |
62 | end | 73 | end |
63 | 74 | ||
75 | + def after_spam! | ||
76 | + SpammerLogger.log(ip_address, self) | ||
77 | + self.delay.marked_as_spam | ||
78 | + end | ||
79 | + | ||
80 | + def after_ham! | ||
81 | + self.delay.marked_as_ham | ||
82 | + end | ||
64 | end | 83 | end |
app/models/tags_block.rb
app/models/task.rb
@@ -235,6 +235,8 @@ class Task < ActiveRecord::Base | @@ -235,6 +235,8 @@ class Task < ActiveRecord::Base | ||
235 | end | 235 | end |
236 | end | 236 | end |
237 | 237 | ||
238 | + include Spammable | ||
239 | + | ||
238 | protected | 240 | protected |
239 | 241 | ||
240 | # This method must be overrided in subclasses, and its implementation must do | 242 | # This method must be overrided in subclasses, and its implementation must do |
@@ -275,6 +277,7 @@ class Task < ActiveRecord::Base | @@ -275,6 +277,7 @@ class Task < ActiveRecord::Base | ||
275 | named_scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } | 277 | named_scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } |
276 | named_scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } | 278 | named_scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } |
277 | 279 | ||
280 | + | ||
278 | named_scope :to, lambda { |profile| | 281 | named_scope :to, lambda { |profile| |
279 | environment_condition = nil | 282 | environment_condition = nil |
280 | if profile.person? | 283 | if profile.person? |
app/models/uploaded_file.rb
@@ -41,7 +41,25 @@ class UploadedFile < Article | @@ -41,7 +41,25 @@ class UploadedFile < Article | ||
41 | end | 41 | end |
42 | 42 | ||
43 | def self.max_size | 43 | def self.max_size |
44 | - UploadedFile.attachment_options[:max_size] | 44 | + default = 5.megabytes |
45 | + | ||
46 | + multipliers = { | ||
47 | + :KB => :kilobytes, | ||
48 | + :MB => :megabytes, | ||
49 | + :GB => :gigabytes, | ||
50 | + :TB => :terabytes, | ||
51 | + } | ||
52 | + max_upload_size = NOOSFERO_CONF['max_upload_size'] | ||
53 | + | ||
54 | + if max_upload_size =~ /^(\d+(\.\d+)?)\s*(KB|MB|GB|TB)?$/ | ||
55 | + number = $1.to_f | ||
56 | + unit = $3 || :MB | ||
57 | + multiplier = multipliers[unit.to_sym] | ||
58 | + | ||
59 | + number.send(multiplier).to_i | ||
60 | + else | ||
61 | + default | ||
62 | + end | ||
45 | end | 63 | end |
46 | 64 | ||
47 | # FIXME need to define min/max file size | 65 | # FIXME need to define min/max file size |
@@ -52,20 +70,28 @@ class UploadedFile < Article | @@ -52,20 +70,28 @@ class UploadedFile < Article | ||
52 | has_attachment :storage => :file_system, | 70 | has_attachment :storage => :file_system, |
53 | :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, | 71 | :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, |
54 | :thumbnail_class => Thumbnail, | 72 | :thumbnail_class => Thumbnail, |
55 | - :max_size => 5.megabytes # remember to update validate message below | 73 | + :max_size => self.max_size |
56 | 74 | ||
57 | - validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n | 75 | + validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of %{size}").sub('%{size}', self.max_size.to_humanreadable).fix_i18n |
58 | 76 | ||
59 | delay_attachment_fu_thumbnails | 77 | delay_attachment_fu_thumbnails |
60 | 78 | ||
61 | postgresql_attachment_fu | 79 | postgresql_attachment_fu |
62 | 80 | ||
81 | + # Use this method only to get the generic icon for this kind of content. | ||
82 | + # If you want the specific icon for a file type or the iconified version | ||
83 | + # of an image, use FilePresenter.for(uploaded_file).icon_name | ||
63 | def self.icon_name(article = nil) | 84 | def self.icon_name(article = nil) |
64 | - if article | ||
65 | - article.image? ? article.public_filename(:icon) : (article.mime_type ? article.mime_type.gsub(/[\/+.]/, '-') : 'upload-file') | ||
66 | - else | ||
67 | - 'upload-file' | 85 | + unless article.nil? |
86 | + warn = ('='*80) + "\n" + | ||
87 | + 'The method `UploadedFile.icon_name(obj)` is deprecated. ' + | ||
88 | + 'You must to encapsulate UploadedFile with `FilePresenter.for()`.' + | ||
89 | + "\n" + ('='*80) | ||
90 | + raise NoMethodError, warn if ENV['RAILS_ENV'] == 'test' | ||
91 | + Rails.logger.warn warn if Rails.logger | ||
92 | + puts warn if ENV['RAILS_ENV'] == 'development' | ||
68 | end | 93 | end |
94 | + 'upload-file' | ||
69 | end | 95 | end |
70 | 96 | ||
71 | def mime_type | 97 | def mime_type |
@@ -91,40 +117,27 @@ class UploadedFile < Article | @@ -91,40 +117,27 @@ class UploadedFile < Article | ||
91 | end | 117 | end |
92 | 118 | ||
93 | def to_html(options = {}) | 119 | def to_html(options = {}) |
120 | + warn = ('='*80) + "\n" + | ||
121 | + 'The method `UploadedFile#to_html()` is deprecated. ' + | ||
122 | + 'You must to encapsulate UploadedFile with `FilePresenter.for()`.' + | ||
123 | + "\n" + ('='*80) | ||
124 | + raise NoMethodError, warn if ENV['RAILS_ENV'] == 'test' | ||
125 | + Rails.logger.warn warn if Rails.logger | ||
126 | + puts warn if ENV['RAILS_ENV'] == 'development' | ||
94 | article = self | 127 | article = self |
95 | if image? | 128 | if image? |
96 | lambda do | 129 | lambda do |
97 | - if article.gallery? && options[:gallery_view] | ||
98 | - images = article.parent.images | ||
99 | - current_index = images.index(article) | ||
100 | - total_of_images = images.count | ||
101 | - | ||
102 | - link_to_previous = if current_index >= 1 | ||
103 | - link_to(_('« Previous'), images[current_index - 1].view_url, :class => 'left') | ||
104 | - else | ||
105 | - content_tag('span', _('« Previous'), :class => 'left') | ||
106 | - end | ||
107 | - | ||
108 | - link_to_next = if current_index < total_of_images - 1 | ||
109 | - link_to(_('Next »'), images[current_index + 1].view_url, :class => 'right') | ||
110 | - else | ||
111 | - content_tag('span', _('Next »'), :class => 'right') | ||
112 | - end | ||
113 | - | ||
114 | - content_tag( | ||
115 | - 'div', | ||
116 | - link_to_previous + (content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images]).html_safe + link_to_next, | ||
117 | - :class => 'gallery-navigation' | ||
118 | - ) | ||
119 | - end.to_s + | ||
120 | - image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') + | ||
121 | - content_tag('p', article.abstract, :class => 'uploaded-file-description') | ||
122 | - | 130 | + image_tag(article.public_filename(:display), |
131 | + :class => article.css_class_name, | ||
132 | + :style => 'max-width: 100%') + | ||
133 | + content_tag('div', article.abstract, :class => 'uploaded-file-description') | ||
123 | end | 134 | end |
124 | else | 135 | else |
125 | lambda do | 136 | lambda do |
126 | - content_tag('ul', content_tag('li', link_to(article.name, article.url, :class => article.css_class_name))) + | ||
127 | - content_tag('p', article.abstract, :class => 'uploaded-file-description') | 137 | + content_tag('div', |
138 | + link_to(article.name, article.url), | ||
139 | + :class => article.css_class_name) + | ||
140 | + content_tag('div', article.abstract, :class => 'uploaded-file-description') | ||
128 | end | 141 | end |
129 | end | 142 | end |
130 | end | 143 | end |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +class FilePresenter::Image < FilePresenter | ||
2 | + def self.accepts?(f) | ||
3 | + return nil unless f.respond_to? :image? | ||
4 | + f.image? ? 10 : nil | ||
5 | + end | ||
6 | + | ||
7 | + def icon_name | ||
8 | + public_filename :icon | ||
9 | + end | ||
10 | + | ||
11 | + def short_description | ||
12 | + _('Image (%s)') % content_type.split('/')[1].upcase | ||
13 | + end | ||
14 | +end |
app/sweepers/article_sweeper.rb
@@ -16,15 +16,15 @@ class ArticleSweeper < ActiveRecord::Observer | @@ -16,15 +16,15 @@ class ArticleSweeper < ActiveRecord::Observer | ||
16 | end | 16 | end |
17 | end | 17 | end |
18 | 18 | ||
19 | + | ||
19 | protected | 20 | protected |
20 | 21 | ||
21 | def expire_caches(article) | 22 | def expire_caches(article) |
23 | + expire_blocks_cache(article.profile, [:article]) | ||
24 | + | ||
22 | return if !article.environment | 25 | return if !article.environment |
26 | + | ||
23 | article.hierarchy(true).each { |a| a.touch if a != article } | 27 | article.hierarchy(true).each { |a| a.touch if a != article } |
24 | - blocks = article.profile.blocks | ||
25 | - blocks += article.profile.environment.blocks if article.profile.environment | ||
26 | - blocks = blocks.select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}} | ||
27 | - BlockSweeper.expire_blocks(blocks) | ||
28 | env = article.profile.environment | 28 | env = article.profile.environment |
29 | if env && (env.portal_community == article.profile) | 29 | if env && (env.portal_community == article.profile) |
30 | article.environment.locales.keys.each do |locale| | 30 | article.environment.locales.keys.each do |locale| |
app/sweepers/category_sweeper.rb
@@ -3,7 +3,13 @@ class CategorySweeper < ActiveRecord::Observer | @@ -3,7 +3,13 @@ class CategorySweeper < ActiveRecord::Observer | ||
3 | include SweeperHelper | 3 | include SweeperHelper |
4 | 4 | ||
5 | def after_save(category) | 5 | def after_save(category) |
6 | + expire_blocks_cache(category.environment, [:category]) | ||
7 | + | ||
8 | + # Needed for environments with application layout | ||
6 | expire_fragment(category.environment.id.to_s + "_categories_menu") | 9 | expire_fragment(category.environment.id.to_s + "_categories_menu") |
7 | end | 10 | end |
8 | 11 | ||
12 | + def after_destroy(category) | ||
13 | + expire_blocks_cache(category.environment, [:category]) | ||
14 | + end | ||
9 | end | 15 | end |
app/views/box_organizer/_link_list_block.rhtml
1 | <strong><%= _('Links') %></strong> | 1 | <strong><%= _('Links') %></strong> |
2 | <div id='edit-link-list-block' style='width:450px'> | 2 | <div id='edit-link-list-block' style='width:450px'> |
3 | <table id='links' class='noborder'> | 3 | <table id='links' class='noborder'> |
4 | - <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th></tr> | 4 | + <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th><th><%= _('Target') %></th></tr> |
5 | <% for link in @block.links do %> | 5 | <% for link in @block.links do %> |
6 | <tr> | 6 | <tr> |
7 | <td> | 7 | <td> |
@@ -9,6 +9,9 @@ | @@ -9,6 +9,9 @@ | ||
9 | </td> | 9 | </td> |
10 | <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td> | 10 | <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td> |
11 | <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td> | 11 | <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td> |
12 | + <td> | ||
13 | + <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %> | ||
14 | + </td> | ||
12 | </tr> | 15 | </tr> |
13 | <% end %> | 16 | <% end %> |
14 | </table> | 17 | </table> |
@@ -18,7 +21,9 @@ | @@ -18,7 +21,9 @@ | ||
18 | page.insert_html :bottom, 'links', content_tag('tr', | 21 | page.insert_html :bottom, 'links', content_tag('tr', |
19 | content_tag('td', icon_selector('ok')) + | 22 | content_tag('td', icon_selector('ok')) + |
20 | content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) + | 23 | content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) + |
21 | - content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'cel-address')) | 24 | + content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') + |
25 | + content_tag('td', select_tag('block[links][][target]', | ||
26 | +options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target]))) | ||
22 | ) + | 27 | ) + |
23 | javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") | 28 | javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") |
24 | end %> | 29 | end %> |
app/views/cms/view.rhtml
@@ -2,6 +2,18 @@ | @@ -2,6 +2,18 @@ | ||
2 | <%= _('Content management') %> | 2 | <%= _('Content management') %> |
3 | </h1> | 3 | </h1> |
4 | 4 | ||
5 | +<% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> | ||
6 | + <div class="cms-homepage"> | ||
7 | + <%= _('Profile homepage:') %> | ||
8 | + <% if profile.home_page %> | ||
9 | + <%= link_to_article(profile.home_page) %> | ||
10 | + <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %> | ||
11 | + <% else %> | ||
12 | + <span class="cms-homepage-default"><%= _('Profile Information') %></span> | ||
13 | + <% end %> | ||
14 | + </div> | ||
15 | +<% end %> | ||
16 | + | ||
5 | <% button_bar(:style => 'margin-bottom: 1em;') do %> | 17 | <% button_bar(:style => 'margin-bottom: 1em;') do %> |
6 | <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> | 18 | <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> |
7 | 19 | ||
@@ -40,20 +52,27 @@ | @@ -40,20 +52,27 @@ | ||
40 | </tr> | 52 | </tr> |
41 | <% end %> | 53 | <% end %> |
42 | 54 | ||
43 | - <% @articles.each do |article| %> | 55 | + <% @articles.each do |article| article = FilePresenter.for article %> |
44 | <tr title="<%= article.title%>" > | 56 | <tr title="<%= article.title%>" > |
45 | - <td> | 57 | + <td class="article-name"> |
46 | <%= link_to_article(article) %> | 58 | <%= link_to_article(article) %> |
47 | </td> | 59 | </td> |
48 | - <td> | ||
49 | - <%= article.class.short_description %> | 60 | + <% short_description = article.respond_to?(:short_description) ? |
61 | + article.short_description : | ||
62 | + article.class.short_description %> | ||
63 | + <td class="article-mime" title=<%= short_description.to_json %>> | ||
64 | + <%= short_description %> | ||
50 | </td> | 65 | </td> |
51 | <td class="article-controls"> | 66 | <td class="article-controls"> |
52 | <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> | 67 | <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> |
53 | <%= button_without_text :eyes, _('Public view'), article.view_url %> | 68 | <%= button_without_text :eyes, _('Public view'), article.view_url %> |
54 | <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> | 69 | <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> |
55 | <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> | 70 | <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> |
56 | - <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | 71 | + <% if profile.home_page != article %> |
72 | + <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | ||
73 | + <% else %> | ||
74 | + <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %> | ||
75 | + <% end %> | ||
57 | <% end %> | 76 | <% end %> |
58 | <%= display_delete_button(article) if !remove_content_button(:delete) %> | 77 | <%= display_delete_button(article) if !remove_content_button(:delete) %> |
59 | </td> | 78 | </td> |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +<span class="download-link"> | ||
2 | + <span>Download</span> | ||
3 | + <strong><%= link_to generic.filename, generic.public_filename %></strong> | ||
4 | +</span> | ||
5 | + | ||
6 | +<div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>"> | ||
7 | + <%= generic.abstract %> | ||
8 | +</div> | ||
9 | + |
@@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
1 | +<% if image.gallery? && options[:gallery_view] %> | ||
2 | +<% | ||
3 | + images = image.parent.images | ||
4 | + current_index = images.index(image.encapsulated_file) | ||
5 | + total_of_images = images.count | ||
6 | + link_to_previous = if current_index >= 1 | ||
7 | + link_to(_('« Previous'), images[current_index - 1].view_url, :class => 'previous') | ||
8 | + else | ||
9 | + content_tag('span', _('« Previous'), :class => 'previous') | ||
10 | + end | ||
11 | + | ||
12 | + link_to_next = if current_index < total_of_images - 1 | ||
13 | + link_to(_('Next »'), images[current_index + 1].view_url, :class => 'next') | ||
14 | + else | ||
15 | + content_tag('span', _('Next »'), :class => 'next') | ||
16 | + end | ||
17 | +%> | ||
18 | + | ||
19 | +<div class="gallery-navigation"> | ||
20 | + <%= link_to_previous %> | ||
21 | + <span class="total-of-images"> | ||
22 | + <%= _('image %d of %d') % [current_index + 1, total_of_images] %> | ||
23 | + </span> | ||
24 | + <%= link_to_next %> | ||
25 | +</div> | ||
26 | + | ||
27 | +<% end %> | ||
28 | + | ||
29 | +<%# image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') %> | ||
30 | + | ||
31 | +<img src="<%=image.public_filename(:display)%>" class="<%=image.css_class_name%>"> | ||
32 | + | ||
33 | +<div class="uploaded-file-description <%= 'empty' if image.abstract.blank? %>"> | ||
34 | + <%= image.abstract %> | ||
35 | +</div> | ||
36 | + |
app/views/memberships/new_community.rhtml
@@ -46,9 +46,11 @@ | @@ -46,9 +46,11 @@ | ||
46 | 46 | ||
47 | <%= template_options(Community, 'community')%> | 47 | <%= template_options(Community, 'community')%> |
48 | 48 | ||
49 | + <%= hidden_field_tag('back_to', @back_to) %> | ||
50 | + | ||
49 | <% button_bar do %> | 51 | <% button_bar do %> |
50 | <%= submit_button(:save, _('Create')) %> | 52 | <%= submit_button(:save, _('Create')) %> |
51 | - <%= button(:cancel, _('Cancel'), :action => 'index') %> | 53 | + <%= button(:cancel, _('Cancel'), @back_to ) %> |
52 | <% end %> | 54 | <% end %> |
53 | 55 | ||
54 | <% end %> | 56 | <% end %> |
app/views/profile/_profile_activities_list.rhtml
@@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
4 | <% if activity.kind_of?(ActionTracker::Record) %> | 4 | <% if activity.kind_of?(ActionTracker::Record) %> |
5 | <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %> | 5 | <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %> |
6 | <% else %> | 6 | <% else %> |
7 | - <%= render :partial => 'profile_scrap', :locals => {:scrap => activity } %> | 7 | + <%= render :partial => 'profile_scraps', :locals => { :activity => activity, :scrap => activity } %> |
8 | <% end %> | 8 | <% end %> |
9 | <% end %> | 9 | <% end %> |
10 | <% end %> | 10 | <% end %> |
app/views/profile/_profile_comments.rhtml
1 | <hr /> | 1 | <hr /> |
2 | 2 | ||
3 | -<% if activity.comments_count > 2 %> | 3 | +<ul id="profile-wall-activities-comments-<%= activity.id %>" class="profile-wall-activities-comments" > |
4 | +</ul> | ||
5 | +<% if activity.comments_count > 0 %> | ||
6 | +<div id="profile-wall-activities-comments-more-<%= activity.id %>" class="profile-wall-activities-comments" > | ||
4 | <div class='view-all-comments icon-chat'> | 7 | <div class='view-all-comments icon-chat'> |
5 | - <%= link_to(_("View all %s comments") % activity.comments_count, '#') %> | 8 | + <%= link_to(n_('View comment', "View all %s comments", activity.comments_count) % activity.comments_count, :profile => profile.identifier, :controller => 'profile', :action => 'more_comments', :activity => activity, :comment_page => (1)) %> |
6 | </div> | 9 | </div> |
10 | +</div> | ||
7 | <% end %> | 11 | <% end %> |
8 | - | ||
9 | -<ul class="profile-wall-activities-comments" style="<%= 'display:none;' if (activity.comments_count > 2) %>" > | ||
10 | - <%= render :partial => 'comment', :collection => activity.comments_as_thread %> | ||
11 | -</ul> | ||
12 | - | ||
13 | <%= render :partial => 'profile_comment_form', :locals => { :activity => activity, :tab_action => tab_action } %> | 12 | <%= render :partial => 'profile_comment_form', :locals => { :activity => activity, :tab_action => tab_action } %> |
app/views/profile/_profile_scrap.rhtml
@@ -16,13 +16,7 @@ | @@ -16,13 +16,7 @@ | ||
16 | </div> | 16 | </div> |
17 | </div> | 17 | </div> |
18 | 18 | ||
19 | - <% if scrap.replies.count > 2 %> | ||
20 | - <div class='view-all-comments icon-chat'> | ||
21 | - <%= link_to(_("View all %s comments") % scrap.replies.count, '#') %> | ||
22 | - </div> | ||
23 | - <% end %> | ||
24 | - | ||
25 | - <ul class="profile-wall-activities-comments scrap-replies" style="width: auto; <%= 'display:none;' if (scrap.replies.count > 2) %>" > | 19 | + <ul class="profile-wall-activities-comments scrap-replies" style="width: auto;" > |
26 | <% scrap.replies.map do |reply| %> | 20 | <% scrap.replies.map do |reply| %> |
27 | <%= render :partial => 'profile_scrap', :locals => {:scrap => reply} %> | 21 | <%= render :partial => 'profile_scrap', :locals => {:scrap => reply} %> |
28 | <% end %> | 22 | <% end %> |
app/views/profile/_profile_scraps.rhtml
1 | -NÃO DEVE APARECER | 1 | +<li class='profile-activity-item' id='profile-activity-item-<%= scrap.id %>'> |
2 | + <div class='profile-activity-image'> | ||
3 | + <%= link_to(profile_image(scrap.sender, :minor), scrap.sender.url) %> | ||
4 | + </div> | ||
5 | + <div class='profile-activity-description'> | ||
6 | + <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> | ||
7 | + <p class='profile-activity-text'><%= txt2html scrap.content %></p> | ||
8 | + <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p> | ||
9 | + <div class='profile-wall-actions'> | ||
10 | + <% if logged_in? && current_person.follows?(scrap.sender) %> | ||
11 | + <span class='profile-activity-send-reply'> | ||
12 | + <%= link_to_function s_('profile|Comment'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);$('reply_content_#{scrap.id}').value='';$('reply_content_#{scrap.id}').focus();return false", :class => "profile-send-reply" %> | ||
13 | + </span> | ||
14 | + <% end %> | ||
15 | + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.profile-activity-item'", url_for(:profile => params[:profile], :action => :remove_scrap, :scrap_id => scrap.id, :view => params[:view]).to_json, _('Are you sure you want to remove this scrap and all its replies?').to_json]) if logged_in? && user.can_control_scrap?(scrap) %> | ||
16 | + </div> | ||
17 | + </div> | ||
18 | + | ||
19 | + | ||
20 | + <ul id="profile-wall-activities-comments-<%= activity.id %>" class="profile-wall-activities-comments scrap-replies" style="width: auto;" > | ||
21 | + </ul> | ||
22 | + | ||
23 | + <% if scrap.replies.count > 0 %> | ||
24 | + <div id="profile-wall-activities-comments-more-<%= activity.id %>" class="profile-wall-activities-comments"> | ||
25 | + <div class='view-all-comments icon-chat'> | ||
26 | + <%= link_to(n_('View comment', "View all %s comments", scrap.replies.count) % scrap.replies.count, :profile => profile.identifier, :controller => 'profile', :action => 'more_replies', :activity => activity, :comment_page => (1)) %> | ||
27 | + </div> | ||
28 | + </div> | ||
29 | + <% end %> | ||
30 | + <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %> | ||
31 | + <hr /> | ||
32 | +</li> |
app/views/shared/_manage_enterprises.rhtml
@@ -1,8 +0,0 @@ | @@ -1,8 +0,0 @@ | ||
1 | -<div id='manage-enterprises'> | ||
2 | - <a href="#" id='manage-enterprises-link' class='simplemenu-trigger' title='<%= _('Manage enterprises') %>'><i class="icon-menu-enterprise"></i><strong><%= ui_icon('ui-icon-triangle-1-s') + _('My enterprises') %></strong></a> | ||
3 | - <ul class='simplemenu-submenu'> | ||
4 | - <% enterprises_link.each do |link| %> | ||
5 | - <li class='simplemenu-item'><%= link %></li> | ||
6 | - <% end %> | ||
7 | - </ul> | ||
8 | -</div> |
@@ -0,0 +1,8 @@ | @@ -0,0 +1,8 @@ | ||
1 | +<div id=<%= "manage-#{kind}" %> class="manage-groups"> | ||
2 | + <a href="#" id=<%= "manage-#{kind}-link" %> class="simplemenu-trigger" title="<%= _('Manage %s') % kind %>"><i class=<%= "icon-menu-#{kind.singularize}" %>></i><strong><%= ui_icon('ui-icon-triangle-1-s') + _('My %s') % kind %></strong></a> | ||
3 | + <ul class="simplemenu-submenu"> | ||
4 | + <% link.each do |link| %> | ||
5 | + <li class="simplemenu-item"><%= link %></li> | ||
6 | + <% end %> | ||
7 | + </ul> | ||
8 | +</div> |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +<%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> | ||
2 | +<div id='article'> | ||
3 | + <div class="comments" id="comments_list"> | ||
4 | + <ul class="article-comments-list"> | ||
5 | + <%= render :partial => 'comment/comment', :collection => @comment_spam %> | ||
6 | + </ul> | ||
7 | + </div> | ||
8 | +</div> | ||
9 | + | ||
10 | +<%= pagination_links @comment_spam, :param_name => :comments_page %> | ||
11 | + |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +<% render :layout => 'task', :locals => { :task => task } do %> | ||
2 | + <% content_for :extra_buttons do %> | ||
3 | + <%= button_to_function('down', _('Show details'), "toggleDetails(this, '#{_('Hide details')}', '#{_('Show details')}')" ) %> | ||
4 | + <% end %> | ||
5 | + | ||
6 | + <% content_for :extra_content do %> | ||
7 | + <ul class="suggest-article-details" style="display: none"> | ||
8 | + <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li> | ||
9 | + <li><strong><%=_('Email')%></strong>: <%=task.email%> </li> | ||
10 | + <li><strong><%=_('Source')%></strong>: <%=task.source_name%> </li> | ||
11 | + <li><strong><%=_('Source URL')%></strong>: <%=task.source%> </li> | ||
12 | + <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li> | ||
13 | + <li><strong><%=_('Lead')%></strong>: <%=task.article_abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_abstract%> </li> | ||
14 | + <li><strong><%=_('Body')%></strong>: | ||
15 | + <div class='suggest-article-body'> | ||
16 | + <%= task.article_body %> | ||
17 | + </div> | ||
18 | + </li> | ||
19 | + </ul> | ||
20 | + <% end %> | ||
21 | +<% end %> |
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | +<div class="task_box" id="task-<%= task.id %>"> | ||
2 | + <%= render :partial => 'tasks/task_icon', :locals => {:task => task} %> | ||
3 | + <%= render :partial => 'tasks/task_title', :locals => {:task => task} %> | ||
4 | + <div class="task-information"> | ||
5 | + <%= task_information(task) %> | ||
6 | + </div> | ||
7 | + | ||
8 | + <%= yield %> <% # ??? %> | ||
9 | + | ||
10 | + <% button_bar do %> | ||
11 | + <%= button_to_function('new', _('Mark as NOT SPAM'), 'removeTaskBox(this, %s, "%s", "")' % [url_for(:mark_task_as_ham => task.id).to_json, "task-#{task.id}"]) %> | ||
12 | + <%= yield :extra_buttons %> | ||
13 | + <%= button_to_function('delete', _('Remove'), 'removeTaskBox(this, %s, "%s", %s)' % [url_for(:profile => params[:profile], :remove_task => task.id).to_json, "task-#{task.id}", _('Are you sure you want to remove this article suggestion?').to_json]) %> | ||
14 | + | ||
15 | + <% end %> | ||
16 | + | ||
17 | + <%= yield :extra_content %> | ||
18 | +</div> |
app/views/spam/index.rhtml
1 | +<%= stylesheet('tasks') %> | ||
2 | + | ||
1 | <h1><%= _('Manage SPAM') %></h1> | 3 | <h1><%= _('Manage SPAM') %></h1> |
2 | 4 | ||
5 | +<% no_tabs = @comment_spam.blank? && @task_spam.blank? %> | ||
6 | + | ||
7 | +<%= _('There are no spams to review.') if no_tabs %> | ||
8 | + | ||
3 | <% button_bar do %> | 9 | <% button_bar do %> |
4 | <%= button :back, _('Back to control panel'), :controller => :profile_editor %> | 10 | <%= button :back, _('Back to control panel'), :controller => :profile_editor %> |
5 | <% end %> | 11 | <% end %> |
6 | 12 | ||
7 | <%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> | 13 | <%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> |
8 | -<div id='article'> | ||
9 | - <div class="comments" id="comments_list"> | ||
10 | - <ul class="article-comments-list"> | ||
11 | - <%= render :partial => 'comment/comment', :collection => @spam %> | ||
12 | - </ul> | ||
13 | - </div> | ||
14 | -</div> | ||
15 | 14 | ||
16 | -<%= pagination_links @spam %> | 15 | +<% tabs = [] %> |
16 | +<% tabs << {:title => _('Comment Spam'), :id => 'comment-spam', | ||
17 | + :content => (render :partial => 'comment_spam')} if @comment_spam.present? %> | ||
18 | +<% tabs << {:title => _('Task Spam'), :id => 'task-spam', | ||
19 | + :content => (render :partial => 'task_spam') } if @task_spam.present? %> | ||
20 | +<%= render_tabs(tabs) %> | ||
17 | 21 | ||
18 | -<% button_bar do %> | ||
19 | - <%= button :back, _('Back to control panel'), :controller => :profile_editor %> | 22 | +<% unless no_tabs %> |
23 | + <% button_bar do %> | ||
24 | + <%= button :back, _('Back to control panel'), :controller => :profile_editor %> | ||
25 | + <% end %> | ||
20 | <% end %> | 26 | <% end %> |
27 | + | ||
28 | +<%= javascript_include_tag 'spam' %> |
app/views/tasks/_task.rhtml
1 | <div class="task_box" id="task-<%= task.id %>"> | 1 | <div class="task_box" id="task-<%= task.id %>"> |
2 | 2 | ||
3 | - <div class="task_icon"> | ||
4 | - <% | ||
5 | - icon_info = task.icon | ||
6 | - if icon_info[:type] == :profile_image | ||
7 | - icon = profile_image(icon_info[:profile], :minor) | ||
8 | - elsif icon_info[:type] == :defined_image | ||
9 | - icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />" | ||
10 | - end | ||
11 | - %> | ||
12 | - <%= | ||
13 | - if icon_info[:url] | ||
14 | - link_to(icon, icon_info[:url]) | ||
15 | - else | ||
16 | - icon | ||
17 | - end | ||
18 | - %> | ||
19 | - | ||
20 | - </div> | 3 | + <%= render :partial => 'task_icon', :locals => {:task => task} %> |
21 | 4 | ||
22 | <div class="task_decisions"> | 5 | <div class="task_decisions"> |
23 | <%= | 6 | <%= |
@@ -39,9 +22,7 @@ | @@ -39,9 +22,7 @@ | ||
39 | %> | 22 | %> |
40 | </div><!-- class="task_decisions" --> | 23 | </div><!-- class="task_decisions" --> |
41 | 24 | ||
42 | - <strong class="task_title"> | ||
43 | - <%= task.title %> | ||
44 | - </strong> | 25 | + <%= render :partial => 'task_title', :locals => {:task => task} %> |
45 | 26 | ||
46 | <div class="task_information"> | 27 | <div class="task_information"> |
47 | <%= task_information(task) %> | 28 | <%= task_information(task) %> |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +<% | ||
2 | + icon_info = task.icon | ||
3 | + if icon_info[:type] == :profile_image | ||
4 | + icon = profile_image(icon_info[:profile], :minor) | ||
5 | + elsif icon_info[:type] == :defined_image | ||
6 | + icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />" | ||
7 | + end | ||
8 | + | ||
9 | + if icon_info[:url] | ||
10 | + icon = link_to(icon, icon_info[:url]) | ||
11 | + end | ||
12 | +%> | ||
13 | + | ||
14 | +<div class="task_icon"> | ||
15 | + <%= icon %> | ||
16 | +</div> |
config/initializers/plugins.rb
@@ -4,4 +4,5 @@ require 'noosfero/plugin/manager' | @@ -4,4 +4,5 @@ require 'noosfero/plugin/manager' | ||
4 | require 'noosfero/plugin/active_record' | 4 | require 'noosfero/plugin/active_record' |
5 | require 'noosfero/plugin/mailer_base' | 5 | require 'noosfero/plugin/mailer_base' |
6 | require 'noosfero/plugin/settings' | 6 | require 'noosfero/plugin/settings' |
7 | +require 'noosfero/plugin/spammable' | ||
7 | Noosfero::Plugin.init_system if $NOOSFERO_LOAD_PLUGINS | 8 | Noosfero::Plugin.init_system if $NOOSFERO_LOAD_PLUGINS |
config/noosfero.yml.dist
@@ -8,6 +8,7 @@ development: | @@ -8,6 +8,7 @@ development: | ||
8 | gravatar: wavatar | 8 | gravatar: wavatar |
9 | googlemaps_initial_zoom: 4 | 9 | googlemaps_initial_zoom: 4 |
10 | exception_recipients: [admin@example.com] | 10 | exception_recipients: [admin@example.com] |
11 | + max_upload_size: 5MB | ||
11 | 12 | ||
12 | test: | 13 | test: |
13 | 14 |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class AddSpamToTask < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + change_table :tasks do |t| | ||
4 | + t.boolean :spam, :default => false | ||
5 | + end | ||
6 | + Task.update_all ["spam = ?", false] | ||
7 | + add_index :tasks, [:spam] | ||
8 | + end | ||
9 | + | ||
10 | + def self.down | ||
11 | + remove_column :tasks, :spam | ||
12 | + end | ||
13 | +end |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class AddImageToArticle < ActiveRecord::Migration | ||
2 | + | ||
3 | + def self.up | ||
4 | + add_column :articles, :image_id, :integer | ||
5 | + add_column :article_versions, :image_id, :integer | ||
6 | + end | ||
7 | + | ||
8 | + def self.down | ||
9 | + remove_column :articles, :image_id | ||
10 | + remove_column :article_versions, :image_id | ||
11 | + end | ||
12 | + | ||
13 | +end |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class AddPositionToArticle < ActiveRecord::Migration | ||
2 | + | ||
3 | + def self.up | ||
4 | + add_column :articles, :position, :integer | ||
5 | + add_column :article_versions, :position, :integer | ||
6 | + end | ||
7 | + | ||
8 | + def self.down | ||
9 | + remove_column :articles, :position | ||
10 | + remove_column :article_versions, :position | ||
11 | + end | ||
12 | + | ||
13 | +end |
db/migrate/20131116165327_enable_enterprises_list_on_user_menu.rb
0 → 100644
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +class EnableEnterprisesListOnUserMenu < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + # The enterprises were always listed on user menu. | ||
4 | + # As now it is configured by admin, the running environments should not need to enable it | ||
5 | + select_all("select id from environments").each do |environment| | ||
6 | + env = Environment.find(environment['id']) | ||
7 | + env.enable(:display_my_enterprises_on_user_menu) | ||
8 | + end | ||
9 | + end | ||
10 | + | ||
11 | + def self.down | ||
12 | + #nothing to be done | ||
13 | + end | ||
14 | +end |
db/schema.rb
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | # | 9 | # |
10 | # It's strongly recommended to check this file into your version control system. | 10 | # It's strongly recommended to check this file into your version control system. |
11 | 11 | ||
12 | -ActiveRecord::Schema.define(:version => 20130711213046) do | 12 | +ActiveRecord::Schema.define(:version => 20131116165327) do |
13 | 13 | ||
14 | create_table "abuse_reports", :force => true do |t| | 14 | create_table "abuse_reports", :force => true do |t| |
15 | t.integer "reporter_id" | 15 | t.integer "reporter_id" |
@@ -86,6 +86,8 @@ ActiveRecord::Schema.define(:version => 20130711213046) do | @@ -86,6 +86,8 @@ ActiveRecord::Schema.define(:version => 20130711213046) do | ||
86 | t.string "language" | 86 | t.string "language" |
87 | t.string "source_name" | 87 | t.string "source_name" |
88 | t.integer "license_id" | 88 | t.integer "license_id" |
89 | + t.integer "image_id" | ||
90 | + t.integer "position" | ||
89 | end | 91 | end |
90 | 92 | ||
91 | add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id" | 93 | add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id" |
@@ -129,6 +131,8 @@ ActiveRecord::Schema.define(:version => 20130711213046) do | @@ -129,6 +131,8 @@ ActiveRecord::Schema.define(:version => 20130711213046) do | ||
129 | t.string "language" | 131 | t.string "language" |
130 | t.string "source_name" | 132 | t.string "source_name" |
131 | t.integer "license_id" | 133 | t.integer "license_id" |
134 | + t.integer "image_id" | ||
135 | + t.integer "position" | ||
132 | end | 136 | end |
133 | 137 | ||
134 | add_index "articles", ["name"], :name => "index_articles_on_name" | 138 | add_index "articles", ["name"], :name => "index_articles_on_name" |
@@ -547,8 +551,11 @@ ActiveRecord::Schema.define(:version => 20130711213046) do | @@ -547,8 +551,11 @@ ActiveRecord::Schema.define(:version => 20130711213046) do | ||
547 | t.datetime "created_at" | 551 | t.datetime "created_at" |
548 | t.string "target_type" | 552 | t.string "target_type" |
549 | t.integer "image_id" | 553 | t.integer "image_id" |
554 | + t.boolean "spam", :default => false | ||
550 | end | 555 | end |
551 | 556 | ||
557 | + add_index "tasks", ["spam"], :name => "index_tasks_on_spam" | ||
558 | + | ||
552 | create_table "thumbnails", :force => true do |t| | 559 | create_table "thumbnails", :force => true do |t| |
553 | t.integer "size" | 560 | t.integer "size" |
554 | t.string "content_type" | 561 | t.string "content_type" |
features/browse_catalogs.feature
@@ -9,7 +9,7 @@ Feature: browse catalogs | @@ -9,7 +9,7 @@ Feature: browse catalogs | ||
9 | And the following enterprises | 9 | And the following enterprises |
10 | | identifier | owner | name | enabled | | 10 | | identifier | owner | name | enabled | |
11 | | artebonito | joaosilva | Associação de Artesanato de Bonito | true | | 11 | | artebonito | joaosilva | Associação de Artesanato de Bonito | true | |
12 | - And feature "disable_products_for_enterprises" is disabled on environment | 12 | + And feature "products_for_enterprises" is enabled on environment |
13 | And the following product_categories | 13 | And the following product_categories |
14 | | name | | 14 | | name | |
15 | | categ1 | | 15 | | categ1 | |
features/browse_enterprises.feature
@@ -6,7 +6,7 @@ Background: | @@ -6,7 +6,7 @@ Background: | ||
6 | Given the following enterprises | 6 | Given the following enterprises |
7 | | identifier | name | | 7 | | identifier | name | |
8 | | shop1 | Shoes Shop | | 8 | | shop1 | Shoes Shop | |
9 | - And feature "disable_products_for_enterprises" is disabled on environment | 9 | + And feature "products_for_enterprises" is enabled on environment |
10 | And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | 10 | And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment |
11 | 11 | ||
12 | Scenario: show all enterprises | 12 | Scenario: show all enterprises |
features/enterprise_homepage.feature
@@ -21,6 +21,7 @@ Feature: enterprise homepage | @@ -21,6 +21,7 @@ Feature: enterprise homepage | ||
21 | And the following product | 21 | And the following product |
22 | | name | category | owner | | 22 | | name | category | owner | |
23 | | Natural Handmade | soap | mayhem | | 23 | | Natural Handmade | soap | mayhem | |
24 | + And feature "products_for_enterprises" is enabled on environment | ||
24 | 25 | ||
25 | 26 | ||
26 | Scenario: display profile info | 27 | Scenario: display profile info |
features/manage_inputs.feature
@@ -19,7 +19,7 @@ Feature: manage inputs | @@ -19,7 +19,7 @@ Feature: manage inputs | ||
19 | And the following product | 19 | And the following product |
20 | | owner | category | name | | 20 | | owner | category | name | |
21 | | redemoinho | rock | Abbey Road | | 21 | | redemoinho | rock | Abbey Road | |
22 | - And feature "disable_products_for_enterprises" is disabled on environment | 22 | + And feature "products_for_enterprises" is enabled on environment |
23 | And the following units | 23 | And the following units |
24 | | singular | plural | | 24 | | singular | plural | |
25 | | Meter | Meters | | 25 | | Meter | Meters | |
features/manage_product_price_details.feature
@@ -19,7 +19,7 @@ Feature: manage product price details | @@ -19,7 +19,7 @@ Feature: manage product price details | ||
19 | And the following product | 19 | And the following product |
20 | | owner | category | name | price | | 20 | | owner | category | name | price | |
21 | | redemoinho | rock | Abbey Road | 80.0 | | 21 | | redemoinho | rock | Abbey Road | 80.0 | |
22 | - And feature "disable_products_for_enterprises" is disabled on environment | 22 | + And feature "products_for_enterprises" is enabled on environment |
23 | And the following inputs | 23 | And the following inputs |
24 | | product | category | price_per_unit | amount_used | | 24 | | product | category | price_per_unit | amount_used | |
25 | | Abbey Road | Rock | 10.0 | 2 | | 25 | | Abbey Road | Rock | 10.0 | 2 | |
features/manage_products.feature
@@ -9,7 +9,7 @@ Feature: manage products | @@ -9,7 +9,7 @@ Feature: manage products | ||
9 | And the following enterprises | 9 | And the following enterprises |
10 | | identifier | owner | name | enabled | | 10 | | identifier | owner | name | enabled | |
11 | | redemoinho | joaosilva | Rede Moinho | true | | 11 | | redemoinho | joaosilva | Rede Moinho | true | |
12 | - And feature "disable_products_for_enterprises" is disabled on environment | 12 | + And feature "products_for_enterprises" is enabled on environment |
13 | 13 | ||
14 | Scenario: display "create new product" button | 14 | Scenario: display "create new product" button |
15 | Given I am logged in as "joaosilva" | 15 | Given I am logged in as "joaosilva" |
lib/feed_updater.rb
@@ -20,14 +20,20 @@ end | @@ -20,14 +20,20 @@ end | ||
20 | class FeedUpdater | 20 | class FeedUpdater |
21 | 21 | ||
22 | class ExceptionNotification < ActionMailer::Base | 22 | class ExceptionNotification < ActionMailer::Base |
23 | - def mail error | 23 | + def mail container, error |
24 | environment = Environment.default | 24 | environment = Environment.default |
25 | 25 | ||
26 | recipients NOOSFERO_CONF['exception_recipients'] | 26 | recipients NOOSFERO_CONF['exception_recipients'] |
27 | from environment.contact_email | 27 | from environment.contact_email |
28 | reply_to environment.contact_email | 28 | reply_to environment.contact_email |
29 | subject "[#{environment.name}] Feed-updater: #{error.message}" | 29 | subject "[#{environment.name}] Feed-updater: #{error.message}" |
30 | - body render(:text => error.backtrace.join("\n")) | 30 | + body render(:text => " |
31 | +Container: | ||
32 | +#{container.inspect} | ||
33 | + | ||
34 | +Backtrace: | ||
35 | +#{error.backtrace.join("\n")} | ||
36 | + ") | ||
31 | end | 37 | end |
32 | end | 38 | end |
33 | 39 | ||
@@ -88,11 +94,13 @@ class FeedUpdater | @@ -88,11 +94,13 @@ class FeedUpdater | ||
88 | if !running | 94 | if !running |
89 | break | 95 | break |
90 | end | 96 | end |
91 | - feed_handler.process(container) | 97 | + begin |
98 | + feed_handler.process(container) | ||
99 | + rescue Exception => e | ||
100 | + FeedUpdater::ExceptionNotification.deliver_mail container, e if NOOSFERO_CONF['exception_recipients'].present? | ||
101 | + end | ||
92 | end | 102 | end |
93 | end | 103 | end |
94 | - rescue Exception => e | ||
95 | - FeedUpdater::ExceptionNotification.deliver_mail e if NOOSFERO_CONF['exception_recipients'].present? | ||
96 | end | 104 | end |
97 | end | 105 | end |
98 | 106 |
@@ -0,0 +1,107 @@ | @@ -0,0 +1,107 @@ | ||
1 | +# All file presenters must extends `FilePresenter` not only to ensure the | ||
2 | +# same interface, but also to make `FilePresenter.for(file)` to work. | ||
3 | +class FilePresenter | ||
4 | + | ||
5 | + # Will return a encapsulated `UploadedFile` or the same object if no | ||
6 | + # one accepts it. That behave allow to give any model to this class, | ||
7 | + # like a Article and have no trouble with that. | ||
8 | + def self.for(f) | ||
9 | + return f if f.is_a? FilePresenter | ||
10 | + klass = FilePresenter.subclasses.sort_by {|class_name| | ||
11 | + class_name.constantize.accepts?(f) || 0 | ||
12 | + }.last.constantize | ||
13 | + klass.accepts?(f) ? klass.new(f) : f | ||
14 | + end | ||
15 | + | ||
16 | + def initialize(f) | ||
17 | + @file = f | ||
18 | + end | ||
19 | + | ||
20 | + # Allows to use the original `UploadedFile` reference. | ||
21 | + def encapsulated_file | ||
22 | + @file | ||
23 | + end | ||
24 | + | ||
25 | + def id | ||
26 | + @file.id | ||
27 | + end | ||
28 | + | ||
29 | + def reload | ||
30 | + @file.reload | ||
31 | + self | ||
32 | + end | ||
33 | + | ||
34 | + # This method must be overridden in subclasses. | ||
35 | + # | ||
36 | + # If the class accepts the file, return a number that represents the | ||
37 | + # priority the class should be given to handle that file. Higher numbers | ||
38 | + # mean higher priority. | ||
39 | + # | ||
40 | + # If the class does not accept the file, return false. | ||
41 | + def self.accepts?(f) | ||
42 | + nil | ||
43 | + end | ||
44 | + | ||
45 | + def short_description | ||
46 | + _("File (%s)") % content_type.sub(/^application\//, '').sub(/^x-/, '').sub(/^image\//, '') | ||
47 | + end | ||
48 | + | ||
49 | + # Define the css classes to style the page fragment with the file related | ||
50 | + # content. If you want other classes to identify this area to your | ||
51 | + # customized presenter, so do this: | ||
52 | + # def css_class_list | ||
53 | + # [super, 'myclass'].flatten | ||
54 | + # end | ||
55 | + def css_class_list | ||
56 | + [ @file.css_class_list, | ||
57 | + 'file-' + self.class.to_s.split(/:+/).map(&:underscore)[1..-1].join('-'), | ||
58 | + 'content-type_' + self.content_type.split('/')[0], | ||
59 | + 'content-type_' + self.content_type.gsub(/[^a-z0-9]/i,'-') | ||
60 | + ].flatten | ||
61 | + end | ||
62 | + | ||
63 | + # Enable file presenter to customize the css classes on view_page.rhtml | ||
64 | + # You may not overwrite this method on your customized presenter. | ||
65 | + def css_class_name | ||
66 | + [css_class_list].flatten.compact.join(' ') | ||
67 | + end | ||
68 | + | ||
69 | + # The generic icon class-name or the specific file path. | ||
70 | + # You may replace this method on your custom FilePresenter. | ||
71 | + # See the current used icons class-names in public/designs/icons/tango/style.css | ||
72 | + def icon_name | ||
73 | + if mime_type | ||
74 | + [ mime_type.split('/')[0], mime_type.gsub(/[^a-z0-9]/i, '-') ] | ||
75 | + else | ||
76 | + 'upload-file' | ||
77 | + end | ||
78 | + end | ||
79 | + | ||
80 | + # Automatic render `file_presenter/<custom>.html.erb` to display your | ||
81 | + # custom presenter html content. | ||
82 | + # You may not overwrite this method on your customized presenter. | ||
83 | + # A variable with the same presenter name will be created to refer | ||
84 | + # to the file object. | ||
85 | + # Example: | ||
86 | + # The `FilePresenter::Image` render `file_presenter/image.html.erb` | ||
87 | + # inside the `file_presenter/image.html.erb` you can access the | ||
88 | + # required `FilePresenter::Image` instance in the `image` variable. | ||
89 | + def to_html(options = {}) | ||
90 | + file = self | ||
91 | + lambda do | ||
92 | + render :partial => file.class.to_s.underscore, | ||
93 | + :locals => { :options => options }, | ||
94 | + :object => file | ||
95 | + end | ||
96 | + end | ||
97 | + | ||
98 | + # That makes the presenter to works like any other `UploadedFile` instance. | ||
99 | + def method_missing(m, *args) | ||
100 | + @file.send(m, *args) | ||
101 | + end | ||
102 | +end | ||
103 | + | ||
104 | +# Preload FilePresenters to allow `FilePresenter.for()` to work | ||
105 | +Dir.glob(File.join('app', 'presenters', '*.rb')) do |file| | ||
106 | + load file | ||
107 | +end |
lib/noosfero/plugin.rb
@@ -155,6 +155,7 @@ class Noosfero::Plugin | @@ -155,6 +155,7 @@ class Noosfero::Plugin | ||
155 | 155 | ||
156 | # Here the developer may specify the events to which the plugins can | 156 | # Here the developer may specify the events to which the plugins can |
157 | # register and must return true or false. The default value must be false. | 157 | # register and must return true or false. The default value must be false. |
158 | + # Must also explicitly define its returning variables. | ||
158 | 159 | ||
159 | # -> If true, noosfero will include plugin_dir/public/style.css into | 160 | # -> If true, noosfero will include plugin_dir/public/style.css into |
160 | # application | 161 | # application |
@@ -162,10 +163,6 @@ class Noosfero::Plugin | @@ -162,10 +163,6 @@ class Noosfero::Plugin | ||
162 | false | 163 | false |
163 | end | 164 | end |
164 | 165 | ||
165 | - # Here the developer should specify the events to which the plugins can | ||
166 | - # register to. Must be explicitly defined its returning | ||
167 | - # variables. | ||
168 | - | ||
169 | # -> Adds buttons to the control panel | 166 | # -> Adds buttons to the control panel |
170 | # returns = { :title => title, :icon => icon, :url => url } | 167 | # returns = { :title => title, :icon => icon, :url => url } |
171 | # title = name that will be displayed. | 168 | # title = name that will be displayed. |
@@ -175,6 +172,13 @@ class Noosfero::Plugin | @@ -175,6 +172,13 @@ class Noosfero::Plugin | ||
175 | nil | 172 | nil |
176 | end | 173 | end |
177 | 174 | ||
175 | + # -> Customize profile block design and behavior | ||
176 | + # (overwrites profile_image_link function) | ||
177 | + # returns = lambda block that creates html code. | ||
178 | + def profile_image_link(profile, size, tag, extra_info) | ||
179 | + nil | ||
180 | + end | ||
181 | + | ||
178 | # -> Adds tabs to the profile | 182 | # -> Adds tabs to the profile |
179 | # returns = { :title => title, :id => id, :content => content, :start => start } | 183 | # returns = { :title => title, :id => id, :content => content, :start => start } |
180 | # title = name that will be displayed. | 184 | # title = name that will be displayed. |
@@ -304,45 +308,16 @@ class Noosfero::Plugin | @@ -304,45 +308,16 @@ class Noosfero::Plugin | ||
304 | scope | 308 | scope |
305 | end | 309 | end |
306 | 310 | ||
307 | - # This method is called by the CommentHandler background job before sending | ||
308 | - # the notification email. If the comment is marked as spam (i.e. by calling | ||
309 | - # <tt>comment.spam!</tt>), then the notification email will *not* be sent. | ||
310 | - # | ||
311 | - # example: | ||
312 | - # | ||
313 | - # def check_comment_for_spam(comment) | ||
314 | - # if anti_spam_service.is_spam?(comment) | ||
315 | - # comment.spam! | ||
316 | - # end | ||
317 | - # end | ||
318 | - # | ||
319 | - def check_comment_for_spam(comment) | 311 | + # -> Allows plugins to check weather object is a spam |
312 | + def check_for_spam(object) | ||
320 | end | 313 | end |
321 | 314 | ||
322 | - # This method is called when the user manually marks a comment as SPAM. A | ||
323 | - # plugin implementing this method should train its spam detection mechanism | ||
324 | - # by submitting this comment as a confirmed spam. | ||
325 | - # | ||
326 | - # example: | ||
327 | - # | ||
328 | - # def comment_marked_as_spam(comment) | ||
329 | - # anti_spam_service.train_with_spam(comment) | ||
330 | - # end | ||
331 | - # | ||
332 | - def comment_marked_as_spam(comment) | 315 | + # -> Allows plugins to know when an object is marked as a spam |
316 | + def marked_as_spam(object) | ||
333 | end | 317 | end |
334 | 318 | ||
335 | - # This method is called when the user manually marks a comment a NOT SPAM. A | ||
336 | - # plugin implementing this method should train its spam detection mechanism | ||
337 | - # by submitting this coimment as a confirmed ham. | ||
338 | - # | ||
339 | - # example: | ||
340 | - # | ||
341 | - # def comment_marked_as_ham(comment) | ||
342 | - # anti_spam_service.train_with_ham(comment) | ||
343 | - # end | ||
344 | - # | ||
345 | - def comment_marked_as_ham(comment) | 319 | + # -> Allows plugins to know when an object is marked as a ham |
320 | + def marked_as_ham(object) | ||
346 | end | 321 | end |
347 | 322 | ||
348 | # Adds extra actions for comments | 323 | # Adds extra actions for comments |
lib/noosfero/plugin/manager.rb
@@ -34,18 +34,20 @@ class Noosfero::Plugin::Manager | @@ -34,18 +34,20 @@ class Noosfero::Plugin::Manager | ||
34 | alias :dispatch_scopes :dispatch_without_flatten | 34 | alias :dispatch_scopes :dispatch_without_flatten |
35 | 35 | ||
36 | def dispatch_first(event, *args) | 36 | def dispatch_first(event, *args) |
37 | - result = nil | 37 | + default = Noosfero::Plugin.new.send(event, *args) |
38 | + result = default | ||
38 | each do |plugin| | 39 | each do |plugin| |
39 | result = plugin.send(event, *args) | 40 | result = plugin.send(event, *args) |
40 | - break if result.present? | 41 | + break if result != default |
41 | end | 42 | end |
42 | result | 43 | result |
43 | end | 44 | end |
44 | 45 | ||
45 | def fetch_first_plugin(event, *args) | 46 | def fetch_first_plugin(event, *args) |
47 | + default = Noosfero::Plugin.new.send(event, *args) | ||
46 | result = nil | 48 | result = nil |
47 | each do |plugin| | 49 | each do |plugin| |
48 | - if plugin.send(event, *args) | 50 | + if plugin.send(event, *args) != default |
49 | result = plugin.class | 51 | result = plugin.class |
50 | break | 52 | break |
51 | end | 53 | end |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +Spammable.module_eval do | ||
2 | + def marked_as_spam | ||
3 | + plugins.dispatch(:marked_as_spam, self) | ||
4 | + end | ||
5 | + | ||
6 | + def marked_as_ham | ||
7 | + plugins.dispatch(:marked_as_ham, self) | ||
8 | + end | ||
9 | + | ||
10 | + def check_for_spam | ||
11 | + plugins.dispatch(:check_for_spam, self) | ||
12 | + end | ||
13 | +end |
@@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
1 | +module Spammable | ||
2 | + def self.included(recipient) | ||
3 | + #TODO This line crashes the migration which includes the spam attribute to | ||
4 | + # Task... =P | ||
5 | + # No fail-safe until someone find out how to use this without crashing | ||
6 | + # the migration process | ||
7 | + #raise "This model (#{recipient.to_s}) should have a spam attribute!" if !recipient.new.respond_to?('spam=') | ||
8 | + recipient.extend(ClassMethods) | ||
9 | + end | ||
10 | + | ||
11 | + module ClassMethods | ||
12 | + def self.extended (base) | ||
13 | + if base.respond_to?(:named_scope) | ||
14 | + base.class_eval do | ||
15 | + named_scope :without_spam, :conditions => ['spam IS NULL OR spam = ?', false] | ||
16 | + named_scope :spam, :conditions => ['spam = ?', true] | ||
17 | + end | ||
18 | + end | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
22 | + def spam? | ||
23 | + !spam.nil? && spam | ||
24 | + end | ||
25 | + | ||
26 | + def ham? | ||
27 | + !spam.nil? && !spam | ||
28 | + end | ||
29 | + | ||
30 | + def spam! | ||
31 | + before_spam! | ||
32 | + self.spam = true | ||
33 | + self.save! | ||
34 | + after_spam! | ||
35 | + self | ||
36 | + end | ||
37 | + | ||
38 | + def ham! | ||
39 | + before_ham! | ||
40 | + self.spam = false | ||
41 | + self.save! | ||
42 | + after_ham! | ||
43 | + self | ||
44 | + end | ||
45 | + | ||
46 | + def after_spam!; end | ||
47 | + def before_spam!; end | ||
48 | + | ||
49 | + def after_ham!; end | ||
50 | + def before_ham!; end | ||
51 | +end |
plugins/anti_spam/lib/anti_spam_plugin.rb
@@ -5,38 +5,37 @@ class AntiSpamPlugin < Noosfero::Plugin | @@ -5,38 +5,37 @@ class AntiSpamPlugin < Noosfero::Plugin | ||
5 | end | 5 | end |
6 | 6 | ||
7 | def self.plugin_description | 7 | def self.plugin_description |
8 | - _("Checks comments against a spam checking service compatible with the Akismet API") | 8 | + _("Tests comments and suggested articles against a spam checking service compatible with the Akismet API") |
9 | end | 9 | end |
10 | 10 | ||
11 | def self.host_default_setting | 11 | def self.host_default_setting |
12 | 'api.antispam.typepad.com' | 12 | 'api.antispam.typepad.com' |
13 | end | 13 | end |
14 | 14 | ||
15 | - def check_comment_for_spam(comment) | ||
16 | - if rakismet_call(comment, :spam?) | ||
17 | - comment.spam = true | ||
18 | - comment.save! | 15 | + def check_for_spam(object) |
16 | + if rakismet_call AntiSpamPlugin::Wrapper.wrap(object), object.environment, :spam? | ||
17 | + object.spam = true | ||
18 | + object.save! | ||
19 | end | 19 | end |
20 | end | 20 | end |
21 | 21 | ||
22 | - def comment_marked_as_spam(comment) | ||
23 | - rakismet_call(comment, :spam!) | 22 | + def marked_as_spam(object) |
23 | + rakismet_call AntiSpamPlugin::Wrapper.wrap(object), object.environment, :spam! | ||
24 | end | 24 | end |
25 | 25 | ||
26 | - def comment_marked_as_ham(comment) | ||
27 | - rakismet_call(comment, :ham!) | 26 | + def marked_as_ham(object) |
27 | + rakismet_call AntiSpamPlugin::Wrapper.wrap(object), object.environment, :ham! | ||
28 | end | 28 | end |
29 | 29 | ||
30 | protected | 30 | protected |
31 | 31 | ||
32 | - def rakismet_call(comment, op) | ||
33 | - settings = Noosfero::Plugin::Settings.new(comment.environment, self.class) | 32 | + def rakismet_call(submission, environment, op) |
33 | + settings = Noosfero::Plugin::Settings.new(environment, self.class) | ||
34 | 34 | ||
35 | Rakismet.host = settings.host | 35 | Rakismet.host = settings.host |
36 | Rakismet.key = settings.api_key | 36 | Rakismet.key = settings.api_key |
37 | - Rakismet.url = comment.environment.top_url | 37 | + Rakismet.url = environment.top_url |
38 | 38 | ||
39 | - submission = AntiSpamPlugin::CommentWrapper.new(comment) | ||
40 | submission.send(op) | 39 | submission.send(op) |
41 | end | 40 | end |
42 | 41 |
plugins/anti_spam/lib/anti_spam_plugin/comment_wrapper.rb
1 | -class AntiSpamPlugin::CommentWrapper < Struct.new(:comment) | ||
2 | - | ||
3 | - delegate :author_name, :author_email, :title, :body, :ip_address, :user_agent, :referrer, :to => :comment | ||
4 | - | ||
5 | - include Rakismet::Model | ||
6 | - | ||
7 | - alias :author :author_name | ||
8 | - alias :user_ip :ip_address | ||
9 | - alias :content :body | ||
10 | - | 1 | +class AntiSpamPlugin::CommentWrapper < AntiSpamPlugin::Wrapper |
2 | + alias_attribute :author, :author_name | ||
3 | + alias_attribute :user_ip, :ip_address | ||
4 | + alias_attribute :content, :body | ||
5 | + | ||
6 | + def self.wraps?(object) | ||
7 | + object.kind_of?(Comment) | ||
8 | + end | ||
11 | end | 9 | end |
plugins/anti_spam/lib/anti_spam_plugin/suggest_article_wrapper.rb
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +class AntiSpamPlugin::SuggestArticleWrapper < AntiSpamPlugin::Wrapper | ||
2 | + alias_attribute :author, :name | ||
3 | + alias_attribute :author_email, :email | ||
4 | + alias_attribute :user_ip, :ip_address | ||
5 | + alias_attribute :content, :article_body | ||
6 | + | ||
7 | + def self.wraps?(object) | ||
8 | + object.kind_of?(SuggestArticle) | ||
9 | + end | ||
10 | +end |
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | +class AntiSpamPlugin::Wrapper < SimpleDelegator | ||
2 | + include Rakismet::Model | ||
3 | + | ||
4 | + @@wrappers = [] | ||
5 | + | ||
6 | + def self.wrap(object) | ||
7 | + wrapper = @@wrappers.find { |wrapper| wrapper.wraps?(object) } | ||
8 | + wrapper ? wrapper.new(object) : object | ||
9 | + end | ||
10 | + | ||
11 | + def self.wraps?(object) | ||
12 | + false | ||
13 | + end | ||
14 | + | ||
15 | + def self.inherited(child) | ||
16 | + @@wrappers << child | ||
17 | + end | ||
18 | +end |
plugins/anti_spam/test/unit/anti_spam_plugin/comment_wrapper_test.rb
1 | require 'test_helper' | 1 | require 'test_helper' |
2 | 2 | ||
3 | -class AntiSpamPluginCommentWrapperTest < ActiveSupport::TestCase | 3 | +class AntiSpamPlugin::CommentWrapperTest < ActiveSupport::TestCase |
4 | 4 | ||
5 | def setup | 5 | def setup |
6 | @comment = Comment.new( | 6 | @comment = Comment.new( |
@@ -15,10 +15,6 @@ class AntiSpamPluginCommentWrapperTest < ActiveSupport::TestCase | @@ -15,10 +15,6 @@ class AntiSpamPluginCommentWrapperTest < ActiveSupport::TestCase | ||
15 | @wrapper = AntiSpamPlugin::CommentWrapper.new(@comment) | 15 | @wrapper = AntiSpamPlugin::CommentWrapper.new(@comment) |
16 | end | 16 | end |
17 | 17 | ||
18 | - should 'use Rakismet::Model' do | ||
19 | - assert_includes @wrapper.class.included_modules, Rakismet::Model | ||
20 | - end | ||
21 | - | ||
22 | should 'get contents' do | 18 | should 'get contents' do |
23 | assert_equal @comment.body, @wrapper.content | 19 | assert_equal @comment.body, @wrapper.content |
24 | end | 20 | end |
plugins/anti_spam/test/unit/anti_spam_plugin/suggest_article_wrapper_test.rb
0 → 100644
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +require 'test_helper' | ||
2 | + | ||
3 | +class AntiSpamPlugin::SuggestArticleWrapperTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @suggest_article = SuggestArticle.new( | ||
7 | + :article_body => 'comment body', | ||
8 | + :name => 'author', | ||
9 | + :email => 'foo@example.com', | ||
10 | + :ip_address => '1.2.3.4', | ||
11 | + :user_agent => 'Some Good Browser (I hope)', | ||
12 | + :referrer => 'http://noosfero.org/' | ||
13 | + ) | ||
14 | + @wrapper = AntiSpamPlugin::SuggestArticleWrapper.new(@suggest_article) | ||
15 | + end | ||
16 | + | ||
17 | + should 'get contents' do | ||
18 | + assert_equal @suggest_article.article_body, @wrapper.content | ||
19 | + end | ||
20 | + | ||
21 | + should 'get author name' do | ||
22 | + assert_equal @suggest_article.name, @wrapper.author | ||
23 | + end | ||
24 | + | ||
25 | + should 'get author email' do | ||
26 | + assert_equal @suggest_article.email, @wrapper.author_email | ||
27 | + end | ||
28 | + | ||
29 | + should 'get IP address' do | ||
30 | + assert_equal @suggest_article.ip_address, @wrapper.user_ip | ||
31 | + end | ||
32 | + | ||
33 | + should 'get User-Agent' do | ||
34 | + assert_equal @suggest_article.user_agent, @wrapper.user_agent | ||
35 | + end | ||
36 | + | ||
37 | + should 'get get Referrer' do | ||
38 | + assert_equal @suggest_article.referrer, @wrapper.referrer | ||
39 | + end | ||
40 | + | ||
41 | +end |
plugins/anti_spam/test/unit/anti_spam_plugin/wrapper_test.rb
0 → 100644
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +require 'test_helper' | ||
2 | +require 'anti_spam_plugin/wrapper' | ||
3 | + | ||
4 | +class AntiSpamPluginWrapperTest < ActiveSupport::TestCase | ||
5 | + should 'use Rakismet::Model' do | ||
6 | + wrapped = AntiSpamPlugin::Wrapper.new(mock) | ||
7 | + assert_includes wrapped.class.included_modules, Rakismet::Model | ||
8 | + end | ||
9 | + | ||
10 | + should 'wrap object according to wraps? method' do | ||
11 | + class EvenWrapper < AntiSpamPlugin::Wrapper | ||
12 | + def self.wraps?(object) | ||
13 | + object % 2 == 0 | ||
14 | + end | ||
15 | + end | ||
16 | + class OddWrapper < AntiSpamPlugin::Wrapper | ||
17 | + def self.wraps?(object) | ||
18 | + object % 2 != 0 | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
22 | + assert AntiSpamPlugin::Wrapper.wrap(5).kind_of?(OddWrapper) | ||
23 | + assert AntiSpamPlugin::Wrapper.wrap(6).kind_of?(EvenWrapper) | ||
24 | + end | ||
25 | +end |
plugins/anti_spam/test/unit/anti_spam_plugin_test.rb
@@ -2,35 +2,36 @@ require 'test_helper' | @@ -2,35 +2,36 @@ require 'test_helper' | ||
2 | 2 | ||
3 | class AntiSpamPluginTest < ActiveSupport::TestCase | 3 | class AntiSpamPluginTest < ActiveSupport::TestCase |
4 | 4 | ||
5 | - def setup | ||
6 | - profile = fast_create(Profile) | ||
7 | - article = fast_create(TextileArticle, :profile_id => profile.id) | ||
8 | - @comment = fast_create(Comment, :source_id => article.id, :source_type => 'Article') | 5 | + class SpammableContent |
6 | + attr_accessor :spam | ||
7 | + include Spammable | ||
9 | 8 | ||
10 | - @settings = Noosfero::Plugin::Settings.new(@comment.environment, AntiSpamPlugin) | ||
11 | - @settings.api_key = 'b8b80ddb8084062d0c9119c945ce3bc3' | ||
12 | - @settings.save! | 9 | + def save!; end |
10 | + def environment; Environment.default; end | ||
11 | + end | ||
13 | 12 | ||
13 | + def setup | ||
14 | + @spammable = SpammableContent.new | ||
14 | @plugin = AntiSpamPlugin.new | 15 | @plugin = AntiSpamPlugin.new |
15 | - @plugin.context = @comment | ||
16 | end | 16 | end |
17 | 17 | ||
18 | - should 'check for spam and mark comment as spam if server says it is spam' do | ||
19 | - AntiSpamPlugin::CommentWrapper.any_instance.expects(:spam?).returns(true) | ||
20 | - @comment.expects(:save!) | 18 | + attr_accessor :spammable |
21 | 19 | ||
22 | - @plugin.check_comment_for_spam(@comment) | ||
23 | - assert @comment.spam | ||
24 | - end | 20 | + should 'check for spam and mark as spam if server says it is spam' do |
21 | + spammable.expects(:spam?).returns(true) | ||
22 | + spammable.expects(:save!) | ||
25 | 23 | ||
26 | - should 'report spam' do | ||
27 | - AntiSpamPlugin::CommentWrapper.any_instance.expects(:spam!) | ||
28 | - @plugin.comment_marked_as_spam(@comment) | 24 | + @plugin.check_for_spam(spammable) |
25 | + assert spammable.spam | ||
29 | end | 26 | end |
30 | 27 | ||
31 | - should 'report ham' do | ||
32 | - AntiSpamPlugin::CommentWrapper.any_instance.expects(:ham!) | ||
33 | - @plugin.comment_marked_as_ham(@comment) | 28 | + should 'report comment spam' do |
29 | + spammable.expects(:spam!) | ||
30 | + @plugin.marked_as_spam(spammable) | ||
34 | end | 31 | end |
35 | 32 | ||
33 | + should 'report comment ham' do | ||
34 | + spammable.expects(:ham!) | ||
35 | + @plugin.marked_as_ham(spammable) | ||
36 | + end | ||
36 | end | 37 | end |
plugins/comment_group/controllers/profile/comment_group_plugin_profile_controller.rb
1 | class CommentGroupPluginProfileController < ProfileController | 1 | class CommentGroupPluginProfileController < ProfileController |
2 | - append_view_path File.join(File.dirname(__FILE__) + '/../views') | 2 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') |
3 | 3 | ||
4 | def view_comments | 4 | def view_comments |
5 | - article_id = params[:article_id] | ||
6 | - group_id = params[:group_id] | 5 | + @article_id = params[:article_id] |
6 | + @group_id = params[:group_id] | ||
7 | 7 | ||
8 | - article = profile.articles.find(article_id) | ||
9 | - comments = article.group_comments.without_spam.in_group(group_id) | ||
10 | - render :update do |page| | ||
11 | - page.replace_html "comments_list_group_#{group_id}", :partial => 'comment/comment.rhtml', :collection => comments | ||
12 | - page.replace_html "comment-count-#{group_id}", comments.count | ||
13 | - end | 8 | + article = profile.articles.find(@article_id) |
9 | + @group_comment_page = (params[:group_comment_page] || 1).to_i | ||
10 | + | ||
11 | + @comments = article.comments.without_spam.in_group(@group_id) | ||
12 | + @comments_count = @comments.count | ||
13 | + @comments = @comments.without_reply.paginate(:per_page => per_page, :page => @group_comment_page ) | ||
14 | + | ||
15 | + @no_more_pages = @comments_count <= @group_comment_page * per_page | ||
16 | + end | ||
17 | + | ||
18 | + def per_page | ||
19 | + 3 | ||
14 | end | 20 | end |
15 | 21 | ||
16 | end | 22 | end |
plugins/comment_group/lib/comment_group_plugin.rb
@@ -24,6 +24,11 @@ class CommentGroupPlugin < Noosfero::Plugin | @@ -24,6 +24,11 @@ class CommentGroupPlugin < Noosfero::Plugin | ||
24 | 'comment_group_macro.js' | 24 | 'comment_group_macro.js' |
25 | end | 25 | end |
26 | 26 | ||
27 | + def stylesheet? | ||
28 | + true | ||
29 | + end | ||
30 | + | ||
31 | + | ||
27 | end | 32 | end |
28 | 33 | ||
29 | require_dependency 'comment_group_plugin/macros/allow_comment' | 34 | require_dependency 'comment_group_plugin/macros/allow_comment' |
plugins/comment_group/lib/comment_group_plugin/macros/allow_comment.rb
@@ -11,7 +11,6 @@ class CommentGroupPlugin::AllowComment < Noosfero::Plugin::Macro | @@ -11,7 +11,6 @@ class CommentGroupPlugin::AllowComment < Noosfero::Plugin::Macro | ||
11 | :css_files => 'comment_group.css' } | 11 | :css_files => 'comment_group.css' } |
12 | end | 12 | end |
13 | 13 | ||
14 | - #FIXME Make this test | ||
15 | def parse(params, inner_html, source) | 14 | def parse(params, inner_html, source) |
16 | group_id = params[:group_id].to_i | 15 | group_id = params[:group_id].to_i |
17 | article = source | 16 | article = source |
plugins/comment_group/lib/ext/article.rb
@@ -2,13 +2,10 @@ require_dependency 'article' | @@ -2,13 +2,10 @@ require_dependency 'article' | ||
2 | 2 | ||
3 | class Article | 3 | class Article |
4 | 4 | ||
5 | - #FIXME make this test | ||
6 | has_many :group_comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc', :conditions => [ 'group_id IS NOT NULL'] | 5 | has_many :group_comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc', :conditions => [ 'group_id IS NOT NULL'] |
7 | 6 | ||
8 | - #FIXME make this test | ||
9 | validate :not_empty_group_comments_removed | 7 | validate :not_empty_group_comments_removed |
10 | 8 | ||
11 | - #FIXME make this test | ||
12 | def not_empty_group_comments_removed | 9 | def not_empty_group_comments_removed |
13 | if body | 10 | if body |
14 | groups_with_comments = group_comments.collect {|comment| comment.group_id}.uniq | 11 | groups_with_comments = group_comments.collect {|comment| comment.group_id}.uniq |
plugins/comment_group/test/functional/comment_group_plugin_profile_controller_test.rb
1 | -require File.dirname(__FILE__) + '/../../../../test/test_helper' | 1 | +require File.dirname(__FILE__) + '/../test_helper' |
2 | require File.dirname(__FILE__) + '/../../controllers/profile/comment_group_plugin_profile_controller' | 2 | require File.dirname(__FILE__) + '/../../controllers/profile/comment_group_plugin_profile_controller' |
3 | 3 | ||
4 | # Re-raise errors caught by the controller. | 4 | # Re-raise errors caught by the controller. |
@@ -21,18 +21,52 @@ class CommentGroupPluginProfileControllerTest < ActionController::TestCase | @@ -21,18 +21,52 @@ class CommentGroupPluginProfileControllerTest < ActionController::TestCase | ||
21 | should 'be able to show group comments' do | 21 | should 'be able to show group comments' do |
22 | comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | 22 | comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) |
23 | xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 | 23 | xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 |
24 | - assert_template 'comment/_comment.rhtml' | 24 | + assert_template 'comment_group_plugin_profile/view_comments.rjs' |
25 | assert_match /comments_list_group_0/, @response.body | 25 | assert_match /comments_list_group_0/, @response.body |
26 | assert_match /\"comment-count-0\", \"1\"/, @response.body | 26 | assert_match /\"comment-count-0\", \"1\"/, @response.body |
27 | end | 27 | end |
28 | 28 | ||
29 | should 'do not show global comments' do | 29 | should 'do not show global comments' do |
30 | - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'global comment', :body => 'global', :group_id => nil) | ||
31 | - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | 30 | + fast_create(Comment, :source_id => article, :author_id => profile, :title => 'global comment', :body => 'global', :group_id => nil) |
31 | + fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | ||
32 | xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 | 32 | xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 |
33 | - assert_template 'comment/_comment.rhtml' | 33 | + assert_template 'comment_group_plugin_profile/view_comments.rjs' |
34 | assert_match /comments_list_group_0/, @response.body | 34 | assert_match /comments_list_group_0/, @response.body |
35 | assert_match /\"comment-count-0\", \"1\"/, @response.body | 35 | assert_match /\"comment-count-0\", \"1\"/, @response.body |
36 | end | 36 | end |
37 | 37 | ||
38 | + should 'show first page comments only' do | ||
39 | + comment1 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'secondpage', :group_id => 0) | ||
40 | + comment2 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 1', :group_id => 0) | ||
41 | + comment3 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 2', :group_id => 0) | ||
42 | + comment4 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 3', :group_id => 0) | ||
43 | + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 | ||
44 | + assert_match /firstpage 1/, @response.body | ||
45 | + assert_match /firstpage 2/, @response.body | ||
46 | + assert_match /firstpage 3/, @response.body | ||
47 | + assert_no_match /secondpage/, @response.body | ||
48 | + end | ||
49 | + | ||
50 | + should 'show link to display more comments' do | ||
51 | + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | ||
52 | + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | ||
53 | + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | ||
54 | + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'secondpage', :body => 'secondpage', :group_id => 0) | ||
55 | + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 | ||
56 | + assert_match /group_comment_page=2/, @response.body | ||
57 | + end | ||
58 | + | ||
59 | + should 'do not show link to display more comments if do not have more pages' do | ||
60 | + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | ||
61 | + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | ||
62 | + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) | ||
63 | + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 | ||
64 | + assert_no_match /group_comment_page/, @response.body | ||
65 | + end | ||
66 | + | ||
67 | + should 'do not show link to display more comments if do not have any comments' do | ||
68 | + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 | ||
69 | + assert_no_match /group_comment_page/, @response.body | ||
70 | + end | ||
71 | + | ||
38 | end | 72 | end |
plugins/comment_group/test/functional/comment_group_plugin_public_controller_test.rb
1 | -require File.dirname(__FILE__) + '/../../../../test/test_helper' | 1 | +require File.dirname(__FILE__) + '/../test_helper' |
2 | require File.dirname(__FILE__) + '/../../controllers/public/comment_group_plugin_public_controller' | 2 | require File.dirname(__FILE__) + '/../../controllers/public/comment_group_plugin_public_controller' |
3 | 3 | ||
4 | # Re-raise errors caught by the controller. | 4 | # Re-raise errors caught by the controller. |
plugins/comment_group/test/functional/content_viewer_controller_test.rb
0 → 100644
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class ContentViewerController | ||
4 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') | ||
5 | + def rescue_action(e) | ||
6 | + raise e | ||
7 | + end | ||
8 | +end | ||
9 | + | ||
10 | +class ContentViewerControllerTest < ActionController::TestCase | ||
11 | + | ||
12 | + def setup | ||
13 | + @profile = fast_create(Community) | ||
14 | + @page = fast_create(Article, :profile_id => @profile.id, :body => "<div class=\"macro\" data-macro-group_id=\"1\" data-macro='comment_group_plugin/allow_comment' ></div>") | ||
15 | + @environment = Environment.default | ||
16 | + @environment.enable_plugin(CommentGroupPlugin) | ||
17 | + end | ||
18 | + | ||
19 | + attr_reader :page | ||
20 | + | ||
21 | + should 'parse article body and render comment group view' do | ||
22 | + comment1 = fast_create(Comment, :group_id => 1, :source_id => page.id) | ||
23 | + get :view_page, @page.url | ||
24 | + assert_tag 'div', :attributes => {:class => 'comment_group_1'} | ||
25 | + assert_tag 'div', :attributes => {:id => 'comments_group_count_1'} | ||
26 | + end | ||
27 | + | ||
28 | +end |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class AllowCommentTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @macro = CommentGroupPlugin::AllowComment.new | ||
7 | + end | ||
8 | + | ||
9 | + attr_reader :macro | ||
10 | + | ||
11 | + should 'have a configuration' do | ||
12 | + assert CommentGroupPlugin::AllowComment.configuration | ||
13 | + end | ||
14 | + | ||
15 | + should 'parse contents to include comment group view' do | ||
16 | + profile = fast_create(Community) | ||
17 | + article = fast_create(Article, :profile_id => profile.id) | ||
18 | + comment = fast_create(Comment, :group_id => 1, :source_id => article.id) | ||
19 | + inner_html = 'inner' | ||
20 | + content = macro.parse({:group_id => comment.group_id}, inner_html, article) | ||
21 | + | ||
22 | + expects(:render).with({:partial => 'plugins/comment_group/views/comment_group.rhtml', :locals => {:group_id => comment.group_id, :article_id => article.id, :inner_html => inner_html, :count => 1, :profile_identifier => profile.identifier} }) | ||
23 | + instance_eval(&content) | ||
24 | + end | ||
25 | + | ||
26 | +end |
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class ArticleTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + profile = fast_create(Community) | ||
7 | + @article = fast_create(Article, :profile_id => profile.id) | ||
8 | + end | ||
9 | + | ||
10 | + attr_reader :article | ||
11 | + | ||
12 | + should 'return group comments from article' do | ||
13 | + comment1 = fast_create(Comment, :group_id => 1, :source_id => article.id) | ||
14 | + comment2 = fast_create(Comment, :group_id => nil, :source_id => article.id) | ||
15 | + assert_equal [comment1], article.group_comments | ||
16 | + end | ||
17 | + | ||
18 | + should 'do not allow a exclusion of a group comment macro if this group has comments' do | ||
19 | + article.update_attribute(:body, "<div class=\"macro\" data-macro-group_id=2></div>") | ||
20 | + comment1 = fast_create(Comment, :group_id => 1, :source_id => article.id) | ||
21 | + assert !article.save | ||
22 | + assert_equal 'Not empty group comment cannot be removed', article.errors[:base] | ||
23 | + end | ||
24 | + | ||
25 | + should 'allow save if comment group macro is not removed for group with comments' do | ||
26 | + article.update_attribute(:body, "<div class=\"macro\" data-macro-group_id=1></div>") | ||
27 | + comment1 = fast_create(Comment, :group_id => 1, :source_id => article.id) | ||
28 | + assert article.save | ||
29 | + end | ||
30 | + | ||
31 | +end |
plugins/comment_group/test/unit/comment_group_plugin_test.rb
1 | -require File.dirname(__FILE__) + '/../../../../test/test_helper' | 1 | +require File.dirname(__FILE__) + '/../test_helper' |
2 | 2 | ||
3 | class CommentGroupPluginTest < ActiveSupport::TestCase | 3 | class CommentGroupPluginTest < ActiveSupport::TestCase |
4 | 4 | ||
5 | - include Noosfero::Plugin::HotSpot | ||
6 | - | ||
7 | def setup | 5 | def setup |
8 | @environment = Environment.default | 6 | @environment = Environment.default |
7 | + @plugin = CommentGroupPlugin.new | ||
8 | + end | ||
9 | + | ||
10 | + attr_reader :environment, :plugin | ||
11 | + | ||
12 | + should 'have a name' do | ||
13 | + assert_not_equal Noosfero::Plugin.plugin_name, CommentGroupPlugin::plugin_name | ||
14 | + end | ||
15 | + | ||
16 | + should 'describe yourself' do | ||
17 | + assert_not_equal Noosfero::Plugin.plugin_description, CommentGroupPlugin::plugin_description | ||
18 | + end | ||
19 | + | ||
20 | + should 'have a js file' do | ||
21 | + assert !plugin.js_files.blank? | ||
9 | end | 22 | end |
10 | 23 | ||
11 | - attr_reader :environment | 24 | + should 'have stylesheet' do |
25 | + assert plugin.stylesheet? | ||
26 | + end | ||
27 | + | ||
28 | + should 'have extra contents for comment form' do | ||
29 | + comment = fast_create(Comment, :group_id => 1) | ||
30 | + content = plugin.comment_form_extra_contents({:comment => comment}) | ||
31 | + expects(:hidden_field_tag).with('comment[group_id]', comment.group_id).once | ||
32 | + instance_eval(&content) | ||
33 | + end | ||
34 | + | ||
35 | + should 'do not have extra contents for comments without group' do | ||
36 | + comment = fast_create(Comment, :group_id => nil) | ||
37 | + content = plugin.comment_form_extra_contents({:comment => comment}) | ||
38 | + assert_equal nil, instance_eval(&content) | ||
39 | + end | ||
40 | + | ||
41 | + should 'call without_group for scope passed as parameter to unavailable_comments' do | ||
42 | + article = fast_create(Article) | ||
43 | + article.expects(:without_group).once | ||
44 | + plugin.unavailable_comments(article) | ||
45 | + end | ||
12 | 46 | ||
13 | #FIXME Obsolete test | 47 | #FIXME Obsolete test |
14 | # | 48 | # |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class CommentTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + profile = fast_create(Community) | ||
7 | + @article = fast_create(Article, :profile_id => profile.id) | ||
8 | + end | ||
9 | + | ||
10 | + attr_reader :article | ||
11 | + | ||
12 | + should 'return comments that belongs to a specified group' do | ||
13 | + comment1 = fast_create(Comment, :group_id => 1, :source_id => article.id) | ||
14 | + comment2 = fast_create(Comment, :group_id => nil, :source_id => article.id) | ||
15 | + comment3 = fast_create(Comment, :group_id => 2, :source_id => article.id) | ||
16 | + assert_equal [comment1], article.comments.in_group(1) | ||
17 | + end | ||
18 | + | ||
19 | + should 'return comments that do not belongs to any group' do | ||
20 | + comment1 = fast_create(Comment, :group_id => 1, :source_id => article.id) | ||
21 | + comment2 = fast_create(Comment, :group_id => nil, :source_id => article.id) | ||
22 | + comment3 = fast_create(Comment, :group_id => 2, :source_id => article.id) | ||
23 | + assert_equal [comment2], article.comments.without_group | ||
24 | + end | ||
25 | + | ||
26 | +end |
plugins/comment_group/views/_comment_group.rhtml
@@ -20,7 +20,13 @@ | @@ -20,7 +20,13 @@ | ||
20 | <div class="comment-group-loading-<%= group_id %>"/> | 20 | <div class="comment-group-loading-<%= group_id %>"/> |
21 | 21 | ||
22 | <div class="comments_list_toggle_group_<%= group_id %>" style="display:none"> | 22 | <div class="comments_list_toggle_group_<%= group_id %>" style="display:none"> |
23 | - <div class="article-comments-list" id="comments_list_group_<%= group_id %>"></div> | ||
24 | - <div id="page-comment-form-<%= group_id %>" class='post_comment_box closed'><%= render :partial => 'comment/comment_form', :locals => {:comment => Comment.new, :display_link => true, :cancel_triggers_hide => true, :group_id => group_id}%></div> | 23 | + <div class="article-comments-list" id="comments_list_group_<%= group_id %>"> |
24 | + </div> | ||
25 | + <div class ="article-comments-list-more" id="comments_list_group_<%= group_id %>_more"> | ||
26 | + </div> | ||
27 | + <div id="page-comment-form-<%= group_id %>" class='post_comment_box closed'> | ||
28 | + <%= render :partial => 'comment/comment_form', :locals => {:comment => Comment.new, :display_link => true, :cancel_triggers_hide => true, :group_id => group_id}%> | ||
29 | + </div> | ||
30 | + | ||
25 | </div> | 31 | </div> |
26 | </div> | 32 | </div> |
plugins/comment_group/views/comment_group_plugin_profile/view_comments.rjs
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +if @group_comment_page == 1 | ||
2 | + page.replace_html "comments_list_group_#{@group_id}", :partial => 'comment/comment.rhtml', :collection => @comments | ||
3 | +else | ||
4 | + page.insert_html :bottom, "comments_list_group_#{@group_id}", :partial => 'comment/comment.rhtml', :collection => @comments | ||
5 | +end | ||
6 | +page.replace_html "comment-count-#{@group_id}", @comments_count | ||
7 | + | ||
8 | +if @no_more_pages | ||
9 | + page.replace_html "comments_list_group_#{@group_id}_more", "" | ||
10 | +else | ||
11 | + page.replace_html "comments_list_group_#{@group_id}_more", link_to_remote(_('More'), :url => { :profile => profile.identifier, :controller => 'comment_group_plugin_profile', :action => 'view_comments', :group_id => @group_id, :article_id => @article_id, :group_comment_page => @group_comment_page + 1}, :loaded => visual_effect(:highlight, "comments_list_group_#{@group_id}"), :method => :post, :complete => "loadCompleted(#{@group_id})") | ||
12 | +end |
plugins/community_track/controllers/myprofile/community_track_plugin_myprofile_controller.rb
0 → 100644
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | +class CommunityTrackPluginMyprofileController < MyProfileController | ||
2 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') | ||
3 | + | ||
4 | + before_filter :allow_edit_track, :only => :save_order | ||
5 | + | ||
6 | + def save_order | ||
7 | + track = profile.articles.find(params[:track]) | ||
8 | + track.reorder_steps(params[:step_ids]) | ||
9 | + redirect_to track.url | ||
10 | + end | ||
11 | + | ||
12 | + protected | ||
13 | + | ||
14 | + def allow_edit_track | ||
15 | + render_access_denied unless profile.articles.find(params[:track]).allow_edit?(user) | ||
16 | + end | ||
17 | + | ||
18 | +end |
plugins/community_track/controllers/public/community_track_plugin_public_controller.rb
0 → 100644
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +class CommunityTrackPluginPublicController < PublicController | ||
2 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') | ||
3 | + | ||
4 | + no_design_blocks | ||
5 | + | ||
6 | + before_filter :login_required, :only => :select_community | ||
7 | + | ||
8 | + def view_tracks | ||
9 | + block = Block.find(params[:id]) | ||
10 | + p = params[:page].to_i | ||
11 | + per_page = params[:per_page] | ||
12 | + per_page ||= block.limit | ||
13 | + per_page = per_page.to_i | ||
14 | + tracks = block.tracks(p, per_page) | ||
15 | + | ||
16 | + render :update do |page| | ||
17 | + page.insert_html :bottom, "track_list_#{block.id}", :partial => "blocks/#{block.track_partial}", :collection => tracks, :locals => {:block => block} | ||
18 | + | ||
19 | + if block.has_page?(p+1, per_page) | ||
20 | + page.replace_html "track_list_more_#{block.id}", :partial => 'blocks/track_list_more', :locals => {:block => block, :page => p+1, :force_same_page => params[:force_same_page], :per_page => per_page} | ||
21 | + else | ||
22 | + page.replace_html "track_list_more_#{block.id}", '' | ||
23 | + end | ||
24 | + end | ||
25 | + end | ||
26 | + | ||
27 | + def all_tracks | ||
28 | + @per_page = 5 #FIXME | ||
29 | + @block = Block.find(params[:id]) | ||
30 | + @tracks = @block.tracks(1, @per_page) | ||
31 | + @show_more = @block.has_page?(2, @per_page) | ||
32 | + end | ||
33 | + | ||
34 | + def select_community | ||
35 | + @communities = user.memberships.select{ |community| user.has_permission?('post_content', community) } | ||
36 | + @back_to = request.url | ||
37 | + if request.post? | ||
38 | + community_identifier = params[:community_identifier] | ||
39 | + if community_identifier.nil? | ||
40 | + @failed = [_('Select one community to proceed')] | ||
41 | + else | ||
42 | + redirect_to :controller => 'cms', :action => 'new', :type => "CommunityTrackPlugin::Track", :profile => community_identifier | ||
43 | + end | ||
44 | + end | ||
45 | + end | ||
46 | + | ||
47 | +end |
@@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
1 | +class CommunityTrackPlugin < Noosfero::Plugin | ||
2 | + | ||
3 | + def self.plugin_name | ||
4 | + 'Community Track' | ||
5 | + end | ||
6 | + | ||
7 | + def self.plugin_description | ||
8 | + _("New kind of content for communities.") | ||
9 | + end | ||
10 | + | ||
11 | + def stylesheet? | ||
12 | + true | ||
13 | + end | ||
14 | + | ||
15 | + def content_types | ||
16 | + if context.respond_to?(:params) && context.params | ||
17 | + types = [] | ||
18 | + parent_id = context.params[:parent_id] | ||
19 | + types << CommunityTrackPlugin::Track if context.profile.community? && !parent_id | ||
20 | + parent = parent_id ? context.profile.articles.find(parent_id) : nil | ||
21 | + types << CommunityTrackPlugin::Step if parent.kind_of?(CommunityTrackPlugin::Track) | ||
22 | + types | ||
23 | + else | ||
24 | + [CommunityTrackPlugin::Track, CommunityTrackPlugin::Step] | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + def self.extra_blocks | ||
29 | + { CommunityTrackPlugin::TrackListBlock => {:position => 1}, CommunityTrackPlugin::TrackCardListBlock => {} } | ||
30 | + end | ||
31 | + | ||
32 | + def content_remove_new(page) | ||
33 | + page.kind_of?(CommunityTrackPlugin::Track) | ||
34 | + end | ||
35 | + | ||
36 | +end |
plugins/community_track/lib/community_track_plugin/step.rb
0 → 100644
@@ -0,0 +1,105 @@ | @@ -0,0 +1,105 @@ | ||
1 | +class CommunityTrackPlugin::Step < Folder | ||
2 | + | ||
3 | + settings_items :hidden, :type => :boolean, :default => false | ||
4 | + | ||
5 | + alias :tools :children | ||
6 | + | ||
7 | + acts_as_list :scope => :parent | ||
8 | + | ||
9 | + def belong_to_track | ||
10 | + errors.add(:parent, _("Step not allowed at this parent.")) unless parent.kind_of?(CommunityTrackPlugin::Track) | ||
11 | + end | ||
12 | + | ||
13 | + validate :belong_to_track | ||
14 | + validates_presence_of :start_date, :end_date | ||
15 | + validate :end_date_equal_or_after_start_date | ||
16 | + | ||
17 | + after_save :schedule_activation | ||
18 | + | ||
19 | + before_create do |step| | ||
20 | + step.published = false | ||
21 | + true | ||
22 | + end | ||
23 | + | ||
24 | + before_create :set_hidden_position | ||
25 | + before_save :set_hidden_position | ||
26 | + | ||
27 | + def set_hidden_position | ||
28 | + if hidden | ||
29 | + decrement_positions_on_lower_items | ||
30 | + self[:position] = 0 | ||
31 | + elsif position == 0 | ||
32 | + add_to_list_bottom | ||
33 | + end | ||
34 | + end | ||
35 | + | ||
36 | + def end_date_equal_or_after_start_date | ||
37 | + if end_date && start_date | ||
38 | + errors.add(:end_date, _('must be equal or after start date.')) unless end_date >= start_date | ||
39 | + end | ||
40 | + end | ||
41 | + | ||
42 | + def self.short_description | ||
43 | + _("Step") | ||
44 | + end | ||
45 | + | ||
46 | + def self.description | ||
47 | + _('Defines a step.') | ||
48 | + end | ||
49 | + | ||
50 | + def accept_comments? | ||
51 | + false | ||
52 | + end | ||
53 | + | ||
54 | + def enabled_tools | ||
55 | + {TinyMceArticle => {:name => _('Article')}, Forum => {:name => _('Forum')}} | ||
56 | + end | ||
57 | + | ||
58 | + def to_html(options = {}) | ||
59 | + step = self | ||
60 | + lambda do | ||
61 | + render :file => 'content_viewer/step.rhtml', :locals => {:step => step} | ||
62 | + end | ||
63 | + end | ||
64 | + | ||
65 | + def active? | ||
66 | + (start_date..end_date).include?(Date.today) | ||
67 | + end | ||
68 | + | ||
69 | + def finished? | ||
70 | + Date.today > end_date | ||
71 | + end | ||
72 | + | ||
73 | + def waiting? | ||
74 | + Date.today < start_date | ||
75 | + end | ||
76 | + | ||
77 | + def schedule_activation | ||
78 | + return if !changes['start_date'] && !changes['end_date'] && !changes['published'] | ||
79 | + today = Date.today | ||
80 | + if today <= end_date || published | ||
81 | + schedule_date = !published ? start_date : end_date + 1.day | ||
82 | + CommunityTrackPlugin::ActivationJob.find(id).destroy_all | ||
83 | + Delayed::Job.enqueue(CommunityTrackPlugin::ActivationJob.new(self.id), 0, schedule_date) | ||
84 | + end | ||
85 | + end | ||
86 | + | ||
87 | + def publish | ||
88 | + self[:published] = active? && !hidden | ||
89 | + save! | ||
90 | + end | ||
91 | + | ||
92 | + class CommunityTrackPlugin::ActivationJob < Struct.new(:step_id) | ||
93 | + | ||
94 | + def self.find(step_id) | ||
95 | + Delayed::Job.where(:handler => "--- !ruby/struct:CommunityTrackPlugin::ActivationJob \nstep_id: #{step_id}\n") | ||
96 | + end | ||
97 | + | ||
98 | + def perform | ||
99 | + step = CommunityTrackPlugin::Step.find(step_id) | ||
100 | + step.publish | ||
101 | + end | ||
102 | + | ||
103 | + end | ||
104 | + | ||
105 | +end |
plugins/community_track/lib/community_track_plugin/step_helper.rb
0 → 100644
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +module CommunityTrackPlugin::StepHelper | ||
2 | + | ||
3 | + def self.status_descriptions | ||
4 | + [_('Finished'), _('In progress'), _('Waiting')] | ||
5 | + end | ||
6 | + | ||
7 | + def self.status_classes | ||
8 | + ['step_finished', 'step_active', 'step_waiting'] | ||
9 | + end | ||
10 | + | ||
11 | + def status_description(step) | ||
12 | + CommunityTrackPlugin::StepHelper.status_descriptions[status_index(step)] | ||
13 | + end | ||
14 | + | ||
15 | + def status_class(step) | ||
16 | + CommunityTrackPlugin::StepHelper.status_classes[status_index(step)] | ||
17 | + end | ||
18 | + | ||
19 | + def custom_options_for_article(article) | ||
20 | + #no options for step? | ||
21 | + nil | ||
22 | + end | ||
23 | + | ||
24 | + protected | ||
25 | + | ||
26 | + def status_index(step) | ||
27 | + [step.finished?, step.active?, step.waiting?].find_index(true) | ||
28 | + end | ||
29 | + | ||
30 | +end |
plugins/community_track/lib/community_track_plugin/track.rb
0 → 100644
@@ -0,0 +1,70 @@ | @@ -0,0 +1,70 @@ | ||
1 | +class CommunityTrackPlugin::Track < Folder | ||
2 | + | ||
3 | + settings_items :goals, :type => :string | ||
4 | + settings_items :expected_results, :type => :string | ||
5 | + | ||
6 | + def self.icon_name(article = nil) | ||
7 | + 'community-track' | ||
8 | + end | ||
9 | + | ||
10 | + def self.short_description | ||
11 | + _("Track") | ||
12 | + end | ||
13 | + | ||
14 | + def self.description | ||
15 | + _('Defines a track.') | ||
16 | + end | ||
17 | + | ||
18 | + def steps | ||
19 | + #XXX article default order is name (acts_as_filesystem) -> should use reorder (rails3) | ||
20 | + steps_unsorted.sort_by(&:position).select{|s| !s.hidden} | ||
21 | + end | ||
22 | + | ||
23 | + def hidden_steps | ||
24 | + steps_unsorted.select{|s| s.hidden} | ||
25 | + end | ||
26 | + | ||
27 | + def reorder_steps(step_ids) | ||
28 | + transaction do | ||
29 | + step_ids.each_with_index do |step_id, i| | ||
30 | + step = steps_unsorted.find(step_id) | ||
31 | + step.update_attribute(:position, step.position = i + 1) | ||
32 | + end | ||
33 | + end | ||
34 | + end | ||
35 | + | ||
36 | + def steps_unsorted | ||
37 | + children.where(:type => 'CommunityTrackPlugin::Step') | ||
38 | + end | ||
39 | + | ||
40 | + def accept_comments? | ||
41 | + false | ||
42 | + end | ||
43 | + | ||
44 | + def comments_count | ||
45 | + steps_unsorted.joins(:children).sum('childrens_articles.comments_count') | ||
46 | + end | ||
47 | + | ||
48 | + def css_class_name | ||
49 | + "community-track-plugin-track" | ||
50 | + end | ||
51 | + | ||
52 | + def first_paragraph | ||
53 | + return '' if body.blank? | ||
54 | + paragraphs = Hpricot(body).search('p') | ||
55 | + paragraphs.empty? ? '' : paragraphs.first.to_html | ||
56 | + end | ||
57 | + | ||
58 | + def category_name | ||
59 | + category = categories.first | ||
60 | + category ? category.name : '' | ||
61 | + end | ||
62 | + | ||
63 | + def to_html(options = {}) | ||
64 | + track = self | ||
65 | + lambda do | ||
66 | + render :file => 'content_viewer/track.rhtml', :locals => {:track => track} | ||
67 | + end | ||
68 | + end | ||
69 | + | ||
70 | +end |
plugins/community_track/lib/community_track_plugin/track_card_list_block.rb
0 → 100644
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +class CommunityTrackPlugin::TrackCardListBlock < CommunityTrackPlugin::TrackListBlock | ||
2 | + | ||
3 | + def self.description | ||
4 | + _('Track Card List') | ||
5 | + end | ||
6 | + | ||
7 | + def help | ||
8 | + _('This block displays a list of most relevant tracks as cards.') | ||
9 | + end | ||
10 | + | ||
11 | + def track_partial | ||
12 | + 'track_card' | ||
13 | + end | ||
14 | + | ||
15 | +end |
plugins/community_track/lib/community_track_plugin/track_helper.rb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +module CommunityTrackPlugin::TrackHelper | ||
2 | + | ||
3 | + def category_class(track) | ||
4 | + 'category_' + (track.categories.empty? ? 'not_defined' : track.categories.first.name.to_slug) | ||
5 | + end | ||
6 | + | ||
7 | + def track_card_lead(track) | ||
8 | + lead_stripped = strip_tags(track.lead) | ||
9 | + excerpt(lead_stripped, lead_stripped.first(3), track.image ? 180 : 300) | ||
10 | + end | ||
11 | + | ||
12 | +end |
plugins/community_track/lib/community_track_plugin/track_list_block.rb
0 → 100644
@@ -0,0 +1,64 @@ | @@ -0,0 +1,64 @@ | ||
1 | +class CommunityTrackPlugin::TrackListBlock < Block | ||
2 | + | ||
3 | + include CommunityTrackPlugin::StepHelper | ||
4 | + | ||
5 | + settings_items :limit, :type => :integer, :default => 3 | ||
6 | + settings_items :more_another_page, :type => :boolean, :default => false | ||
7 | + settings_items :category_ids, :type => Array, :default => [] | ||
8 | + | ||
9 | + def self.description | ||
10 | + _('Track List') | ||
11 | + end | ||
12 | + | ||
13 | + def help | ||
14 | + _('This block displays a list of most relevant tracks.') | ||
15 | + end | ||
16 | + | ||
17 | + def track_partial | ||
18 | + 'track' | ||
19 | + end | ||
20 | + | ||
21 | + def tracks(page=1, per_page=limit) | ||
22 | + all_tracks.order('hits DESC').paginate(:per_page => per_page, :page => page) | ||
23 | + end | ||
24 | + | ||
25 | + def count_tracks | ||
26 | + all_tracks.count | ||
27 | + end | ||
28 | + | ||
29 | + def accept_category?(cat) | ||
30 | + true #accept all? | ||
31 | + end | ||
32 | + | ||
33 | + def category_ids=(ids) | ||
34 | + settings[:category_ids] = ids.uniq.map{|item| item.to_i unless item.to_i.zero?}.compact | ||
35 | + end | ||
36 | + | ||
37 | + def all_tracks | ||
38 | + tracks = owner.articles.where(:type => 'CommunityTrackPlugin::Track') | ||
39 | + if !category_ids.empty? | ||
40 | + tracks = tracks.joins(:article_categorizations).where(:articles_categories => {:category_id => category_ids}) | ||
41 | + end | ||
42 | + tracks | ||
43 | + end | ||
44 | + | ||
45 | + def content(args={}) | ||
46 | + block = self | ||
47 | + lambda do | ||
48 | + render :file => 'blocks/track_list.rhtml', :locals => {:block => block} | ||
49 | + end | ||
50 | + end | ||
51 | + | ||
52 | + def has_page?(page, per_page=limit) | ||
53 | + return (page-1) * per_page < count_tracks | ||
54 | + end | ||
55 | + | ||
56 | + def footer | ||
57 | + block = self | ||
58 | + return nil if !has_page?(2) | ||
59 | + lambda do | ||
60 | + render :partial => 'blocks/track_list_more', :locals => {:block => block, :page => 2, :per_page => block.limit} | ||
61 | + end | ||
62 | + end | ||
63 | + | ||
64 | +end |
604 Bytes
1.49 KB
@@ -0,0 +1,201 @@ | @@ -0,0 +1,201 @@ | ||
1 | +.icon-newcommunity-track, | ||
2 | +.icon-community-track { | ||
3 | + background-image: url(/plugins/community_track/icons/community-track.png) | ||
4 | +} | ||
5 | + | ||
6 | +.step_active, #article .step_active a { | ||
7 | + background-color: #CCEBD6; | ||
8 | + color: #338533; | ||
9 | +} | ||
10 | + | ||
11 | +.step_waiting, #article .step_waiting a { | ||
12 | + background-color: #FFFFD1; | ||
13 | + color: #D17519; | ||
14 | +} | ||
15 | + | ||
16 | +.step_finished, #article .step_finished a { | ||
17 | + background-color: #D1FFFF; | ||
18 | + color: #00297A; | ||
19 | +} | ||
20 | + | ||
21 | +.step_status_description { | ||
22 | + float: right; | ||
23 | +} | ||
24 | + | ||
25 | +.step { | ||
26 | + font-weight: bold; | ||
27 | +} | ||
28 | + | ||
29 | +.track_list .item .step { | ||
30 | + padding: 8px 5px; | ||
31 | +} | ||
32 | + | ||
33 | +#article .step a { | ||
34 | + text-decoration: none; | ||
35 | +} | ||
36 | + | ||
37 | +.track_list .item .track_content .lead { | ||
38 | + float: left; | ||
39 | + width: 50%; | ||
40 | +} | ||
41 | + | ||
42 | +.track_list .item .track_content .steps { | ||
43 | + float: right; | ||
44 | + width: 50%; | ||
45 | +} | ||
46 | + | ||
47 | +.track_list .item { | ||
48 | + border-bottom: 1px solid #DDDDDD; | ||
49 | +} | ||
50 | + | ||
51 | +.track_stats, .track_content { | ||
52 | + clear: both; | ||
53 | +} | ||
54 | + | ||
55 | +.track_stats .comments { | ||
56 | + float: left; | ||
57 | +} | ||
58 | + | ||
59 | +.track_stats .hits { | ||
60 | + float: right; | ||
61 | +} | ||
62 | + | ||
63 | +.track_list .item_card { | ||
64 | + width: 155px; | ||
65 | + border: 1px solid #DDDDDD; | ||
66 | + float: left; | ||
67 | + padding: 0px 8px; | ||
68 | + margin-left: 3px; | ||
69 | + margin-right: 3px; | ||
70 | + margin-bottom: 8px; | ||
71 | +} | ||
72 | + | ||
73 | +.steps .step { | ||
74 | + margin-top: 3px; | ||
75 | + margin-bottom: 3px; | ||
76 | +} | ||
77 | + | ||
78 | +.track_list .item_card .track_stats { | ||
79 | + border-top: 1px solid #DDDDDD; | ||
80 | +} | ||
81 | + | ||
82 | +.track_list .item_card a, .track_list .item_card a:hover, .track_list .item_card a:visited { | ||
83 | + text-decoration: none; | ||
84 | + color: #444; | ||
85 | +} | ||
86 | + | ||
87 | +.track_list .item_card:hover { | ||
88 | + background: #EEE; | ||
89 | +} | ||
90 | + | ||
91 | +.track_list .title { | ||
92 | + font-size: 16px; | ||
93 | + font-weight: bold; | ||
94 | + border-bottom: 1px solid #DDDDDD; | ||
95 | + padding: 2px 0px; | ||
96 | + margin-bottom: 5px; | ||
97 | + min-height: 10px; | ||
98 | +} | ||
99 | + | ||
100 | +.track_list .image img { | ||
101 | + max-width: 100%; | ||
102 | + max-height: 100px; | ||
103 | + display: block; | ||
104 | + margin-left: auto; | ||
105 | + margin-right: auto; | ||
106 | +} | ||
107 | + | ||
108 | +.track_list .name { | ||
109 | + padding-top: 5px; | ||
110 | +} | ||
111 | + | ||
112 | +.track_list .item_card { | ||
113 | + height: 270px; | ||
114 | +} | ||
115 | + | ||
116 | +.track_list .track_content { | ||
117 | + height: 250px; | ||
118 | +} | ||
119 | + | ||
120 | +#track .step_list { | ||
121 | + list-style-type: none; | ||
122 | + margin: 0; | ||
123 | + padding: 0; | ||
124 | +} | ||
125 | + | ||
126 | +#track .position { | ||
127 | + font-size: 24px; | ||
128 | + font-weight: bold; | ||
129 | + float: left; | ||
130 | + margin: 0 10px; | ||
131 | +} | ||
132 | + | ||
133 | +#track .step .name, #track .step .name a { | ||
134 | + font-weight: bold; | ||
135 | + color: #333; | ||
136 | +} | ||
137 | + | ||
138 | +#track .step .name a:hover { | ||
139 | + color: #555; | ||
140 | +} | ||
141 | + | ||
142 | +#track .step .date { | ||
143 | + font-size: 12px; | ||
144 | + color: #AAA; | ||
145 | +} | ||
146 | + | ||
147 | +#track .step .lead { | ||
148 | + margin: 0px 10px; | ||
149 | + color: #555; | ||
150 | +} | ||
151 | + | ||
152 | +#track .content { | ||
153 | + margin: 6px 0px; | ||
154 | + border-bottom: 1px solid #DDDDDD; | ||
155 | +} | ||
156 | + | ||
157 | +#track .ui-state-default .content { | ||
158 | + border-bottom: 0px; | ||
159 | +} | ||
160 | + | ||
161 | +.track_list .item .step .position { | ||
162 | + float: left; | ||
163 | + padding-right: 5px; | ||
164 | +} | ||
165 | + | ||
166 | +#track .actions .save_button { | ||
167 | + display: none; | ||
168 | +} | ||
169 | + | ||
170 | +#track .actions, #step .actions { | ||
171 | + margin-bottom: 20px; | ||
172 | +} | ||
173 | + | ||
174 | +#edit-track-list-block .categorie_box a { | ||
175 | + float: left; | ||
176 | +} | ||
177 | + | ||
178 | +.all_tracks .more_button { | ||
179 | + text-align: center; | ||
180 | +} | ||
181 | + | ||
182 | +#step .tools .item .name a, #step .tools .item .name a:hover { | ||
183 | + border: none; | ||
184 | + background-color: transparent; | ||
185 | + color: #666; | ||
186 | + font-weight: bold; | ||
187 | +} | ||
188 | + | ||
189 | +#step .tools .item .name a:hover { | ||
190 | + color: #888; | ||
191 | +} | ||
192 | + | ||
193 | +.community-track textarea { | ||
194 | + width: 100%; | ||
195 | +} | ||
196 | + | ||
197 | +.formfield input#datepicker-from-date, | ||
198 | +.formfield input#datepicker-to-date { | ||
199 | + width: 115px; | ||
200 | + background: url(/plugins/community_track/icons/calendar.png) right center no-repeat; | ||
201 | +} |
plugins/community_track/test/functional/community_track_plugin_cms_controller_test.rb
0 → 100644
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +# Re-raise errors caught by the controller. | ||
4 | +class CmsController; def rescue_action(e) raise e end; end | ||
5 | + | ||
6 | +class CmsControllerTest < ActionController::TestCase | ||
7 | + | ||
8 | + def setup | ||
9 | + @profile = fast_create(Community) | ||
10 | + @track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track', :profile => @profile) | ||
11 | + @step = CommunityTrackPlugin::Step.create!(:name => 'step1', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today) | ||
12 | + | ||
13 | + user = create_user('testinguser') | ||
14 | + @profile.add_admin(user.person) | ||
15 | + login_as(user.login) | ||
16 | + end | ||
17 | + | ||
18 | + should 'be able to edit track' do | ||
19 | + get :edit, :id => @track.id, :profile => @profile.identifier | ||
20 | + assert_tag :tag => 'input', :attributes => { :id => 'article_name' } | ||
21 | + end | ||
22 | + | ||
23 | + should 'be able to edit step' do | ||
24 | + get :edit, :id => @step.id, :profile => @profile.identifier | ||
25 | + assert_tag :tag => 'input', :attributes => { :id => 'article_name' } | ||
26 | + end | ||
27 | + | ||
28 | + should 'be able to save track' do | ||
29 | + get :edit, :id => @track.id, :profile => @profile.identifier | ||
30 | + post :edit, :id => @track.id, :profile => @profile.identifier, :article => {:name => 'changed'} | ||
31 | + @track.reload | ||
32 | + assert_equal 'changed', @track.name | ||
33 | + end | ||
34 | + | ||
35 | + should 'be able to save step' do | ||
36 | + get :edit, :id => @step.id, :profile => @profile.identifier | ||
37 | + post :edit, :id => @step.id, :profile => @profile.identifier, :article => {:name => 'changed'} | ||
38 | + @step.reload | ||
39 | + assert_equal 'changed', @step.name | ||
40 | + end | ||
41 | + | ||
42 | + should 'do not be able to edit visibility of step' do | ||
43 | + get :edit, :id => @step.id, :profile => @profile.identifier | ||
44 | + assert_no_tag :tag => 'input', :attributes => { :name => 'article[published]' } | ||
45 | + end | ||
46 | + | ||
47 | +end |
plugins/community_track/test/functional/community_track_plugin_content_viewer_controller_test.rb
0 → 100644
@@ -0,0 +1,147 @@ | @@ -0,0 +1,147 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class ContentViewerController | ||
4 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') | ||
5 | + def rescue_action(e) | ||
6 | + raise e | ||
7 | + end | ||
8 | +end | ||
9 | + | ||
10 | +class ContentViewerControllerTest < ActionController::TestCase | ||
11 | + | ||
12 | + def setup | ||
13 | + @profile = fast_create(Community) | ||
14 | + @track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track', :profile => @profile) | ||
15 | + category = fast_create(Category, :name => "education") | ||
16 | + @track.add_category(category) | ||
17 | + | ||
18 | + @step = CommunityTrackPlugin::Step.create!(:name => 'step1', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today) | ||
19 | + | ||
20 | + user = create_user('testinguser') | ||
21 | + login_as(user.login) | ||
22 | + @profile.add_admin(user.person) | ||
23 | + end | ||
24 | + | ||
25 | + should 'show actions for tracks when user has permission for edit' do | ||
26 | + get :view_page, @track.url | ||
27 | + assert_tag :tag => 'div', :attributes => {:id => 'track' }, :descendant => { :tag => 'div', :attributes => { :class => 'actions' } } | ||
28 | + end | ||
29 | + | ||
30 | + should 'do not show actions for tracks when user has not permission for edit' do | ||
31 | + user = create_user('intruder') | ||
32 | + logout | ||
33 | + login_as(user.login) | ||
34 | + get :view_page, @track.url | ||
35 | + assert_no_tag :tag => 'div', :attributes => {:id => 'track' }, :descendant => { :tag => 'div', :attributes => { :class => 'actions' } } | ||
36 | + end | ||
37 | + | ||
38 | + should 'do not show new button at article toolbar for tracks' do | ||
39 | + user = create_user('intruder') | ||
40 | + logout | ||
41 | + login_as(user.login) | ||
42 | + get :view_page, @track.url | ||
43 | + assert_no_tag :tag => 'div', :attributes => {:id => 'article-actions'}, :descendant => { :tag => 'div', :attributes => { :id => 'icon-new' } } | ||
44 | + end | ||
45 | + | ||
46 | + should 'display steps for tracks' do | ||
47 | + get :view_page, @track.url | ||
48 | + assert_tag :tag => 'ul', :attributes => { :id => 'sortable' }, :descendant => {:tag => 'li', :attributes => { :class => 'step' } } | ||
49 | + end | ||
50 | + | ||
51 | + should 'display hidden field with step id' do | ||
52 | + get :view_page, @track.url | ||
53 | + assert_tag :tag => 'input', :attributes => { :name => 'step_ids[]' } | ||
54 | + end | ||
55 | + | ||
56 | + should 'show step' do | ||
57 | + get :view_page, @step.url | ||
58 | + assert_tag :tag => 'div', :attributes => { :id => 'step' } | ||
59 | + end | ||
60 | + | ||
61 | + should 'show tools for a step' do | ||
62 | + Article.create!(:profile => @profile, :name => 'article', :parent => @step) | ||
63 | + get :view_page, @step.url | ||
64 | + assert_tag :tag => 'div', :attributes => { :class => 'tools' }, :descendant => { :tag => 'div', :attributes => { :class => 'item' } } | ||
65 | + end | ||
66 | + | ||
67 | + should 'show actions for steps when user has permission for edit' do | ||
68 | + get :view_page, @step.url | ||
69 | + assert_tag :tag => 'div', :attributes => {:id => 'step' }, :descendant => { :tag => 'div', :attributes => { :class => 'actions' } } | ||
70 | + end | ||
71 | + | ||
72 | + should 'show actions for enabled tools in step' do | ||
73 | + get :view_page, @step.url | ||
74 | + assert_tag 'div', :attributes => {:class => 'actions' }, :descendant => { :tag => 'a', :attributes => { :class => 'button with-text icon-new icon-newforum' } } | ||
75 | + assert_tag 'div', :attributes => {:class => 'actions' }, :descendant => { :tag => 'a', :attributes => { :class => 'button with-text icon-new icon-newtext-html' } } | ||
76 | + end | ||
77 | + | ||
78 | + should 'do not show actions for steps when user has not permission for edit' do | ||
79 | + user = create_user('intruder') | ||
80 | + logout | ||
81 | + login_as(user.login) | ||
82 | + get :view_page, @step.url | ||
83 | + assert_no_tag :tag => 'div', :attributes => {:id => 'step' }, :descendant => { :tag => 'div', :attributes => { :class => 'actions' } } | ||
84 | + end | ||
85 | + | ||
86 | + should 'render a div with block id for track list block' do | ||
87 | + box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name) | ||
88 | + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => box) | ||
89 | + @profile.boxes << box | ||
90 | + get :view_page, @step.url | ||
91 | + assert_tag :tag => 'div', :attributes => { :class => 'track_list', :id => "track_list_#{@block.id}" } | ||
92 | + end | ||
93 | + | ||
94 | + should 'render a div with block id for track card list block' do | ||
95 | + box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name) | ||
96 | + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box) | ||
97 | + @profile.boxes << box | ||
98 | + get :view_page, @step.url | ||
99 | + assert_tag :tag => 'div', :attributes => { :class => 'track_list', :id => "track_list_#{@block.id}" } | ||
100 | + end | ||
101 | + | ||
102 | + should 'render tracks in track list block' do | ||
103 | + box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name) | ||
104 | + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => box) | ||
105 | + @profile.boxes << box | ||
106 | + get :view_page, @step.url | ||
107 | + assert_tag :tag => 'div', :attributes => { :class => 'item category_education' }, :descendant => { :tag => 'div', :attributes => { :class => 'steps' }, :descendant => { :tag => 'div', :attributes => { :class => "step #{@block.status_class(@step)}" } } } | ||
108 | + end | ||
109 | + | ||
110 | + should 'render tracks in track card list block' do | ||
111 | + box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name) | ||
112 | + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box) | ||
113 | + @profile.boxes << box | ||
114 | + get :view_page, @step.url | ||
115 | + assert_tag :tag => 'div', :attributes => { :class => 'item_card category_education' }, :descendant => { :tag => 'div', :attributes => { :class => 'track_content' } } | ||
116 | + assert_tag :tag => 'div', :attributes => { :class => 'item_card category_education' }, :descendant => { :tag => 'div', :attributes => { :class => 'track_stats' } } | ||
117 | + end | ||
118 | + | ||
119 | + should 'render link to display more tracks in track list block' do | ||
120 | + box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name) | ||
121 | + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box) | ||
122 | + @profile.boxes << box | ||
123 | + | ||
124 | + (@block.limit+1).times do |i| | ||
125 | + CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @profile) | ||
126 | + end | ||
127 | + | ||
128 | + get :view_page, @step.url | ||
129 | + assert_tag :tag => 'div', :attributes => { :id => "track_list_more_#{@block.id}" }, :descendant => { :tag => 'div', :attributes => { :class => 'more' } } | ||
130 | + end | ||
131 | + | ||
132 | + should 'render link to show all tracks in track list block' do | ||
133 | + box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name) | ||
134 | + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box) | ||
135 | + @profile.boxes << box | ||
136 | + @block.more_another_page = true | ||
137 | + @block.save! | ||
138 | + | ||
139 | + (@block.limit+1).times do |i| | ||
140 | + CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @profile) | ||
141 | + end | ||
142 | + | ||
143 | + get :view_page, @step.url | ||
144 | + assert_tag :tag => 'div', :attributes => { :id => "track_list_more_#{@block.id}" }, :descendant => { :tag => 'div', :attributes => { :class => 'view_all' } } | ||
145 | + end | ||
146 | + | ||
147 | +end |
plugins/community_track/test/functional/community_track_plugin_environment_design_controller_test.rb
0 → 100644
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +# Re-raise errors caught by the controller. | ||
4 | +class EnvironmentDesignController; def rescue_action(e) raise e end; end | ||
5 | + | ||
6 | +class EnvironmentDesignControllerTest < ActionController::TestCase | ||
7 | + | ||
8 | + def setup | ||
9 | + Environment.delete_all | ||
10 | + @environment = Environment.new(:name => 'testenv', :is_default => true) | ||
11 | + @environment.enabled_plugins = ['CommunityTrackPlugin'] | ||
12 | + @environment.save! | ||
13 | + | ||
14 | + user = create_user('testinguser') | ||
15 | + @environment.add_admin(user.person) | ||
16 | + login_as(user.login) | ||
17 | + | ||
18 | + box = Box.create!(:owner => @environment) | ||
19 | + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => box) | ||
20 | + @block_card = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box) | ||
21 | + end | ||
22 | + | ||
23 | + should 'be able to edit TrackListBlock' do | ||
24 | + get :edit, :id => @block.id | ||
25 | + assert_tag :tag => 'input', :attributes => { :id => 'block_title' } | ||
26 | + end | ||
27 | + | ||
28 | + should 'be able to save TrackListBlock' do | ||
29 | + get :edit, :id => @block.id | ||
30 | + post :save, :id => @block.id, :block => {:title => 'Tracks' } | ||
31 | + @block.reload | ||
32 | + assert_equal 'Tracks', @block.title | ||
33 | + end | ||
34 | + | ||
35 | + should 'be able to edit TrackCardListBlock' do | ||
36 | + get :edit, :id => @block_card.id | ||
37 | + assert_tag :tag => 'input', :attributes => { :id => 'block_title' } | ||
38 | + end | ||
39 | + | ||
40 | + should 'be able to save TrackCardListBlock' do | ||
41 | + get :edit, :id => @block_card.id | ||
42 | + post :save, :id => @block_card.id, :block => {:title => 'Tracks' } | ||
43 | + @block_card.reload | ||
44 | + assert_equal 'Tracks', @block_card.title | ||
45 | + end | ||
46 | + | ||
47 | +end |
plugins/community_track/test/functional/community_track_plugin_myprofile_controller_test.rb
0 → 100644
@@ -0,0 +1,49 @@ | @@ -0,0 +1,49 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | +require File.dirname(__FILE__) + '/../../controllers/myprofile/community_track_plugin_myprofile_controller' | ||
3 | + | ||
4 | +# Re-raise errors caught by the controller. | ||
5 | +class CommunityTrackPluginMyprofileController; def rescue_action(e) raise e end; end | ||
6 | + | ||
7 | +class CommunityTrackPluginMyprofileControllerTest < ActionController::TestCase | ||
8 | + | ||
9 | + def setup | ||
10 | + @controller = CommunityTrackPluginMyprofileController.new | ||
11 | + @request = ActionController::TestRequest.new | ||
12 | + @response = ActionController::TestResponse.new | ||
13 | + | ||
14 | + @profile = fast_create(Community) | ||
15 | + @track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track', :profile => @profile) | ||
16 | + | ||
17 | + @user = create_user('testinguser') | ||
18 | + login_as(@user.login) | ||
19 | + @profile.add_admin(@user.person) | ||
20 | + end | ||
21 | + | ||
22 | + should 'redirect to track on save order' do | ||
23 | + get :save_order, :profile => @profile.identifier, :track => @track.id, :step_ids => [] | ||
24 | + assert_redirected_to @track.url | ||
25 | + end | ||
26 | + | ||
27 | + should 'save new step positions on save order' do | ||
28 | + step1 = CommunityTrackPlugin::Step.create!(:name => 'step1', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today) | ||
29 | + step2 = CommunityTrackPlugin::Step.create!(:name => 'step2', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today) | ||
30 | + assert_equal [step1, step2], @track.steps | ||
31 | + get :save_order, :profile => @profile.identifier, :track => @track.id, :step_ids => [step2.id, step1.id] | ||
32 | + assert_equal [step2, step1], @track.steps | ||
33 | + end | ||
34 | + | ||
35 | + should 'do not allow a user without permission to save order' do | ||
36 | + logout | ||
37 | + user = create_user('intruder') | ||
38 | + login_as(user.login) | ||
39 | + get :save_order, :profile => @profile.identifier, :track => @track.id, :step_ids => [] | ||
40 | + assert_response 403 | ||
41 | + end | ||
42 | + | ||
43 | + should 'redirect to login page if there is no user logged in' do | ||
44 | + logout | ||
45 | + get :save_order, :profile => @profile.identifier, :track => @track.id, :step_ids => [] | ||
46 | + assert_response 302 | ||
47 | + end | ||
48 | + | ||
49 | +end |
plugins/community_track/test/functional/community_track_plugin_public_controller_test.rb
0 → 100644
@@ -0,0 +1,109 @@ | @@ -0,0 +1,109 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | +require File.dirname(__FILE__) + '/../../controllers/public/community_track_plugin_public_controller' | ||
3 | + | ||
4 | +# Re-raise errors caught by the controller. | ||
5 | +class CommunityTrackPluginPublicController; def rescue_action(e) raise e end; end | ||
6 | + | ||
7 | +class CommunityTrackPluginPublicControllerTest < ActionController::TestCase | ||
8 | + | ||
9 | + def setup | ||
10 | + @community = fast_create(Community) | ||
11 | + @track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track', :profile => @community) | ||
12 | + | ||
13 | + box = fast_create(Box, :owner_id => @community.id, :owner_type => 'Community') | ||
14 | + @card_block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box) | ||
15 | + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => box) | ||
16 | + end | ||
17 | + | ||
18 | + should 'display tracks for card block' do | ||
19 | + xhr :get, :view_tracks, :id => @card_block.id, :page => 1 | ||
20 | + assert_match /track_list_#{@card_block.id}/, @response.body | ||
21 | + end | ||
22 | + | ||
23 | + should 'display tracks for list block' do | ||
24 | + xhr :get, :view_tracks, :id => @block.id, :page => 1 | ||
25 | + assert_match /track_list_#{@block.id}/, @response.body | ||
26 | + end | ||
27 | + | ||
28 | + should 'display tracks with page size' do | ||
29 | + 20.times do |i| | ||
30 | + track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @community) | ||
31 | + end | ||
32 | + xhr :get, :view_tracks, :id => @block.id, :page => 1, :per_page => 10 | ||
33 | + assert_equal 10, @response.body.scan(/item/).size | ||
34 | + end | ||
35 | + | ||
36 | + should 'default page size is the block limit' do | ||
37 | + 20.times do |i| | ||
38 | + track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @community) | ||
39 | + end | ||
40 | + xhr :get, :view_tracks, :id => @block.id, :page => 1 | ||
41 | + assert_equal @block.limit, @response.body.scan(/item/).size | ||
42 | + end | ||
43 | + | ||
44 | + should 'display page for all tracks' do | ||
45 | + get :all_tracks, :id => @block.id | ||
46 | + assert_match /track_list_#{@block.id}/, @response.body | ||
47 | + end | ||
48 | + | ||
49 | + should 'show more link in all tracks if there is no more tracks to show' do | ||
50 | + 10.times do |i| | ||
51 | + CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @community) | ||
52 | + end | ||
53 | + get :all_tracks, :id => @block.id | ||
54 | + assert assigns['show_more'] | ||
55 | + assert_match /track_list_more_#{@block.id}/, @response.body | ||
56 | + end | ||
57 | + | ||
58 | + should 'do not show more link in all tracks if there is no more tracks to show' do | ||
59 | + CommunityTrackPlugin::Track.destroy_all | ||
60 | + get :all_tracks, :id => @block.id | ||
61 | + assert !assigns['show_more'] | ||
62 | + assert_no_match /track_list_more_#{@block.id}/, @response.body | ||
63 | + end | ||
64 | + | ||
65 | + should 'show select community page if user is logged in' do | ||
66 | + user = create_user('testinguser') | ||
67 | + login_as(user.login) | ||
68 | + get :select_community | ||
69 | + assert_template 'select_community' | ||
70 | + end | ||
71 | + | ||
72 | + should 'redirect to login page if user try to access community selection' do | ||
73 | + logout | ||
74 | + get :select_community | ||
75 | + assert_redirected_to :controller => 'account', :action => 'login' | ||
76 | + end | ||
77 | + | ||
78 | + should 'display for selection communities where user has permission to post content' do | ||
79 | + user = create_user('testinguser') | ||
80 | + login_as(user.login) | ||
81 | + @community.add_member(user.person) | ||
82 | + get :select_community | ||
83 | + assert_tag :tag => 'li', :attributes => {:class => 'search-profile-item'} | ||
84 | + assert_tag :tag => 'input', :attributes => {:id => "community_identifier_#{@community.identifier}"} | ||
85 | + end | ||
86 | + | ||
87 | + should 'do not display communities where user has not permission to post content' do | ||
88 | + user = create_user('testinguser') | ||
89 | + login_as(user.login) | ||
90 | + get :select_community | ||
91 | + assert_no_tag :tag => 'input', :attributes => {:id => "community_identifier_#{@community.identifier}"} | ||
92 | + end | ||
93 | + | ||
94 | + should 'redirect to new content with track content type' do | ||
95 | + user = create_user('testinguser') | ||
96 | + login_as(user.login) | ||
97 | + post :select_community, :profile => user.person.identifier, :community_identifier => @community.identifier | ||
98 | + assert_redirected_to :controller => 'cms', :action => 'new', :type => "CommunityTrackPlugin::Track", :profile => @community.identifier | ||
99 | + end | ||
100 | + | ||
101 | + should 'return error message if user do not select a community' do | ||
102 | + user = create_user('testinguser') | ||
103 | + login_as(user.login) | ||
104 | + post :select_community, :profile => user.person.identifier, :community_identifier => nil | ||
105 | + assert_equal 1, assigns(:failed).count | ||
106 | + assert_tag :tag => 'div', :attributes => {:id => 'errorExplanation'} | ||
107 | + end | ||
108 | + | ||
109 | +end |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' |
plugins/community_track/test/unit/community_track_plugin/step_helper_test.rb
0 → 100644
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../test_helper' | ||
2 | + | ||
3 | +class StepHelperTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + include CommunityTrackPlugin::StepHelper | ||
6 | + | ||
7 | + def setup | ||
8 | + @step = CommunityTrackPlugin::Step.new | ||
9 | + @step.stubs(:active?).returns(false) | ||
10 | + @step.stubs(:finished?).returns(false) | ||
11 | + @step.stubs(:waiting?).returns(false) | ||
12 | + end | ||
13 | + | ||
14 | + should 'return active class when step is active' do | ||
15 | + @step.stubs(:active?).returns(true) | ||
16 | + assert_equal 'step_active', status_class(@step) | ||
17 | + end | ||
18 | + | ||
19 | + should 'return finished class when step is finished' do | ||
20 | + @step.stubs(:finished?).returns(true) | ||
21 | + assert_equal 'step_finished', status_class(@step) | ||
22 | + end | ||
23 | + | ||
24 | + should 'return waiting class when step is active' do | ||
25 | + @step.stubs(:waiting?).returns(true) | ||
26 | + assert_equal 'step_waiting', status_class(@step) | ||
27 | + end | ||
28 | + | ||
29 | + should 'return a description for status' do | ||
30 | + @step.stubs(:waiting?).returns(true) | ||
31 | + assert_equal _('Waiting'), status_description(@step) | ||
32 | + end | ||
33 | + | ||
34 | + should 'return nil at custom_options_for_article' do | ||
35 | + assert !custom_options_for_article(fast_create(Article)) | ||
36 | + end | ||
37 | + | ||
38 | +end |
plugins/community_track/test/unit/community_track_plugin/step_test.rb
0 → 100644
@@ -0,0 +1,265 @@ | @@ -0,0 +1,265 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../test_helper' | ||
2 | + | ||
3 | +class StepTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @profile = fast_create(Community) | ||
7 | + @track = CommunityTrackPlugin::Track.create(:profile_id => @profile.id, :name => 'track') | ||
8 | + @step = CommunityTrackPlugin::Step.new(:name => 'Step', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today) | ||
9 | + Delayed::Job.destroy_all | ||
10 | + end | ||
11 | + | ||
12 | + should 'describe yourself' do | ||
13 | + assert CommunityTrackPlugin::Step.description | ||
14 | + end | ||
15 | + | ||
16 | + should 'has a short description' do | ||
17 | + assert CommunityTrackPlugin::Step.short_description | ||
18 | + end | ||
19 | + | ||
20 | + should 'set published to false on create' do | ||
21 | + today = Date.today | ||
22 | + step = CommunityTrackPlugin::Step.create(:name => 'Step', :body => 'body', :profile => @profile, :parent => @track, :start_date => today, :end_date => today, :published => true) | ||
23 | + assert !step.published | ||
24 | + end | ||
25 | + | ||
26 | + should 'do not allow step creation with a parent that is not a track' do | ||
27 | + today = Date.today | ||
28 | + blog = fast_create(Blog) | ||
29 | + step = CommunityTrackPlugin::Step.new(:name => 'Step', :body => 'body', :profile => @profile, :parent => blog, :start_date => today, :end_date => today, :published => true) | ||
30 | + assert !step.save | ||
31 | + end | ||
32 | + | ||
33 | + should 'do not allow step creation without a parent' do | ||
34 | + today = Date.today | ||
35 | + step = CommunityTrackPlugin::Step.new(:name => 'Step', :body => 'body', :profile => @profile, :parent => nil, :start_date => today, :end_date => today, :published => true) | ||
36 | + assert !step.save | ||
37 | + end | ||
38 | + | ||
39 | + should 'create step if end date is equal to start date' do | ||
40 | + @step.start_date = Date.today | ||
41 | + @step.end_date = Date.today | ||
42 | + assert @step.save | ||
43 | + end | ||
44 | + | ||
45 | + should 'create step if end date is after start date' do | ||
46 | + @step.start_date = Date.today | ||
47 | + @step.end_date = Date.today + 1.day | ||
48 | + assert @step.save | ||
49 | + end | ||
50 | + | ||
51 | + should 'do not create step if end date is before start date' do | ||
52 | + @step.start_date = Date.today | ||
53 | + @step.end_date = Date.today - 1.day | ||
54 | + assert !@step.save | ||
55 | + end | ||
56 | + | ||
57 | + should 'do not validate date period if start date is nil' do | ||
58 | + @step.start_date = nil | ||
59 | + @step.end_date_equal_or_after_start_date.inspect | ||
60 | + assert [], @step.errors | ||
61 | + end | ||
62 | + | ||
63 | + should 'do not validate date period if end date is nil' do | ||
64 | + @step.end_date = nil | ||
65 | + @step.end_date_equal_or_after_start_date.inspect | ||
66 | + assert [], @step.errors | ||
67 | + end | ||
68 | + | ||
69 | + should 'be active if today is between start and end dates' do | ||
70 | + @step.start_date = Date.today | ||
71 | + @step.end_date = Date.today + 1.day | ||
72 | + assert @step.active? | ||
73 | + end | ||
74 | + | ||
75 | + should 'be finished if today is after the end date' do | ||
76 | + @step.start_date = Date.today - 2.day | ||
77 | + @step.end_date = Date.today - 1.day | ||
78 | + assert @step.finished? | ||
79 | + end | ||
80 | + | ||
81 | + should 'be waiting if today is before the end date' do | ||
82 | + @step.start_date = Date.today + 1.day | ||
83 | + @step.end_date = Date.today + 2.day | ||
84 | + assert @step.waiting? | ||
85 | + end | ||
86 | + | ||
87 | + should 'return delayed job created with a specific step_id' do | ||
88 | + step_id = 0 | ||
89 | + CommunityTrackPlugin::ActivationJob.new(step_id) | ||
90 | + assert CommunityTrackPlugin::ActivationJob.find(step_id) | ||
91 | + end | ||
92 | + | ||
93 | + should 'create delayed job' do | ||
94 | + @step.start_date = Date.today | ||
95 | + @step.end_date = Date.today | ||
96 | + @step.schedule_activation | ||
97 | + assert_equal 1, Delayed::Job.count | ||
98 | + assert_equal @step.start_date, Delayed::Job.first.run_at.to_date | ||
99 | + end | ||
100 | + | ||
101 | + should 'do not duplicate delayed job' do | ||
102 | + @step.start_date = Date.today | ||
103 | + @step.end_date = Date.today | ||
104 | + @step.schedule_activation | ||
105 | + @step.schedule_activation | ||
106 | + assert_equal 1, Delayed::Job.count | ||
107 | + end | ||
108 | + | ||
109 | + should 'create delayed job when a step is saved' do | ||
110 | + @step.start_date = Date.today | ||
111 | + @step.end_date = Date.today | ||
112 | + @step.save! | ||
113 | + assert_equal @step.start_date, Delayed::Job.first.run_at.to_date | ||
114 | + end | ||
115 | + | ||
116 | + should 'create delayed job even if start date has passed' do | ||
117 | + @step.start_date = Date.today - 2.days | ||
118 | + @step.end_date = Date.today | ||
119 | + @step.schedule_activation | ||
120 | + assert_equal @step.start_date, Delayed::Job.first.run_at.to_date | ||
121 | + end | ||
122 | + | ||
123 | + should 'do not create delayed job if end date has passed and step is not published' do | ||
124 | + @step.start_date = Date.today - 5.days | ||
125 | + @step.end_date = Date.today - 2.days | ||
126 | + @step.published = false | ||
127 | + @step.schedule_activation | ||
128 | + assert_equal 0, Delayed::Job.count | ||
129 | + end | ||
130 | + | ||
131 | + should 'create delayed job if end date has passed and step is published' do | ||
132 | + @step.start_date = Date.today - 5.days | ||
133 | + @step.end_date = Date.today - 2.days | ||
134 | + @step.published = true | ||
135 | + @step.schedule_activation | ||
136 | + assert_equal @step.end_date + 1.day, Delayed::Job.first.run_at.to_date | ||
137 | + end | ||
138 | + | ||
139 | + should 'change publish to true on perform delayed job in a active step' do | ||
140 | + @step.start_date = Date.today | ||
141 | + @step.end_date = Date.today + 2.days | ||
142 | + @step.published = false | ||
143 | + @step.save! | ||
144 | + CommunityTrackPlugin::ActivationJob.new(@step.id).perform | ||
145 | + @step.reload | ||
146 | + assert @step.published | ||
147 | + end | ||
148 | + | ||
149 | + should 'reschedule delayed job after change publish to true' do | ||
150 | + @step.start_date = Date.today | ||
151 | + @step.end_date = Date.today + 2.days | ||
152 | + @step.published = false | ||
153 | + @step.save! | ||
154 | + assert_equal @step.start_date, Delayed::Job.first.run_at.to_date | ||
155 | + process_delayed_job_queue | ||
156 | + assert_equal @step.end_date + 1.day, Delayed::Job.first.run_at.to_date | ||
157 | + end | ||
158 | + | ||
159 | + should 'do not schedule delayed job if save but do not modify date fields and published status' do | ||
160 | + @step.start_date = Date.today | ||
161 | + @step.end_date = Date.today | ||
162 | + @step.published = false | ||
163 | + @step.save! | ||
164 | + assert_equal 1, Delayed::Job.count | ||
165 | + Delayed::Job.destroy_all | ||
166 | + @step.name = 'changed name' | ||
167 | + @step.save! | ||
168 | + assert_equal 0, Delayed::Job.count | ||
169 | + end | ||
170 | + | ||
171 | + should 'set position on save' do | ||
172 | + assert !@step.position | ||
173 | + @step.save! | ||
174 | + assert_equal 1, @step.position | ||
175 | + step2 = CommunityTrackPlugin::Step.new(:name => 'Step2', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today) | ||
176 | + step2.save! | ||
177 | + assert_equal 2, step2.position | ||
178 | + end | ||
179 | + | ||
180 | + should 'publish step if it is active' do | ||
181 | + @step.start_date = Date.today | ||
182 | + @step.save! | ||
183 | + assert !@step.published | ||
184 | + @step.publish | ||
185 | + @step.reload | ||
186 | + assert @step.published | ||
187 | + end | ||
188 | + | ||
189 | + should 'do not publish step if it is not active' do | ||
190 | + @step.start_date = Date.today + 2.days | ||
191 | + @step.end_date = Date.today + 3.days | ||
192 | + @step.save! | ||
193 | + assert !@step.published | ||
194 | + @step.publish | ||
195 | + @step.reload | ||
196 | + assert !@step.published | ||
197 | + end | ||
198 | + | ||
199 | + should 'unpublish step if it is not active anymore' do | ||
200 | + @step.start_date = Date.today | ||
201 | + @step.save! | ||
202 | + @step.publish | ||
203 | + @step.reload | ||
204 | + assert @step.published | ||
205 | + | ||
206 | + @step.start_date = Date.today - 2.days | ||
207 | + @step.end_date = Date.today - 1.day | ||
208 | + @step.save! | ||
209 | + @step.publish | ||
210 | + @step.reload | ||
211 | + assert !@step.published | ||
212 | + end | ||
213 | + | ||
214 | + should 'set position to zero if step is hidden' do | ||
215 | + @step.hidden = true | ||
216 | + @step.save! | ||
217 | + assert_equal 0, @step.position | ||
218 | + end | ||
219 | + | ||
220 | + should 'change position to zero if step becomes hidden' do | ||
221 | + @step.save! | ||
222 | + assert_equal 1, @step.position | ||
223 | + @step.hidden = true | ||
224 | + @step.save! | ||
225 | + assert_equal 0, @step.position | ||
226 | + end | ||
227 | + | ||
228 | + should 'change position to botton if a hidden step becomes visible' do | ||
229 | + step1 = CommunityTrackPlugin::Step.new(:name => 'Step1', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today) | ||
230 | + step1.save! | ||
231 | + @step.hidden = true | ||
232 | + @step.save! | ||
233 | + assert_equal 0, @step.position | ||
234 | + @step.hidden = false | ||
235 | + @step.save! | ||
236 | + assert_equal 2, @step.position | ||
237 | + end | ||
238 | + | ||
239 | + should 'decrement lower items positions if a step becomes hidden' do | ||
240 | + @step.save! | ||
241 | + step1 = CommunityTrackPlugin::Step.new(:name => 'Step1', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today) | ||
242 | + step1.save! | ||
243 | + assert_equal 2, step1.position | ||
244 | + @step.hidden = true | ||
245 | + @step.save! | ||
246 | + step1.reload | ||
247 | + assert_equal 1, step1.position | ||
248 | + end | ||
249 | + | ||
250 | + should 'do not publish a hidden step' do | ||
251 | + @step.start_date = Date.today | ||
252 | + @step.hidden = true | ||
253 | + @step.save! | ||
254 | + assert !@step.published | ||
255 | + @step.publish | ||
256 | + @step.reload | ||
257 | + assert !@step.published | ||
258 | + end | ||
259 | + | ||
260 | + should 'return enabled tools for a step' do | ||
261 | + assert_includes @step.enabled_tools, TinyMceArticle | ||
262 | + assert_includes @step.enabled_tools, Forum | ||
263 | + end | ||
264 | + | ||
265 | +end |
plugins/community_track/test/unit/community_track_plugin/track_card_list_block_test.rb
0 → 100644
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../test_helper' | ||
2 | + | ||
3 | +class TrackCardListBlockTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @community = fast_create(Community) | ||
7 | + box = fast_create(Box, :owner_id => @community.id, :owner_type => @community.class.name) | ||
8 | + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box) | ||
9 | + end | ||
10 | + | ||
11 | + should 'describe yourself' do | ||
12 | + assert CommunityTrackPlugin::TrackCardListBlock.description | ||
13 | + end | ||
14 | + | ||
15 | + should 'return track_card as track partial' do | ||
16 | + assert_equal 'track_card', @block.track_partial | ||
17 | + end | ||
18 | + | ||
19 | +end |
plugins/community_track/test/unit/community_track_plugin/track_helper_test.rb
0 → 100644
@@ -0,0 +1,55 @@ | @@ -0,0 +1,55 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../test_helper' | ||
2 | + | ||
3 | +class TrackHelperTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + include CommunityTrackPlugin::TrackHelper | ||
6 | + include NoosferoTestHelper | ||
7 | + include ActionView::Helpers::TextHelper | ||
8 | + | ||
9 | + def setup | ||
10 | + @track = CommunityTrackPlugin::Track.new | ||
11 | + end | ||
12 | + | ||
13 | + should 'return css class for track with category' do | ||
14 | + category = fast_create(Category, :name => 'education') | ||
15 | + @track.categories << category | ||
16 | + assert_equal 'category_education', category_class(@track) | ||
17 | + end | ||
18 | + | ||
19 | + should 'return default css class for a track without category' do | ||
20 | + assert_equal 'category_not_defined', category_class(@track) | ||
21 | + end | ||
22 | + | ||
23 | + should 'return css class for first category that the class belongs' do | ||
24 | + category1 = fast_create(Category, :name => 'education') | ||
25 | + @track.categories << category1 | ||
26 | + category2 = fast_create(Category, :name => 'tech') | ||
27 | + @track.categories << category2 | ||
28 | + assert_equal 'category_education', category_class(@track) | ||
29 | + end | ||
30 | + | ||
31 | + should 'return css class with category name properly formated' do | ||
32 | + category = fast_create(Category, :name => 'not defined') | ||
33 | + @track.categories << category | ||
34 | + assert_equal 'category_not-defined', category_class(@track) | ||
35 | + end | ||
36 | + | ||
37 | + should 'return lead for track removing html tags' do | ||
38 | + @track.abstract = "display <div>pure text</div>" | ||
39 | + assert_equal "display pure text", track_card_lead(@track) | ||
40 | + end | ||
41 | + | ||
42 | + should 'limit lead char length' do | ||
43 | + @track.abstract = "" | ||
44 | + 400.times { @track.abstract += "a" } | ||
45 | + assert_equal 306, track_card_lead(@track).length | ||
46 | + end | ||
47 | + | ||
48 | + should 'display a shorter lead if track has a image' do | ||
49 | + @track.abstract = "" | ||
50 | + @track.image = Image.new | ||
51 | + 400.times { @track.abstract += "a" } | ||
52 | + assert_equal 186, track_card_lead(@track).length | ||
53 | + end | ||
54 | + | ||
55 | +end |
plugins/community_track/test/unit/community_track_plugin/track_list_block_test.rb
0 → 100644
@@ -0,0 +1,105 @@ | @@ -0,0 +1,105 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../test_helper' | ||
2 | + | ||
3 | +class TrackListBlockTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @community = fast_create(Community) | ||
7 | + @track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track', :profile => @community) | ||
8 | + | ||
9 | + box = fast_create(Box, :owner_id => @community.id, :owner_type => @community.class.name) | ||
10 | + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => box) | ||
11 | + end | ||
12 | + | ||
13 | + should 'describe yourself' do | ||
14 | + assert CommunityTrackPlugin::TrackListBlock.description | ||
15 | + end | ||
16 | + | ||
17 | + should 'return track as track partial' do | ||
18 | + assert_equal 'track', @block.track_partial | ||
19 | + end | ||
20 | + | ||
21 | + should 'load more at another page default to false' do | ||
22 | + assert !@block.more_another_page | ||
23 | + end | ||
24 | + | ||
25 | + should 'list articles only of track type' do | ||
26 | + article = fast_create(Article, :profile_id => @community.id) | ||
27 | + assert_includes @community.articles, article | ||
28 | + assert_equal [@track], @block.tracks | ||
29 | + end | ||
30 | + | ||
31 | + should 'list of articles be limited by block configuration' do | ||
32 | + (@block.limit + 1).times do |i| | ||
33 | + track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @community) | ||
34 | + end | ||
35 | + assert_equal @block.limit, @block.tracks.count | ||
36 | + end | ||
37 | + | ||
38 | + should 'return more link if has more tracks to show' do | ||
39 | + @block.limit.times do |i| | ||
40 | + track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @community) | ||
41 | + end | ||
42 | + assert @block.footer | ||
43 | + end | ||
44 | + | ||
45 | + should 'do not return more link if there is no more tracks to show' do | ||
46 | + (@block.limit-1).times do |i| | ||
47 | + track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @community) | ||
48 | + end | ||
49 | + assert !@block.footer | ||
50 | + end | ||
51 | + | ||
52 | + should 'count all tracks' do | ||
53 | + @block.owner.articles.destroy_all | ||
54 | + tracks_to_insert = @block.limit + 1 | ||
55 | + tracks_to_insert.times do |i| | ||
56 | + track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @community) | ||
57 | + end | ||
58 | + article = fast_create(Article, :profile_id => @block.owner.id) | ||
59 | + @block.reload | ||
60 | + assert_includes @block.owner.articles, article | ||
61 | + assert_equal tracks_to_insert, @block.count_tracks | ||
62 | + end | ||
63 | + | ||
64 | + should 'have a second page if there is more tracks than limit' do | ||
65 | + @block.owner.articles.destroy_all | ||
66 | + (@block.limit+1).times do |i| | ||
67 | + track = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => "track#{i}", :profile => @community) | ||
68 | + end | ||
69 | + assert @block.has_page?(2) | ||
70 | + assert !@block.has_page?(3) | ||
71 | + end | ||
72 | + | ||
73 | + should 'filter tracks by category' do | ||
74 | + @block.owner.articles.destroy_all | ||
75 | + category = fast_create(Category) | ||
76 | + category2 = fast_create(Category) | ||
77 | + track1 = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track1', :profile => @community) | ||
78 | + track2 = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track2', :profile => @community) | ||
79 | + track3 = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track3', :profile => @community) | ||
80 | + track1.add_category(category) | ||
81 | + @block.category_ids = [category.id] | ||
82 | + assert_equal [track1], @block.all_tracks | ||
83 | + end | ||
84 | + | ||
85 | + should 'return all tracks if block does not filter by category' do | ||
86 | + @block.owner.articles.destroy_all | ||
87 | + category = fast_create(Category) | ||
88 | + track1 = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track1', :profile => @community) | ||
89 | + track2 = CommunityTrackPlugin::Track.create!(:abstract => 'abstract', :body => 'body', :name => 'track2', :profile => @community) | ||
90 | + track1.add_category(category) | ||
91 | + assert_includes @block.all_tracks, track1 | ||
92 | + assert_includes @block.all_tracks, track2 | ||
93 | + end | ||
94 | + | ||
95 | + should 'accept any categories' do | ||
96 | + assert @block.accept_category?(nil) | ||
97 | + assert @block.accept_category?(fast_create(Category)) | ||
98 | + end | ||
99 | + | ||
100 | + should 'format category ids array avoiding duplicates and zeros' do | ||
101 | + @block.category_ids = ["0", "0", "1", "1", "2", nil] | ||
102 | + assert_equal [1, 2], @block.category_ids | ||
103 | + end | ||
104 | + | ||
105 | +end |
plugins/community_track/test/unit/community_track_plugin/track_test.rb
0 → 100644
@@ -0,0 +1,127 @@ | @@ -0,0 +1,127 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../test_helper' | ||
2 | + | ||
3 | +class TrackTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + profile = fast_create(Community) | ||
7 | + @track = CommunityTrackPlugin::Track.create!(:profile => profile, :name => 'track') | ||
8 | + @step = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => 'step', :profile => profile) | ||
9 | + @tool = fast_create(Article, :parent_id => @step.id, :profile_id => profile.id) | ||
10 | + end | ||
11 | + | ||
12 | + should 'describe yourself' do | ||
13 | + assert CommunityTrackPlugin::Track.description | ||
14 | + end | ||
15 | + | ||
16 | + should 'has a short descriptionf' do | ||
17 | + assert CommunityTrackPlugin::Track.short_description | ||
18 | + end | ||
19 | + | ||
20 | + should 'has a css class name' do | ||
21 | + assert_equal 'community-track-plugin-track', @track.css_class_name | ||
22 | + end | ||
23 | + | ||
24 | + should 'return comments count of children tools' do | ||
25 | + assert_equal 0, @track.comments_count | ||
26 | + owner = create_user('testuser').person | ||
27 | + article = create(Article, :name => 'article', :parent_id => @step.id, :profile_id => owner.id) | ||
28 | + comment = create(Comment, :source => article, :author_id => owner.id) | ||
29 | + assert_equal 1, @track.comments_count | ||
30 | + end | ||
31 | + | ||
32 | + should 'return children steps' do | ||
33 | + assert_equal [@step], @track.steps_unsorted | ||
34 | + end | ||
35 | + | ||
36 | + should 'do not return other articles type at steps' do | ||
37 | + article = fast_create(Article, :parent_id => @track.id, :profile_id => @track.profile.id) | ||
38 | + assert_includes @track.children, article | ||
39 | + assert_equal [@step], @track.steps_unsorted | ||
40 | + end | ||
41 | + | ||
42 | + should 'return category name' do | ||
43 | + category = fast_create(Category, :name => 'category') | ||
44 | + @track.add_category(category, true) | ||
45 | + assert_equal 'category', @track.category_name | ||
46 | + end | ||
47 | + | ||
48 | + should 'return empty for category name if it has no category' do | ||
49 | + @track.categories.delete_all | ||
50 | + assert_equal '', @track.category_name | ||
51 | + end | ||
52 | + | ||
53 | + should 'return category name of first category' do | ||
54 | + category = fast_create(Category, :name => 'category') | ||
55 | + @track.add_category(category, true) | ||
56 | + category2 = fast_create(Category, :name => 'category2') | ||
57 | + @track.add_category(category2, true) | ||
58 | + assert_equal 'category', @track.category_name | ||
59 | + end | ||
60 | + | ||
61 | + should 'return steps with insert order' do | ||
62 | + @track.children.destroy_all | ||
63 | + step1 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step1", :profile => @track.profile) | ||
64 | + step2 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step2", :profile => @track.profile) | ||
65 | + step3 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step3", :profile => @track.profile) | ||
66 | + assert_equal 1, step1.position | ||
67 | + assert_equal 2, step2.position | ||
68 | + assert_equal 3, step3.position | ||
69 | + assert_equal [step1, step2, step3], @track.steps | ||
70 | + end | ||
71 | + | ||
72 | + should 'return steps with order defined by position attribute' do | ||
73 | + @track.children.destroy_all | ||
74 | + step1 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step1", :profile => @track.profile) | ||
75 | + step2 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step2", :profile => @track.profile) | ||
76 | + step3 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step3", :profile => @track.profile) | ||
77 | + step1.position = 3 | ||
78 | + step1.save! | ||
79 | + step2.position = 1 | ||
80 | + step2.save! | ||
81 | + step3.position = 2 | ||
82 | + step3.save! | ||
83 | + assert_equal [step2, step3, step1], @track.steps | ||
84 | + end | ||
85 | + | ||
86 | + should 'save steps in a new order' do | ||
87 | + @track.children.destroy_all | ||
88 | + | ||
89 | + step1 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step1", :profile => @track.profile) | ||
90 | + step2 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step2", :profile => @track.profile) | ||
91 | + step3 = CommunityTrackPlugin::Step.create!(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => "step3", :profile => @track.profile) | ||
92 | + | ||
93 | + assert_equal [step1.id, step2.id, step3.id], @track.steps.map(&:id) | ||
94 | + @track.reorder_steps([step3.id, step1.id, step2.id]) | ||
95 | + @track.reload | ||
96 | + assert_equal [step3.id, step1.id, step2.id], @track.steps.map(&:id) | ||
97 | + end | ||
98 | + | ||
99 | + should 'do not return hidden steps' do | ||
100 | + hidden_step = CommunityTrackPlugin::Step.new(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => 'hidden step', :profile => @track.profile) | ||
101 | + hidden_step.hidden = true | ||
102 | + hidden_step.save! | ||
103 | + assert_equal [@step], @track.steps | ||
104 | + end | ||
105 | + | ||
106 | + should 'return hidden steps' do | ||
107 | + hidden_step = CommunityTrackPlugin::Step.new(:parent => @track, :start_date => Date.today, :end_date => Date.today, :name => 'hidden step', :profile => @track.profile) | ||
108 | + hidden_step.hidden = true | ||
109 | + hidden_step.save! | ||
110 | + assert_equal [hidden_step], @track.hidden_steps | ||
111 | + end | ||
112 | + | ||
113 | + should 'get first paragraph' do | ||
114 | + @track.body = '<p>First</p><p>Second</p>' | ||
115 | + assert_equal '<p>First</p>', @track.first_paragraph | ||
116 | + end | ||
117 | + | ||
118 | + should 'provide first_paragraph even if body was not given' do | ||
119 | + assert_equal '', @track.first_paragraph | ||
120 | + end | ||
121 | + | ||
122 | + should 'provide first_paragraph even if body is nil' do | ||
123 | + @track.body = nil | ||
124 | + assert_equal '', @track.first_paragraph | ||
125 | + end | ||
126 | + | ||
127 | +end |
plugins/community_track/test/unit/community_track_plugin_test.rb
0 → 100644
@@ -0,0 +1,78 @@ | @@ -0,0 +1,78 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class CommunityTrackPluginTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @plugin = CommunityTrackPlugin.new | ||
7 | + @profile = fast_create(Community) | ||
8 | + @params = {} | ||
9 | + @plugin.stubs(:context).returns(self) | ||
10 | + end | ||
11 | + | ||
12 | + attr_reader :profile, :params | ||
13 | + | ||
14 | + should 'has name' do | ||
15 | + assert CommunityTrackPlugin.plugin_name | ||
16 | + end | ||
17 | + | ||
18 | + should 'describe yourself' do | ||
19 | + assert CommunityTrackPlugin.plugin_description | ||
20 | + end | ||
21 | + | ||
22 | + should 'has stylesheet' do | ||
23 | + assert @plugin.stylesheet? | ||
24 | + end | ||
25 | + | ||
26 | + should 'return Track as a content type if profile is a community' do | ||
27 | + assert_includes @plugin.content_types, CommunityTrackPlugin::Track | ||
28 | + end | ||
29 | + | ||
30 | + should 'do not return Track as a content type if profile is not a community' do | ||
31 | + @profile = Organization.new | ||
32 | + assert_not_includes @plugin.content_types, CommunityTrackPlugin::Track | ||
33 | + end | ||
34 | + | ||
35 | + should 'do not return Track as a content type if there is a parent' do | ||
36 | + parent = fast_create(Blog, :profile_id => @profile.id) | ||
37 | + @params[:parent_id] = parent.id | ||
38 | + assert_not_includes @plugin.content_types, CommunityTrackPlugin::Track | ||
39 | + end | ||
40 | + | ||
41 | + should 'return Step as a content type if parent is a Track' do | ||
42 | + parent = fast_create(CommunityTrackPlugin::Track, :profile_id => @profile.id) | ||
43 | + @params[:parent_id] = parent.id | ||
44 | + assert_includes @plugin.content_types, CommunityTrackPlugin::Step | ||
45 | + end | ||
46 | + | ||
47 | + should 'do not return Step as a content type if parent is not a Track' do | ||
48 | + parent = fast_create(Blog, :profile_id => @profile.id) | ||
49 | + @params[:parent_id] = parent.id | ||
50 | + assert_not_includes @plugin.content_types, CommunityTrackPlugin::Step | ||
51 | + end | ||
52 | + | ||
53 | + should 'return Track and Step as a content type if context has no params' do | ||
54 | + parent = fast_create(Blog, :profile_id => @profile.id) | ||
55 | + expects(:respond_to?).with(:params).returns(false) | ||
56 | + assert_equivalent [CommunityTrackPlugin::Step, CommunityTrackPlugin::Track], @plugin.content_types | ||
57 | + end | ||
58 | + | ||
59 | + should 'return Track and Step as a content type if params is nil' do | ||
60 | + parent = fast_create(Blog, :profile_id => @profile.id) | ||
61 | + @params = nil | ||
62 | + assert_equivalent [CommunityTrackPlugin::Step, CommunityTrackPlugin::Track], @plugin.content_types | ||
63 | + end | ||
64 | + | ||
65 | + should 'return track card as an extra block' do | ||
66 | + assert_includes CommunityTrackPlugin.extra_blocks, CommunityTrackPlugin::TrackListBlock | ||
67 | + end | ||
68 | + | ||
69 | + should 'return true at content_remove_new if page is a track' do | ||
70 | + assert @plugin.content_remove_new(CommunityTrackPlugin::Track.new) | ||
71 | + end | ||
72 | + | ||
73 | + should 'return false at content_remove_new if page is not a track' do | ||
74 | + assert !@plugin.content_remove_new(CommunityTrackPlugin::Step.new) | ||
75 | + assert !@plugin.content_remove_new(Article.new) | ||
76 | + end | ||
77 | + | ||
78 | +end |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +<% extend CommunityTrackPlugin::TrackHelper %> | ||
2 | +<div class="item <%= category_class(track) %>"> | ||
3 | + <div class="track_content"> | ||
4 | + <div class="lead"> | ||
5 | + <h3><%= link_to track.name, track.url %></h3> | ||
6 | + <div class="content"> | ||
7 | + <%= track.lead %> | ||
8 | + </div> | ||
9 | + </div> | ||
10 | + <div class="steps"> | ||
11 | + <h3><%= _("Steps") %></h3> | ||
12 | + <% track.steps.each do |step| %> | ||
13 | + <div class="step <%= block.status_class(step) %>"> | ||
14 | + <div class="position"><%= step.position %></div> | ||
15 | + <%= link_to step.name, step.url %> | ||
16 | + </div> | ||
17 | + <% end %> | ||
18 | + </div> | ||
19 | + </div> | ||
20 | +</div> | ||
21 | +<br style="clear: both;"/> |
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +<% extend CommunityTrackPlugin::TrackHelper %> | ||
2 | +<div class="item_card <%= category_class(track_card) %>"> | ||
3 | + <a href="<%= url_for track_card.url %>"> | ||
4 | + <div class="track_content"> | ||
5 | + <div class="title"> | ||
6 | + <%= track_card.category_name %> | ||
7 | + </div> | ||
8 | + <div class="image"> | ||
9 | + <%= image_tag track_card.image.public_filename if track_card.image %> | ||
10 | + </div> | ||
11 | + <div class="name"> | ||
12 | + <%= track_card.name %> | ||
13 | + </div> | ||
14 | + <div class="lead"> | ||
15 | + <%= track_card_lead(track_card) %> | ||
16 | + </div> | ||
17 | + </div> | ||
18 | + <div class="track_stats"> | ||
19 | + <div class="comments"> | ||
20 | + <%= "#{track_card.comments_count} comments" %> | ||
21 | + </div> | ||
22 | + <div class="hits"> | ||
23 | + <%= "#{track_card.hits} hits" %> | ||
24 | + </div> | ||
25 | + </div> | ||
26 | + </a> | ||
27 | +</div> |
plugins/community_track/views/blocks/_track_list_more.rhtml
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<% force_same_page ||= false %> | ||
2 | +<div id="track_list_more_<%= block.id %>" class="more_button"> | ||
3 | + <% if block.more_another_page && !force_same_page %> | ||
4 | + <div class="view_all"> | ||
5 | + <%= link_to _('View All'), :id => block.id, :controller => 'community_track_plugin_public', :action => 'all_tracks' %> | ||
6 | + </div> | ||
7 | + <% else %> | ||
8 | + <div class="more"> | ||
9 | + <%= link_to_remote(_('More'), :url => {:id => block.id, :controller => 'community_track_plugin_public', :action => 'view_tracks', :page => page, :per_page => per_page, :force_same_page => force_same_page}, :loaded => visual_effect(:highlight, "track_card_list_#{block.id}")) %> | ||
10 | + </div> | ||
11 | + <% end %> | ||
12 | +</div> |
plugins/community_track/views/box_organizer/community_track_plugin/_track_list_block.rhtml
0 → 100644
@@ -0,0 +1,6 @@ | @@ -0,0 +1,6 @@ | ||
1 | +<div id='edit-track-list-block'> | ||
2 | + <%= labelled_form_field _('Limit of items'), text_field(:block, :limit, :size => 3) %> | ||
3 | + <%= labelled_form_field check_box(:block, :more_another_page) + _('Show more at another page'), '' %> | ||
4 | + <%= select_categories(:block, _('Select Categories')) %> | ||
5 | +<br/> | ||
6 | +</div> |
plugins/community_track/views/cms/community_track_plugin/_step.rhtml
0 → 100644
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +<%= required_fields_message %> | ||
2 | + | ||
3 | +<%= render :file => 'shared/tiny_mce' %> | ||
4 | + | ||
5 | +<div> | ||
6 | + <%= required f.text_field('name', :size => '64', :maxlength => 150) %> | ||
7 | + <%= labelled_form_field(_('Period'), ( | ||
8 | + date_range_field('article[start_date]', 'article[end_date]', @article.start_date, @article.end_date, | ||
9 | + '%Y-%m-%d', | ||
10 | + { :change_month => true, :change_year => true, | ||
11 | + :date_format => 'yy-mm-dd' }, | ||
12 | + { :size => 14 }) | ||
13 | + )) %> | ||
14 | + | ||
15 | +</div> | ||
16 | + | ||
17 | +<%= labelled_form_field check_box(:article, :hidden) + _('Hidden Step'), '' %> | ||
18 | + | ||
19 | +<%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :body_label => 'Description:'} %> |
plugins/community_track/views/cms/community_track_plugin/_track.rhtml
0 → 100644
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +<div class='community-track'> | ||
2 | + <%= required_fields_message %> | ||
3 | + | ||
4 | + <%= render :file => 'shared/tiny_mce' %> | ||
5 | + | ||
6 | + <div> | ||
7 | + <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64', :maxlength => 150)) %> | ||
8 | + </div> | ||
9 | + | ||
10 | + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :body_label => 'Description:'} %> | ||
11 | + | ||
12 | + <div> | ||
13 | + <% f.fields_for :image_builder, @article.image do |i| %> | ||
14 | + <%= file_field_or_thumbnail(_('Image:'), @article.image, i) %> | ||
15 | + <% end %> | ||
16 | + | ||
17 | + <%= labelled_form_field(_('Goals:'), text_area(:article, :goals, :rows => 3, :cols => 64)) %> | ||
18 | + <%= labelled_form_field(_('Expected Results:'), text_area(:article, :expected_results, :rows => 3, :cols => 64)) %> | ||
19 | + </div> | ||
20 | +</div> |
plugins/community_track/views/community_track_plugin_public/all_tracks.rhtml
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<h1><%= _('Tracks') %></h1> | ||
2 | +<div class="all_tracks"> | ||
3 | + <div class="track_list track_card_list" id="track_list_<%= @block.id %>"> | ||
4 | + <%= render :partial => "blocks/#{@block.track_partial}", :collection => @tracks, :locals => {:block => @block} %> | ||
5 | + </div> | ||
6 | + <br style="clear: both;"/> | ||
7 | + <% if @show_more %> | ||
8 | + <%= render :partial => "blocks/track_list_more", :locals => {:block => @block, :force_same_page => true, :page => 2, :per_page => @per_page} %> | ||
9 | + <% end %> | ||
10 | +</div> |
plugins/community_track/views/community_track_plugin_public/select_community.rhtml
0 → 100644
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +<div> | ||
2 | + | ||
3 | +<h1><%= _('Select Community') %></h1> | ||
4 | + | ||
5 | +<% if !@failed.blank? %> | ||
6 | + <div class="errorExplanation" id="errorExplanation"> | ||
7 | + <div style="color: #c00;"> | ||
8 | + <% @failed.each do |error|%> | ||
9 | + <strong> <%= error %></strong> | ||
10 | + <% end %> | ||
11 | + </div> | ||
12 | + </div> | ||
13 | +<% end %> | ||
14 | + | ||
15 | +<% button_bar do %> | ||
16 | + <%= button(:add, __('Create a new community'), :controller => 'memberships', :action => 'new_community', :profile => user.identifier, :back_to => @back_to) %> | ||
17 | +<% end %> | ||
18 | + | ||
19 | +<% form_tag({:controller => 'community_track_plugin_public', :action => 'select_community', :profile => user.identifier}) do %> | ||
20 | +<div class="common-profile-list-block"> | ||
21 | + <ul> | ||
22 | + <% @communities.each do |community| %> | ||
23 | + <li class="search-profile-item"> | ||
24 | + <div class="common-profile-list-block"> | ||
25 | + <div class="vcard"> | ||
26 | + <a href="#" onclick="jQuery('<%= "#community_identifier_#{community.identifier}" %>').attr('checked', true);"> | ||
27 | + <span class="profile-image"><%= profile_image(community) %></span> | ||
28 | + <span class="org"><%= community.name %></span> | ||
29 | + <span class="select_community"><%= radio_button_tag(:community_identifier, community.identifier) %></span> | ||
30 | + </a> | ||
31 | + </div> | ||
32 | + </div> | ||
33 | + </li> | ||
34 | + <% end %> | ||
35 | + </ul> | ||
36 | + </div> | ||
37 | + <div class="clear"></div> | ||
38 | + <br/> | ||
39 | + <%= submit_button :save, _('New Track') %> | ||
40 | +<% end %> | ||
41 | +</div> |
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +<div id="step"> | ||
2 | + <div class="event-info"> | ||
3 | + <ul class="event-data"> | ||
4 | + <li class="event-dates"> | ||
5 | + <span><%= _('When:') %></span><%= show_period(step.start_date, step.end_date) %> | ||
6 | + </li> | ||
7 | + </ul> | ||
8 | + </div> | ||
9 | + <div> | ||
10 | + <%= step.body %> | ||
11 | + </div> | ||
12 | + <h3><%= _("Tools") %></h3> | ||
13 | + <% if step.allow_create?(user) %> | ||
14 | + <div class="actions"> | ||
15 | + <% step.enabled_tools.each do |klass, attrs| %> | ||
16 | + <% content_tag('a', :href => url_for({:controller => 'cms', :action => 'new', :type => klass.name, :parent_id => @page}), :class => "button with-text icon-new icon-new#{klass.icon_name}") do %> | ||
17 | + <%= _("New #{attrs[:name]}") %> | ||
18 | + <% end %> | ||
19 | + <% end %> | ||
20 | + </div> | ||
21 | + <% end %> | ||
22 | + <div class="tools"> | ||
23 | + <% step.tools.each do |tool| %> | ||
24 | + <div class="item"> | ||
25 | + <div class="name"> | ||
26 | + <%= link_to tool.name, tool.url, :class=>"button with-text icon-new icon-new#{tool.class.icon_name}" %> | ||
27 | + </div> | ||
28 | + </div> | ||
29 | + <% end %> | ||
30 | + </div> | ||
31 | +</div> |
plugins/community_track/views/content_viewer/track.rhtml
0 → 100644
@@ -0,0 +1,67 @@ | @@ -0,0 +1,67 @@ | ||
1 | +<% extend CommunityTrackPlugin::StepHelper %> | ||
2 | + | ||
3 | +<% form_tag({:controller => 'community_track_plugin_myprofile', :action => 'save_order', :track => track}) do %> | ||
4 | +<div id="track"> | ||
5 | + <div> | ||
6 | + <%= track.body %> | ||
7 | + </div> | ||
8 | + | ||
9 | + <h3><%= _("Steps") %></h3> | ||
10 | + | ||
11 | + <% if track.allow_create?(user) %> | ||
12 | + <div class="actions"> | ||
13 | + <% content_tag('a', :href => url_for({:controller => 'cms', :action => 'new', :type => "CommunityTrackPlugin::Step", :parent_id => track.id}), :class => 'button with-text icon-add') do %> | ||
14 | + <strong><%= _("New %s") % CommunityTrackPlugin::Step.short_description %></strong> | ||
15 | + <% end %> | ||
16 | + <a href="#" class="reorder_button button with-text icon-up" onclick="enableReorder();"><%= _('Reorder Steps') %></a> | ||
17 | + <%= submit_button :save, _('Save Order'), :class => "save_button" %> | ||
18 | + </div> | ||
19 | + <script> | ||
20 | + function enableReorder() { | ||
21 | + jQuery(".reorder_button").hide(); | ||
22 | + jQuery(".save_button").show(); | ||
23 | + jQuery("#sortable li").addClass("ui-state-default"); | ||
24 | + jQuery("#sortable").sortable(); | ||
25 | + jQuery("#sortable").disableSelection(); | ||
26 | + } | ||
27 | + </script> | ||
28 | + <% end %> | ||
29 | + | ||
30 | + <ul id="sortable" class="step_list"> | ||
31 | + <% track.steps.each do |step| %> | ||
32 | + <li class="step"> | ||
33 | + <%= hidden_field_tag "step_ids[]", step.id %> | ||
34 | + <div class="position"><%= step.position %></div> | ||
35 | + <div class="content"> | ||
36 | + <div class="date"> | ||
37 | + <%= show_period(step.start_date, step.end_date) %> | ||
38 | + </div> | ||
39 | + <div class="name"><%= link_to step.name, step.url %></div> | ||
40 | + <div class="lead"><%= step.body %></div> | ||
41 | + </div> | ||
42 | + </li> | ||
43 | + <% end %> | ||
44 | + </ul> | ||
45 | + <% if track.allow_create?(user) && !track.hidden_steps.empty? %> | ||
46 | + <div id="hidden_steps"> | ||
47 | + <h3><%= _('Hidden Steps') %></h3> | ||
48 | + <ul class="step_list"> | ||
49 | + <% track.hidden_steps.each do |step| %> | ||
50 | + <li class="step"> | ||
51 | + <%= hidden_field_tag "step_ids[]", step.id %> | ||
52 | + <div class="position"></div> | ||
53 | + <div class="content"> | ||
54 | + <div class="date"> | ||
55 | + <%= show_period(step.start_date, step.end_date) %> | ||
56 | + </div> | ||
57 | + <div class="name"><%= link_to step.name, step.url %></div> | ||
58 | + <div class="lead"><%= step.body %></div> | ||
59 | + </div> | ||
60 | + </li> | ||
61 | + <% end %> | ||
62 | + </ul> | ||
63 | + </div> | ||
64 | + <% end %> | ||
65 | +</div> | ||
66 | +<% end %> | ||
67 | +</div> |
plugins/community_track/views/environment_design/community_track_plugin
0 → 120000
plugins/community_track/views/profile_design/community_track_plugin
0 → 120000
plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb
@@ -140,5 +140,14 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | @@ -140,5 +140,14 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | ||
140 | assert_equal 'Cool form', form.description | 140 | assert_equal 'Cool form', form.description |
141 | assert_equal 'Source', field.name | 141 | assert_equal 'Source', field.name |
142 | end | 142 | end |
143 | + | ||
144 | + should 'render TinyMce Editor for description' do | ||
145 | + form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') | ||
146 | + | ||
147 | + get :edit, :profile => profile.identifier, :id => form.id | ||
148 | + | ||
149 | + assert_tag :tag => 'textarea', :attributes => { :id => 'form_description', :class => 'mceEditor' } | ||
150 | + end | ||
151 | + | ||
143 | end | 152 | end |
144 | 153 |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb
1 | <% self.extend(CustomFormsPlugin::Helper) %> | 1 | <% self.extend(CustomFormsPlugin::Helper) %> |
2 | +<%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %> | ||
2 | 3 | ||
3 | <%= error_messages_for :form %> | 4 | <%= error_messages_for :form %> |
4 | 5 | ||
@@ -15,7 +16,7 @@ | @@ -15,7 +16,7 @@ | ||
15 | <% if profile.organization? %> | 16 | <% if profile.organization? %> |
16 | <%= labelled_form_field _('Triggered on membership'), f.check_box(:on_membership) %> | 17 | <%= labelled_form_field _('Triggered on membership'), f.check_box(:on_membership) %> |
17 | <% end %> | 18 | <% end %> |
18 | - <%= labelled_form_field _('Description'), f.text_area(:description, :style => 'width: 100%') %> | 19 | + <%= labelled_form_field _('Description'), f.text_area(:description, :style => 'width: 100%', :class => 'mceEditor') %> |
19 | 20 | ||
20 | <h2><%= _('Fields') %></h2> | 21 | <h2><%= _('Fields') %></h2> |
21 | <table class="action-table" id='fields-table'> | 22 | <table class="action-table" id='fields-table'> |
plugins/display_content/lib/display_content_block.rb
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +class FilePresenter::Video < FilePresenter | ||
2 | + def self.accepts?(f) | ||
3 | + return nil if !f.respond_to?(:content_type) || f.content_type.nil? | ||
4 | + ( f.content_type[0..4] == 'video' ) ? 10 : nil | ||
5 | + end | ||
6 | + | ||
7 | + def short_description | ||
8 | + _('Video (%s)') % content_type.split('/')[1].upcase | ||
9 | + end | ||
10 | +end |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class Html5VideoPlugin < Noosfero::Plugin | ||
2 | + | ||
3 | + FilePresenter::Video | ||
4 | + | ||
5 | + def self.plugin_name | ||
6 | + "HTML5 Video" | ||
7 | + end | ||
8 | + | ||
9 | + def self.plugin_description | ||
10 | + _("A plugin to enable the video suport, with auto conversion for the web.") | ||
11 | + end | ||
12 | + | ||
13 | +end |
plugins/html5_video/test/functional/content_viewer_controler_test.rb
0 → 100644
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | +require 'content_viewer_controller' | ||
3 | + | ||
4 | +class ContentViewerController | ||
5 | + # Re-raise errors caught by the controller. | ||
6 | + def rescue_action(e) raise e end | ||
7 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') | ||
8 | +end | ||
9 | + | ||
10 | +class ContentViewerControllerTest < ActionController::TestCase | ||
11 | + | ||
12 | + all_fixtures | ||
13 | + | ||
14 | + def setup | ||
15 | + @controller = ContentViewerController.new | ||
16 | + @request = ActionController::TestRequest.new | ||
17 | + @response = ActionController::TestResponse.new | ||
18 | + | ||
19 | + @profile = create_user('testinguser').person | ||
20 | + @environment = @profile.environment | ||
21 | + end | ||
22 | + attr_reader :profile, :environment | ||
23 | + | ||
24 | + should 'add html5 video tag to the page of file type video' do | ||
25 | + file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'video/ogg'), :profile => profile) | ||
26 | + get :view_page, file.url.merge(:view=>:true) | ||
27 | + assert_select '#article video' | ||
28 | + end | ||
29 | + | ||
30 | +end |
plugins/html5_video/views/file_presenter/_video.html.erb
0 → 100644
@@ -0,0 +1,8 @@ | @@ -0,0 +1,8 @@ | ||
1 | +<video class="video-js vjs-default-skin" controls poster="video.jpg" preload="auto" data-setup="{}"> | ||
2 | + <source type="video/ogg" src="<%= video.public_filename %>"/> | ||
3 | +</video> | ||
4 | + | ||
5 | +<div class="uploaded-file-description <%= 'empty' if video.abstract.blank? %>"> | ||
6 | + <%= video.abstract %> | ||
7 | +</div> | ||
8 | + |
@@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
1 | +README - Video (Video Plugin) | ||
2 | +================================ | ||
3 | + | ||
4 | +Video is a plugin that allow users to add a block where you can choose | ||
5 | +any url from youtube, vimeo and url's of the following file formats: | ||
6 | +mp4, ogg, ogv and webm. | ||
7 | + | ||
8 | +The Video block will be available for all layout columns of communities, | ||
9 | +people, enterprises and environments. | ||
10 | + | ||
11 | +INSTALL | ||
12 | +======= | ||
13 | + | ||
14 | +Enable Plugin | ||
15 | +------------- | ||
16 | + | ||
17 | +Also, you need to enable Video Plugin on your Noosfero: | ||
18 | + | ||
19 | +cd <your_noosfero_dir> | ||
20 | +./script/noosfero-plugins enable video | ||
21 | + | ||
22 | +Active Plugin | ||
23 | +------------- | ||
24 | + | ||
25 | +As a Noosfero administrator user, go to administrator panel: | ||
26 | + | ||
27 | +- Click on "Enable/disable plugins" option | ||
28 | +- Click on "Display Content Plugin" check-box | ||
29 | + | ||
30 | +Running Video tests | ||
31 | +-------------------- | ||
32 | + | ||
33 | +$ rake test:noosfero_plugins:video | ||
34 | + | ||
35 | + | ||
36 | +Get Involved | ||
37 | +============ | ||
38 | + | ||
39 | +If you find any bug and/or want to collaborate, please send an e-mail to leandronunes@gmail.com | ||
40 | + | ||
41 | +LICENSE | ||
42 | +======= | ||
43 | + | ||
44 | +Copyright (c) The Author developers. | ||
45 | + | ||
46 | +See Noosfero license. | ||
47 | + | ||
48 | + | ||
49 | +AUTHORS | ||
50 | +======= | ||
51 | + | ||
52 | + Leandro Nunes dos Santos (leandronunes at gmail.com) | ||
53 | + | ||
54 | +ACKNOWLEDGMENTS | ||
55 | +=============== | ||
56 | + | ||
57 | +The author have been supported by Serpro |
@@ -0,0 +1,58 @@ | @@ -0,0 +1,58 @@ | ||
1 | +class VideoBlock < Block | ||
2 | + | ||
3 | + settings_items :url, :type => :string, :default => "" | ||
4 | + settings_items :width, :type => :integer, :default => 400 | ||
5 | + settings_items :height, :type => :integer, :default => 315 | ||
6 | + | ||
7 | + def is_youtube? | ||
8 | + url.match(/.*(youtube.com.*v=[[:alnum:]]+|youtu.be\/[[:alnum:]]+).*/) ? true : false | ||
9 | + end | ||
10 | + | ||
11 | + def is_vimeo? | ||
12 | + url.match(/^(http[s]?:\/\/)?(www.)?(vimeo.com|player.vimeo.com\/video)\/[[:digit:]]+/) ? true : false | ||
13 | + end | ||
14 | + | ||
15 | + def is_video_file? | ||
16 | + url.match(/.*(mp4|ogg|ogv|webm)$/) ? true : false | ||
17 | + end | ||
18 | + | ||
19 | + def format_embed_video_url_for_youtube | ||
20 | + "//www.youtube-nocookie.com/embed/#{extract_youtube_id}?rel=0&wmode=transparent" if is_youtube? | ||
21 | + end | ||
22 | + | ||
23 | + def format_embed_video_url_for_vimeo | ||
24 | + "//player.vimeo.com/video/#{extract_vimeo_id}" if is_vimeo? | ||
25 | + end | ||
26 | + | ||
27 | + def self.description | ||
28 | + _('Display a Video') | ||
29 | + end | ||
30 | + | ||
31 | + def help | ||
32 | + _('This block presents a video from youtube, vimeo and some video formats (mp4, ogg, ogv and webm)') | ||
33 | + end | ||
34 | + | ||
35 | + def content(args={}) | ||
36 | + block = self | ||
37 | + | ||
38 | + lambda do | ||
39 | + render :file => 'video_block', :locals => { :block => block } | ||
40 | + end | ||
41 | + end | ||
42 | + | ||
43 | + private | ||
44 | + | ||
45 | + def extract_youtube_id | ||
46 | + return nil unless is_youtube? | ||
47 | + youtube_match = url.match('v=([[:alnum:]]*)') | ||
48 | + youtube_match ||= url.match('youtu.be\/([[:alnum:]]*)') | ||
49 | + youtube_match[1] unless youtube_match.nil? | ||
50 | + end | ||
51 | + | ||
52 | + def extract_vimeo_id | ||
53 | + return nil unless is_vimeo? | ||
54 | + vimeo_match = url.match('([[:digit:]]*)$') | ||
55 | + vimeo_match[1] unless vimeo_match.nil? | ||
56 | + end | ||
57 | + | ||
58 | +end |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +require_dependency File.dirname(__FILE__) + '/video_block' | ||
2 | + | ||
3 | +class VideoPlugin < Noosfero::Plugin | ||
4 | + | ||
5 | + def self.plugin_name | ||
6 | + "Video Block Plugin" | ||
7 | + end | ||
8 | + | ||
9 | + def self.plugin_description | ||
10 | + _("A plugin that adds a block where you can add videos from youtube, vimeo and html5.") | ||
11 | + end | ||
12 | + | ||
13 | + def self.extra_blocks | ||
14 | + { | ||
15 | + VideoBlock => {} | ||
16 | + } | ||
17 | + end | ||
18 | + | ||
19 | +end |
plugins/video/test/functional/video_plugin_environment_design_controller_test.rb
0 → 100644
@@ -0,0 +1,130 @@ | @@ -0,0 +1,130 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +# Re-raise errors caught by the controller. | ||
4 | +class EnvironmentDesignController; def rescue_action(e) raise e end; end | ||
5 | + | ||
6 | +class EnvironmentDesignControllerTest < ActionController::TestCase | ||
7 | + | ||
8 | + def setup | ||
9 | + @controller = EnvironmentDesignController.new | ||
10 | + @request = ActionController::TestRequest.new | ||
11 | + @response = ActionController::TestResponse.new | ||
12 | + | ||
13 | + Environment.delete_all | ||
14 | + User.delete_all | ||
15 | + @environment = Environment.create!(defaults_for_environment.merge(:is_default => true)) | ||
16 | + user = create_user('testinguser') | ||
17 | + login_as(user.person.identifier) | ||
18 | + @environment.add_admin(user.person) | ||
19 | + @environment.save! | ||
20 | + | ||
21 | + @environment.enabled_plugins = ['VideoPlugin'] | ||
22 | + @environment.save! | ||
23 | + | ||
24 | + VideoBlock.delete_all | ||
25 | + | ||
26 | + @block = VideoBlock.new | ||
27 | + @block.box = @environment.boxes.first | ||
28 | + @block.save! | ||
29 | + end | ||
30 | + | ||
31 | + attr_accessor :environment, :block | ||
32 | + | ||
33 | + should 'display video-block-data class in profile block edition' do | ||
34 | + block.url='youtube.com/?v=XXXXX' | ||
35 | + block.save! | ||
36 | + get :index | ||
37 | + | ||
38 | + assert_tag :div, :attributes => {:class => 'video-block-data'} | ||
39 | + end | ||
40 | + | ||
41 | + should "display iframe tag in profile block edition on youtube url's" do | ||
42 | + block.url='youtube.com/?v=XXXXX' | ||
43 | + block.save | ||
44 | + get :index | ||
45 | + | ||
46 | + assert_tag :tag => 'iframe' | ||
47 | + end | ||
48 | + | ||
49 | + should "the width in iframe tag be defined on youtube url's" do | ||
50 | + block.url='youtube.com/?v=XXXXX' | ||
51 | + block.save | ||
52 | + get :index | ||
53 | + | ||
54 | + assert_tag :tag => 'iframe', :attributes => {:width => '400px'} | ||
55 | + end | ||
56 | + | ||
57 | + should "display iframe tag in profile block edition on vimeo url's" do | ||
58 | + block.url='http://vimeo.com/98979' | ||
59 | + block.save | ||
60 | + get :index | ||
61 | + | ||
62 | + assert_tag :tag => 'iframe' | ||
63 | + end | ||
64 | + | ||
65 | + should "the width in iframe tag be defined on vimeo url's" do | ||
66 | + block.url='http://vimeo.com/98979' | ||
67 | + block.save | ||
68 | + get :index | ||
69 | + | ||
70 | + assert_tag :tag => 'iframe', :attributes => {:width => '400px'} | ||
71 | + end | ||
72 | + | ||
73 | + should "display video tag in profile block edition for any video url" do | ||
74 | + block.url='http://www.vmsd.com/98979.mp4' | ||
75 | + block.save | ||
76 | + get :index | ||
77 | + | ||
78 | + assert_tag :tag => 'video' | ||
79 | + end | ||
80 | + | ||
81 | + should "the width in video tag be defined for any video url" do | ||
82 | + block.url='http://www.vmsd.com/98979.mp4' | ||
83 | + block.save | ||
84 | + get :index | ||
85 | + | ||
86 | + assert_tag :tag => 'video', :attributes => {:width => '400px'} | ||
87 | + end | ||
88 | + | ||
89 | + should 'the heigth in iframe tag be defined' do | ||
90 | + block.url='youtube.com/?v=XXXXX' | ||
91 | + block.save | ||
92 | + get :index | ||
93 | + | ||
94 | + assert_tag :tag => 'iframe', :attributes => {:height => '315px'} | ||
95 | + end | ||
96 | + | ||
97 | + should 'display youtube videos' do | ||
98 | + block.url='youtube.com/?v=XXXXX' | ||
99 | + block.save | ||
100 | + get :index | ||
101 | + | ||
102 | + assert_tag :tag => 'div', :attributes => {:class => 'video-block-data'}, :descendant => { :tag => 'div', :attributes => {:class => 'youtube'} } | ||
103 | + end | ||
104 | + | ||
105 | + should 'display vimeo videos' do | ||
106 | + block.url='http://vimeo.com/98979' | ||
107 | + block.save | ||
108 | + get :index | ||
109 | + | ||
110 | + assert_tag :tag => 'div', :attributes => {:class => 'video-block-data'}, :descendant => { :tag => 'div', :attributes => {:class => 'vimeo'} } | ||
111 | + end | ||
112 | + | ||
113 | + should 'display other videos' do | ||
114 | + block.url='http://www.vmsd.com/98979.mp4' | ||
115 | + block.save | ||
116 | + get :index | ||
117 | + | ||
118 | + assert_tag :tag => 'div', :attributes => {:class => 'video-block-data'}, :descendant => { :tag => 'div', :attributes => {:class => 'video'} } | ||
119 | + end | ||
120 | + | ||
121 | + should 'display a message to register a new url' do | ||
122 | + block.url='http://www.vmsd.com/test.pdf' | ||
123 | + block.save | ||
124 | + get :index | ||
125 | + | ||
126 | + assert_tag :tag => 'div', :attributes => {:class => 'video-block-data'}, :descendant => { :tag => 'span', :attributes => {:class => 'alert-block'} } | ||
127 | + end | ||
128 | + | ||
129 | + | ||
130 | +end |
plugins/video/test/functional/video_plugin_profile_design_controller_test.rb
0 → 100644
@@ -0,0 +1,132 @@ | @@ -0,0 +1,132 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +# Re-raise errors caught by the controller. | ||
4 | +class ProfileDesignController; def rescue_action(e) raise e end; end | ||
5 | + | ||
6 | +class ProfileDesignControllerTest < ActionController::TestCase | ||
7 | + | ||
8 | + def setup | ||
9 | + @controller = ProfileDesignController.new | ||
10 | + @request = ActionController::TestRequest.new | ||
11 | + @response = ActionController::TestResponse.new | ||
12 | + | ||
13 | + user = create_user('testinguser') | ||
14 | + login_as(user.login) | ||
15 | + @profile = user.person | ||
16 | + @environment = @profile.environment | ||
17 | + | ||
18 | + @environment.enabled_plugins = ['VideoPlugin'] | ||
19 | + @environment.save! | ||
20 | + | ||
21 | + VideoBlock.delete_all | ||
22 | + @box1 = Box.create!(:owner => @profile) | ||
23 | + @profile.boxes = [@box1] | ||
24 | + | ||
25 | + @block = VideoBlock.new | ||
26 | + @block.box = @box1 | ||
27 | + @block.save! | ||
28 | + | ||
29 | + @profile.blocks<<@block | ||
30 | + @profile.save! | ||
31 | + end | ||
32 | + | ||
33 | + attr_accessor :profile, :block | ||
34 | + | ||
35 | + should 'display video-block-data class in profile block edition' do | ||
36 | + block.url='youtube.com/?v=XXXXX' | ||
37 | + block.save | ||
38 | + get :index, :profile => profile.identifier | ||
39 | + | ||
40 | + assert_tag :div, :attributes => {:class => 'video-block-data'} | ||
41 | + end | ||
42 | + | ||
43 | + should "display iframe tag in profile block edition on youtube url's" do | ||
44 | + block.url='youtube.com/?v=XXXXX' | ||
45 | + block.save | ||
46 | + get :index, :profile => profile.identifier | ||
47 | + | ||
48 | + assert_tag :tag => 'iframe' | ||
49 | + end | ||
50 | + | ||
51 | + should "the width in iframe tag be defined on youtube url's" do | ||
52 | + block.url='youtube.com/?v=XXXXX' | ||
53 | + block.save | ||
54 | + get :index, :profile => profile.identifier | ||
55 | + | ||
56 | + assert_tag :tag => 'iframe', :attributes => {:width => '400px'} | ||
57 | + end | ||
58 | + | ||
59 | + should "display iframe tag in profile block edition on vimeo url's" do | ||
60 | + block.url='http://vimeo.com/98979' | ||
61 | + block.save | ||
62 | + get :index, :profile => profile.identifier | ||
63 | + | ||
64 | + assert_tag :tag => 'iframe' | ||
65 | + end | ||
66 | + | ||
67 | + should "the width in iframe tag be defined on vimeo url's" do | ||
68 | + block.url='http://vimeo.com/98979' | ||
69 | + block.save | ||
70 | + get :index, :profile => profile.identifier | ||
71 | + | ||
72 | + assert_tag :tag => 'iframe', :attributes => {:width => '400px'} | ||
73 | + end | ||
74 | + | ||
75 | + should "display video tag in profile block edition for any video url" do | ||
76 | + block.url='http://www.vmsd.com/98979.mp4' | ||
77 | + block.save | ||
78 | + get :index, :profile => profile.identifier | ||
79 | + | ||
80 | + assert_tag :tag => 'video' | ||
81 | + end | ||
82 | + | ||
83 | + should "the width in video tag be defined for any video url" do | ||
84 | + block.url='http://www.vmsd.com/98979.mp4' | ||
85 | + block.save | ||
86 | + get :index, :profile => profile.identifier | ||
87 | + | ||
88 | + assert_tag :tag => 'video', :attributes => {:width => '400px'} | ||
89 | + end | ||
90 | + | ||
91 | + should 'the heigth in iframe tag be defined' do | ||
92 | + block.url='youtube.com/?v=XXXXX' | ||
93 | + block.save | ||
94 | + get :index, :profile => profile.identifier | ||
95 | + | ||
96 | + assert_tag :tag => 'iframe', :attributes => {:height => '315px'} | ||
97 | + end | ||
98 | + | ||
99 | + should 'display youtube videos' do | ||
100 | + block.url='youtube.com/?v=XXXXX' | ||
101 | + block.save | ||
102 | + get :index, :profile => profile.identifier | ||
103 | + | ||
104 | + assert_tag :tag => 'div', :attributes => {:class => 'video-block-data'}, :descendant => { :tag => 'div', :attributes => {:class => 'youtube'} } | ||
105 | + end | ||
106 | + | ||
107 | + should 'display vimeo videos' do | ||
108 | + block.url='http://vimeo.com/98979' | ||
109 | + block.save | ||
110 | + get :index, :profile => profile.identifier | ||
111 | + | ||
112 | + assert_tag :tag => 'div', :attributes => {:class => 'video-block-data'}, :descendant => { :tag => 'div', :attributes => {:class => 'vimeo'} } | ||
113 | + end | ||
114 | + | ||
115 | + should 'display other videos' do | ||
116 | + block.url='http://www.vmsd.com/98979.mp4' | ||
117 | + block.save | ||
118 | + get :index, :profile => profile.identifier | ||
119 | + | ||
120 | + assert_tag :tag => 'div', :attributes => {:class => 'video-block-data'}, :descendant => { :tag => 'div', :attributes => {:class => 'video'} } | ||
121 | + end | ||
122 | + | ||
123 | + should 'display a messagem to register a new url' do | ||
124 | + block.url='http://www.vmsd.com/test.pdf' | ||
125 | + block.save | ||
126 | + get :index, :profile => profile.identifier | ||
127 | + | ||
128 | + assert_tag :tag => 'div', :attributes => {:class => 'video-block-data'}, :descendant => { :tag => 'span', :attributes => {:class => 'alert-block'} } | ||
129 | + end | ||
130 | + | ||
131 | + | ||
132 | +end |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' |
@@ -0,0 +1,218 @@ | @@ -0,0 +1,218 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | +class VideoBlockTest < ActiveSupport::TestCase | ||
3 | + | ||
4 | + ### Tests for YouTube | ||
5 | + | ||
6 | + should "is_youtube return true when the url contains http://youtube.com" do | ||
7 | + block = VideoBlock.new | ||
8 | + block.url = "http://youtube.com/?v=XXXXX" | ||
9 | + assert block.is_youtube? | ||
10 | + end | ||
11 | + | ||
12 | + should "is_youtube return true when the url contains https://youtube.com" do | ||
13 | + block = VideoBlock.new | ||
14 | + block.url = "https://youtube.com/?v=XXXXX" | ||
15 | + assert block.is_youtube? | ||
16 | + end | ||
17 | + | ||
18 | + should "is_youtube return true when the url contains https://www.youtube.com" do | ||
19 | + block = VideoBlock.new | ||
20 | + block.url = "https://www.youtube.com/?v=XXXXX" | ||
21 | + assert block.is_youtube? | ||
22 | + end | ||
23 | + | ||
24 | + should "is_youtube return true when the url contains www.youtube.com" do | ||
25 | + block = VideoBlock.new | ||
26 | + block.url = "www.youtube.com/?v=XXXXX" | ||
27 | + assert block.is_youtube? | ||
28 | + end | ||
29 | + | ||
30 | + should "is_youtube return true when the url contains youtube.com" do | ||
31 | + block = VideoBlock.new | ||
32 | + block.url = "youtube.com/?v=XXXXX" | ||
33 | + assert block.is_youtube? | ||
34 | + end | ||
35 | + | ||
36 | + should "is_youtube return false when the url not contains youtube video ID" do | ||
37 | + block = VideoBlock.new | ||
38 | + block.url = "youtube.com/" | ||
39 | + assert !block.is_youtube? | ||
40 | + end | ||
41 | + | ||
42 | + should "is_youtube return false when the url contains empty youtube video ID" do | ||
43 | + block = VideoBlock.new | ||
44 | + block.url = "youtube.com/?v=" | ||
45 | + assert !block.is_youtube? | ||
46 | + end | ||
47 | + | ||
48 | + should "is_youtube return false when the url contains an invalid youtube link" do | ||
49 | + block = VideoBlock.new | ||
50 | + block.url = "http://www.yt.com/?v=XXXXX" | ||
51 | + assert !block.is_youtube? | ||
52 | + end | ||
53 | + | ||
54 | + should "format embed video for youtube videos" do | ||
55 | + block = VideoBlock.new | ||
56 | + block.url = "youtube.com/?v=XXXXX" | ||
57 | + assert_match /\/\/www.youtube-nocookie.com\/embed/, block.format_embed_video_url_for_youtube | ||
58 | + end | ||
59 | + | ||
60 | + should "format embed video return nil if is not a youtube url" do | ||
61 | + block = VideoBlock.new | ||
62 | + block.url = "http://www.yt.com/?v=XXXXX" | ||
63 | + assert_nil block.format_embed_video_url_for_youtube | ||
64 | + end | ||
65 | + | ||
66 | + should "extract youtube id from youtube video url's if it's a valid youtube full url" do | ||
67 | + block = VideoBlock.new | ||
68 | + id = 'oi43jre2d2' | ||
69 | + block.url = "youtube.com/?v=#{id}" | ||
70 | + assert_equal id, block.send('extract_youtube_id') | ||
71 | + end | ||
72 | + | ||
73 | + should "extract youtube id from youtube video url's if it's a valid youtube short url" do | ||
74 | + block = VideoBlock.new | ||
75 | + id = 'oi43jre2d2' | ||
76 | + block.url = "youtu.be/#{id}" | ||
77 | + assert_equal id, block.send('extract_youtube_id') | ||
78 | + end | ||
79 | + | ||
80 | + should "extract_youtube_id return nil if the url it's not a valid youtube url" do | ||
81 | + block = VideoBlock.new | ||
82 | + block.url = "http://www.yt.com/?v=XXXXX" | ||
83 | + assert_nil block.send('extract_youtube_id') | ||
84 | + end | ||
85 | + | ||
86 | + should "extract_youtube_id return nil if youtue url there is no id" do | ||
87 | + block = VideoBlock.new | ||
88 | + block.url = "youtube.com/" | ||
89 | + assert_nil block.send('extract_youtube_id') | ||
90 | + end | ||
91 | + | ||
92 | + #### Tests for Vimeo Videos | ||
93 | + | ||
94 | + should "is_vimeo return true when the url contains http://vimeo.com" do | ||
95 | + block = VideoBlock.new | ||
96 | + block.url = "http://vimeo.com/98979" | ||
97 | + assert block.is_vimeo? | ||
98 | + end | ||
99 | + | ||
100 | + should "is_vimeo return true when the url contains https://vimeo.com" do | ||
101 | + block = VideoBlock.new | ||
102 | + block.url = "https://vimeo.com/989798" | ||
103 | + assert block.is_vimeo? | ||
104 | + end | ||
105 | + | ||
106 | + should "is_vimeo return true when the url contains https://www.vimeo.com" do | ||
107 | + block = VideoBlock.new | ||
108 | + block.url = "https://www.vimeo.com/98987" | ||
109 | + assert block.is_vimeo? | ||
110 | + end | ||
111 | + | ||
112 | + should "is_vimeo return true when the url contains www.vimeo.com" do | ||
113 | + block = VideoBlock.new | ||
114 | + block.url = "www.vimeo.com/989798" | ||
115 | + assert block.is_vimeo? | ||
116 | + end | ||
117 | + | ||
118 | + should "is_vimeo return true when the url contains vimeo.com" do | ||
119 | + block = VideoBlock.new | ||
120 | + block.url = "vimeo.com/09898" | ||
121 | + assert block.is_vimeo? | ||
122 | + end | ||
123 | + | ||
124 | + should "is_vimeo return false when the url not contains vimeo video ID" do | ||
125 | + block = VideoBlock.new | ||
126 | + block.url = "vimeo.com/home" | ||
127 | + assert !block.is_vimeo? | ||
128 | + end | ||
129 | + | ||
130 | + should "is_vimeo return false when the url contains empty vimeo video ID" do | ||
131 | + block = VideoBlock.new | ||
132 | + block.url = "vimeo.com/" | ||
133 | + assert !block.is_vimeo? | ||
134 | + end | ||
135 | + | ||
136 | + should "is_vimeo return false when the url contains an invalid vimeo link" do | ||
137 | + block = VideoBlock.new | ||
138 | + block.url = "http://www.vmsd.com/98979" | ||
139 | + assert !block.is_vimeo? | ||
140 | + end | ||
141 | + | ||
142 | + should "format embed video for vimeo videos" do | ||
143 | + block = VideoBlock.new | ||
144 | + block.url = "vimeo.com/09898" | ||
145 | + assert_match /\/\/player.vimeo.com\/video\/[[:digit:]]+/, block.format_embed_video_url_for_vimeo | ||
146 | + end | ||
147 | + | ||
148 | + should "format embed video return nil if is not a vimeo url" do | ||
149 | + block = VideoBlock.new | ||
150 | + block.url = "http://www.yt.com/?v=XXXXX" | ||
151 | + assert_nil block.format_embed_video_url_for_vimeo | ||
152 | + end | ||
153 | + | ||
154 | + should "extract vimeo id from vimeo video url's if it's a valid vimeo url" do | ||
155 | + block = VideoBlock.new | ||
156 | + id = '23048239432' | ||
157 | + block.url = "vimeo.com/#{id}" | ||
158 | + assert_equal id, block.send('extract_vimeo_id') | ||
159 | + end | ||
160 | + | ||
161 | + should "extract_vimeo_id return nil if the url it's not a valid vimeo url" do | ||
162 | + block = VideoBlock.new | ||
163 | + block.url = "http://www.yt.com/XXXXX" | ||
164 | + assert_nil block.send('extract_vimeo_id') | ||
165 | + end | ||
166 | + | ||
167 | + should "extract_vimeo_id return nil if vimeo url there is no id" do | ||
168 | + block = VideoBlock.new | ||
169 | + block.url = "vimeo.com/" | ||
170 | + assert_nil block.send('extract_youtube_id') | ||
171 | + end | ||
172 | + | ||
173 | + # Other video formats | ||
174 | + should "is_video return true if url ends with mp4" do | ||
175 | + block = VideoBlock.new | ||
176 | + block.url = "http://www.vmsd.com/98979.mp4" | ||
177 | + assert block.is_video_file? | ||
178 | + end | ||
179 | + | ||
180 | + should "is_video return true if url ends with ogg" do | ||
181 | + block = VideoBlock.new | ||
182 | + block.url = "http://www.vmsd.com/98979.ogg" | ||
183 | + assert block.is_video_file? | ||
184 | + end | ||
185 | + | ||
186 | + should "is_video return true if url ends with ogv" do | ||
187 | + block = VideoBlock.new | ||
188 | + block.url = "http://www.vmsd.com/98979.ogv" | ||
189 | + assert block.is_video_file? | ||
190 | + end | ||
191 | + | ||
192 | + should "is_video return true if url ends with webm" do | ||
193 | + block = VideoBlock.new | ||
194 | + block.url = "http://www.vmsd.com/98979.webm" | ||
195 | + assert block.is_video_file? | ||
196 | + end | ||
197 | + | ||
198 | + should "is_video return false if url ends without mp4, ogg, ogv, webm" do | ||
199 | + block = VideoBlock.new | ||
200 | + block.url = "http://www.vmsd.com/98979.mp4r" | ||
201 | + assert !block.is_video_file? | ||
202 | + block.url = "http://www.vmsd.com/98979.oggr" | ||
203 | + assert !block.is_video_file? | ||
204 | + block.url = "http://www.vmsd.com/98979.ogvr" | ||
205 | + assert !block.is_video_file? | ||
206 | + block.url = "http://www.vmsd.com/98979.webmr" | ||
207 | + assert !block.is_video_file? | ||
208 | + end | ||
209 | + | ||
210 | + should 'display video block partial' do | ||
211 | + block = VideoBlock.new | ||
212 | + self.expects(:render).with(:file => 'video_block', :locals => { | ||
213 | + :block => block | ||
214 | + }) | ||
215 | + instance_eval(& block.content) | ||
216 | + end | ||
217 | + | ||
218 | +end |
plugins/video/views/box_organizer/_html5_video_block.rhtml
0 → 100644
plugins/video/views/box_organizer/_iframe_video_block.rhtml
0 → 100644
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +<iframe width='<%="#{width}px"%>' height='<%="#{height}px"%>' src='<%= "#{url}" %>' frameborder="0" allowfullscreen></iframe> |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +<label for="url" class="formlabel"> Video URL: </label> | ||
2 | + | ||
3 | +<div class="formfield type-text"> | ||
4 | + <%= text_field_tag 'block[url]', @block.url, :class => 'video-url', :maxlength => 255 %> | ||
5 | +</div> | ||
6 | +<div class="formfield type-text"> | ||
7 | + <label for="width" class="formlabel"> Width: </label> | ||
8 | + <%= text_field_tag 'block[width]', @block.width, :size => 7, :class => 'video-width', :maxlength => 5 %> | ||
9 | + <label for="height" class="formlabel"> Height: </label> | ||
10 | + <%= text_field_tag 'block[height]', @block.height, :size => 7, :class => 'video-height', :maxlength => 5 %> | ||
11 | +</div> |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +<h3 class="block-title"> | ||
2 | + <span><%=block.title%></span> | ||
3 | +</h3> | ||
4 | +<div class="video-block-data"> | ||
5 | + <% if block.is_youtube? %> | ||
6 | + <div class='youtube'> | ||
7 | + <%= render :partial => 'box_organizer/iframe_video_block', :locals => { :url => block.format_embed_video_url_for_youtube, :width => block.width, :height => block.height }%> | ||
8 | + </div> | ||
9 | + <% elsif block.is_vimeo? %> | ||
10 | + <div class='vimeo'> | ||
11 | + <%= render :partial => 'box_organizer/iframe_video_block', :locals => { :url => block.format_embed_video_url_for_vimeo, :width => block.width, :height => block.height }%> | ||
12 | + </div> | ||
13 | + <% elsif block.is_video_file? %> | ||
14 | + <div class='video'> | ||
15 | + <%= render :partial => 'box_organizer/html5_video_block', :locals => { :url => block.url, :width => block.width, :height => block.height }%> | ||
16 | + </div> | ||
17 | + <% else %> | ||
18 | + <span class='alert-block'><%= _("Register a valid url (Vimeo, Youtube, video files)") %></span> | ||
19 | + <% end %> | ||
20 | + | ||
21 | +</div> |
public/designs/icons/tango/ie6.css
@@ -1,52 +0,0 @@ | @@ -1,52 +0,0 @@ | ||
1 | -.msie6 .icon-edit { background-image: url(ie6/Tango/16x16/apps/text-editor.gif) } | ||
2 | -.msie6 .icon-home { background-image: url(ie6/Tango/16x16/actions/go-home.gif) } | ||
3 | -.msie6 .icon-new, | ||
4 | -.msie6 .icon-suggest { background-image: url(ie6/Tango/16x16/actions/filenew.gif) } | ||
5 | -.msie6 .icon-close { background-image: url(ie6/Tango/16x16/actions/gtk-cancel.gif) } | ||
6 | -.msie6 .icon-newfolder { background-image: url(ie6/Tango/16x16/actions/folder-new.gif) } | ||
7 | -.msie6 .icon-save { background-image: url(ie6/Tango/16x16/actions/filesave.gif) } | ||
8 | -.msie6 .icon-send { background-image: url(ie6/Tango/16x16/actions/stock_mail-forward.gif) } | ||
9 | -.msie6 .icon-cancel { background-image: url(ie6/Tango/16x16/actions/gtk-cancel.gif) } | ||
10 | -.msie6 .icon-person { background-image: url(ie6/Tango/16x16/apps/system-config-users.gif) } | ||
11 | -.msie6 .icon-product { background-image: url(ie6/Tango/16x16/mimetypes/package.gif) } | ||
12 | -.msie6 .icon-delete { background-image: url(ie6/Tango/16x16/places/user-trash.gif) } | ||
13 | -.msie6 .icon-back { background-image: url(ie6/Tango/16x16/actions/back.gif) } | ||
14 | -.msie6 .icon-next { background-image: url(ie6/Tango/16x16/actions/go-next.gif) } | ||
15 | -.msie6 .icon-add { background-image: url(ie6/Tango/16x16/actions/add.gif) } | ||
16 | -.msie6 .icon-more { background-image: url(ie6/Tango/16x16/actions/add.gif) } | ||
17 | -.msie6 .icon-up { background-image: url(ie6/Tango/16x16/actions/go-up.gif) } | ||
18 | -.msie6 .icon-down { background-image: url(ie6/Tango/16x16/actions/go-down.gif) } | ||
19 | -.msie6 .icon-left { background-image: url(ie6/Tango/16x16/actions/go-previous.gif) } | ||
20 | -.msie6 .icon-right { background-image: url(ie6/Tango/16x16/actions/go-next.gif) } | ||
21 | -.msie6 .icon-up-disabled { background-image: url(ie6/Tango/16x16/actions/go-up.gif); opacity: 0.25; filter:alpha(opacity=25); } | ||
22 | -.msie6 .icon-down-disabled { background-image: url(ie6/Tango/16x16/actions/go-down.gif); opacity: 0.25; filter:alpha(opacity=25); } | ||
23 | -.msie6 .icon-left-disabled { background-image: url(ie6/Tango/16x16/actions/go-previous.gif); opacity: 0.25; filter:alpha(opacity=25); } | ||
24 | -.msie6 .icon-right-disabled { background-image: url(ie6/Tango/16x16/actions/go-next.gif); opacity: 0.25; filter:alpha(opacity=25); } | ||
25 | -.msie6 .icon-up-red { background-image: url(ie6/mod/16x16/actions/go-up-red.gif) } | ||
26 | -.msie6 .icon-forward { background-image: url(ie6/Tango/16x16/actions/go-next.gif) } | ||
27 | -.msie6 .icon-search { background-image: url(ie6/Tango/16x16/actions/search.gif) } | ||
28 | -.msie6 .icon-ok { background-image: url(ie6/Tango/16x16/actions/media-playback-start.gif) } | ||
29 | -.msie6 .icon-login { background-image: url(ie6/mod/16x16/actions/log-in.gif) } | ||
30 | -.msie6 .icon-help { background-image: url(ie6/Tango/16x16/apps/gnome-help.gif) } | ||
31 | -.msie6 .icon-firefox { background-image: url(firefox-24x24.gif) } | ||
32 | -.msie6 .icon-help32on { background-image: url(ie6/Tango/32x32/apps/gnome-help.gif) } | ||
33 | -.msie6 .icon-help32off { background-image: url(ie6/mod/32x32/apps/gnome-help-red.gif) } | ||
34 | -.msie6 .icon-spread { background-image: url(ie6/mod/16x16/actions/spread.gif) } | ||
35 | -.msie6 .icon-todo { background-image: url(ie6/Tango/16x16/actions/stock_paste.gif) } | ||
36 | -.msie6 .icon-eyes { background-image: url(ie6/Tango/16x16/actions/gtk-print-preview.gif) } | ||
37 | -.msie6 .icon-menu-home { background-image: url(ie6/Tango/16x16/actions/go-home.gif) } | ||
38 | -.msie6 .icon-menu-product { background-image: url(ie6/Tango/16x16/mimetypes/package.gif) } | ||
39 | -.msie6 .icon-menu-enterprise { background-image: url(ie6/Tango/16x16/actions/go-home.gif) } | ||
40 | -.msie6 .icon-menu-community { background-image: url(ie6/Tango/16x16/apps/system-config-users.gif) } | ||
41 | -.msie6 .icon-menu-ctrl-panel { background-image: url(ie6/Tango/16x16/categories/preferences-desktop.gif) } | ||
42 | -.msie6 .icon-menu-admin { background-image: url(ie6/Tango/16x16/categories/preferences-system.gif) } | ||
43 | -.msie6 .icon-menu-my-groups { background-image: url(ie6/Tango/16x16/apps/system-config-users.gif) } | ||
44 | -.msie6 .icon-menu-login { background-image: url(ie6/mod/16x16/actions/log-in.gif) } | ||
45 | -.msie6 .icon-menu-logout { background-image: url(ie6/Tango/16x16/actions/exit.gif) } | ||
46 | -.msie6 .icon-menu-search { background-image: url(ie6/Tango/16x16/actions/search.gif) } | ||
47 | -.msie6 .icon-menu-events { background-image: url(ie6/Tango/16x16/mimetypes/stock_calendar.gif) } | ||
48 | -.msie6 .icon-menu-articles { background-image: url(ie6/Tango/16x16/apps/text-editor.gif) } | ||
49 | -.msie6 .icon-menu-people { background-image: url(ie6/mod/16x16/apps/user.gif) } | ||
50 | -.msie6 .icon-menu-mail { background-image: url(ie6/Tango/16x16/apps/email.gif) } | ||
51 | -.msie6 .icon-upload-file { background-image: url(ie6/Tango/16x16/actions/filesave.gif) } | ||
52 | -.msie6 .icon-slideshow { background-image: url(ie6/Tango/16x16/mimetypes/x-office-presentation.gif) } |
public/designs/icons/tango/ie6/Tango/16x16/actions/add.gif
192 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/back.gif
570 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/exit.gif
1.03 KB
public/designs/icons/tango/ie6/Tango/16x16/actions/filenew.gif
354 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/filesave.gif
750 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/folder-new.gif
599 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/go-down.gif
568 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/go-home.gif
587 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/go-next.gif
570 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/go-previous.gif
570 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/go-up.gif
572 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/gtk-cancel.gif
1022 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/gtk-print-preview.gif
1022 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/media-playback-start.gif
314 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/search.gif
601 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/stock_mail-forward.gif
601 Bytes
public/designs/icons/tango/ie6/Tango/16x16/actions/stock_paste.gif
595 Bytes
public/designs/icons/tango/ie6/Tango/16x16/apps/email.gif
347 Bytes
public/designs/icons/tango/ie6/Tango/16x16/apps/gnome-help.gif
1.01 KB
public/designs/icons/tango/ie6/Tango/16x16/apps/system-config-users.gif
1.05 KB
public/designs/icons/tango/ie6/Tango/16x16/apps/text-editor.gif
363 Bytes
public/designs/icons/tango/ie6/Tango/16x16/categories/preferences-desktop.gif
357 Bytes
public/designs/icons/tango/ie6/Tango/16x16/categories/preferences-system.gif
333 Bytes
public/designs/icons/tango/ie6/Tango/16x16/mimetypes/package.gif
573 Bytes
public/designs/icons/tango/ie6/Tango/16x16/mimetypes/stock_calendar.gif
382 Bytes
public/designs/icons/tango/ie6/Tango/16x16/mimetypes/x-office-presentation.gif
559 Bytes
public/designs/icons/tango/ie6/Tango/16x16/places/user-home.gif
1 KB
public/designs/icons/tango/ie6/Tango/16x16/places/user-trash.gif
1009 Bytes
public/designs/icons/tango/ie6/Tango/32x32/apps/gnome-help.gif
1.03 KB
public/designs/icons/tango/ie6/mod/16x16/actions/go-up-red.gif
361 Bytes
public/designs/icons/tango/ie6/mod/16x16/actions/log-in.gif
246 Bytes
public/designs/icons/tango/ie6/mod/16x16/actions/log-out.gif
241 Bytes
public/designs/icons/tango/ie6/mod/16x16/actions/password.gif
546 Bytes
public/designs/icons/tango/ie6/mod/16x16/actions/spread.gif
532 Bytes
public/designs/icons/tango/ie6/mod/16x16/apps/user.gif
620 Bytes
public/designs/icons/tango/ie6/mod/32x32/apps/gnome-help-red.gif
969 Bytes
1.02 KB
public/designs/icons/tango/mod/scalable/actions/go-home-not.svg
0 → 100644
@@ -0,0 +1,1112 @@ | @@ -0,0 +1,1112 @@ | ||
1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
2 | +<svg | ||
3 | + xmlns:osb="http://www.openswatchbook.org/uri/2009/osb" | ||
4 | + xmlns:dc="http://purl.org/dc/elements/1.1/" | ||
5 | + xmlns:cc="http://creativecommons.org/ns#" | ||
6 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||
7 | + xmlns:svg="http://www.w3.org/2000/svg" | ||
8 | + xmlns="http://www.w3.org/2000/svg" | ||
9 | + xmlns:xlink="http://www.w3.org/1999/xlink" | ||
10 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||
11 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||
12 | + width="48" | ||
13 | + height="48" | ||
14 | + overflow="visible" | ||
15 | + enable-background="new 0 0 128 129.396" | ||
16 | + xml:space="preserve" | ||
17 | + id="svg2" | ||
18 | + sodipodi:version="0.32" | ||
19 | + inkscape:version="0.48.1 r9760" | ||
20 | + sodipodi:docname="go-home-not.svg" | ||
21 | + version="1.0" | ||
22 | + inkscape:export-filename="/home/85902810515/projetos/noosfero/public/designs/icons/tango/mod/16x16/actions/go-home-not.png" | ||
23 | + inkscape:export-xdpi="30.01" | ||
24 | + inkscape:export-ydpi="30.01" | ||
25 | + inkscape:output_extension="org.inkscape.output.svg.inkscape" | ||
26 | + style="display:inline;overflow:visible"><metadata | ||
27 | + id="metadata367"><rdf:RDF><cc:Work | ||
28 | + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | ||
29 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license | ||
30 | + rdf:resource="http://creativecommons.org/licenses/publicdomain/" /><dc:title></dc:title><dc:creator><cc:Agent><dc:title>Jakub Steiner</dc:title></cc:Agent></dc:creator><dc:source>http://jimmac.musichall.cz</dc:source><dc:subject><rdf:Bag><rdf:li>home</rdf:li><rdf:li>return</rdf:li><rdf:li>go</rdf:li><rdf:li>default</rdf:li><rdf:li>user</rdf:li><rdf:li>directory</rdf:li></rdf:Bag></dc:subject><dc:contributor><cc:Agent><dc:title>Tuomas Kuosmanen</dc:title></cc:Agent></dc:contributor></cc:Work><cc:License | ||
31 | + rdf:about="http://creativecommons.org/licenses/publicdomain/"><cc:permits | ||
32 | + rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits | ||
33 | + rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:permits | ||
34 | + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata><defs | ||
35 | + id="defs365"><linearGradient | ||
36 | + id="linearGradient4711"><stop | ||
37 | + style="stop-color:#f87171;stop-opacity:1;" | ||
38 | + offset="0" | ||
39 | + id="stop4713" /><stop | ||
40 | + style="stop-color:#fb1f22;stop-opacity:1;" | ||
41 | + offset="1" | ||
42 | + id="stop4715" /></linearGradient><linearGradient | ||
43 | + id="linearGradient4700"><stop | ||
44 | + style="stop-color:#b20000;stop-opacity:1;" | ||
45 | + offset="0" | ||
46 | + id="stop4702" /><stop | ||
47 | + style="stop-color:#db0000;stop-opacity:1;" | ||
48 | + offset="1" | ||
49 | + id="stop4704" /></linearGradient><linearGradient | ||
50 | + id="linearGradient4694" | ||
51 | + osb:paint="solid"><stop | ||
52 | + style="stop-color:#2042e2;stop-opacity:1;" | ||
53 | + offset="0" | ||
54 | + id="stop4696" /></linearGradient><inkscape:perspective | ||
55 | + sodipodi:type="inkscape:persp3d" | ||
56 | + inkscape:vp_x="0 : 24 : 1" | ||
57 | + inkscape:vp_y="0 : 1000 : 0" | ||
58 | + inkscape:vp_z="48 : 24 : 1" | ||
59 | + inkscape:persp3d-origin="24 : 16 : 1" | ||
60 | + id="perspective92" /><radialGradient | ||
61 | + inkscape:collect="always" | ||
62 | + xlink:href="#linearGradient5060" | ||
63 | + id="radialGradient5031" | ||
64 | + gradientUnits="userSpaceOnUse" | ||
65 | + gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)" | ||
66 | + cx="605.71429" | ||
67 | + cy="486.64789" | ||
68 | + fx="605.71429" | ||
69 | + fy="486.64789" | ||
70 | + r="117.14286" /><linearGradient | ||
71 | + inkscape:collect="always" | ||
72 | + id="linearGradient5060"><stop | ||
73 | + style="stop-color:black;stop-opacity:1;" | ||
74 | + offset="0" | ||
75 | + id="stop5062" /><stop | ||
76 | + style="stop-color:black;stop-opacity:0;" | ||
77 | + offset="1" | ||
78 | + id="stop5064" /></linearGradient><radialGradient | ||
79 | + inkscape:collect="always" | ||
80 | + xlink:href="#linearGradient5060" | ||
81 | + id="radialGradient5029" | ||
82 | + gradientUnits="userSpaceOnUse" | ||
83 | + gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)" | ||
84 | + cx="605.71429" | ||
85 | + cy="486.64789" | ||
86 | + fx="605.71429" | ||
87 | + fy="486.64789" | ||
88 | + r="117.14286" /><linearGradient | ||
89 | + id="linearGradient5048"><stop | ||
90 | + style="stop-color:black;stop-opacity:0;" | ||
91 | + offset="0" | ||
92 | + id="stop5050" /><stop | ||
93 | + id="stop5056" | ||
94 | + offset="0.5" | ||
95 | + style="stop-color:black;stop-opacity:1;" /><stop | ||
96 | + style="stop-color:black;stop-opacity:0;" | ||
97 | + offset="1" | ||
98 | + id="stop5052" /></linearGradient><linearGradient | ||
99 | + inkscape:collect="always" | ||
100 | + xlink:href="#linearGradient5048" | ||
101 | + id="linearGradient5027" | ||
102 | + gradientUnits="userSpaceOnUse" | ||
103 | + gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)" | ||
104 | + x1="302.85715" | ||
105 | + y1="366.64789" | ||
106 | + x2="302.85715" | ||
107 | + y2="609.50507" /><linearGradient | ||
108 | + id="linearGradient2406"><stop | ||
109 | + style="stop-color:#7c7e79;stop-opacity:1;" | ||
110 | + offset="0" | ||
111 | + id="stop2408" /><stop | ||
112 | + id="stop2414" | ||
113 | + offset="0.1724138" | ||
114 | + style="stop-color:#848681;stop-opacity:1;" /><stop | ||
115 | + style="stop-color:#898c86;stop-opacity:1;" | ||
116 | + offset="1" | ||
117 | + id="stop2410" /></linearGradient><linearGradient | ||
118 | + inkscape:collect="always" | ||
119 | + id="linearGradient2390"><stop | ||
120 | + style="stop-color:#919191;stop-opacity:1;" | ||
121 | + offset="0" | ||
122 | + id="stop2392" /><stop | ||
123 | + style="stop-color:#919191;stop-opacity:0;" | ||
124 | + offset="1" | ||
125 | + id="stop2394" /></linearGradient><linearGradient | ||
126 | + inkscape:collect="always" | ||
127 | + id="linearGradient2378"><stop | ||
128 | + style="stop-color:#575757;stop-opacity:1;" | ||
129 | + offset="0" | ||
130 | + id="stop2380" /><stop | ||
131 | + style="stop-color:#575757;stop-opacity:0;" | ||
132 | + offset="1" | ||
133 | + id="stop2382" /></linearGradient><linearGradient | ||
134 | + inkscape:collect="always" | ||
135 | + id="linearGradient2368"><stop | ||
136 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
137 | + offset="0" | ||
138 | + id="stop2370" /><stop | ||
139 | + style="stop-color:#ffffff;stop-opacity:0;" | ||
140 | + offset="1" | ||
141 | + id="stop2372" /></linearGradient><linearGradient | ||
142 | + inkscape:collect="always" | ||
143 | + id="linearGradient2349"><stop | ||
144 | + style="stop-color:#000000;stop-opacity:1;" | ||
145 | + offset="0" | ||
146 | + id="stop2351" /><stop | ||
147 | + style="stop-color:#000000;stop-opacity:0;" | ||
148 | + offset="1" | ||
149 | + id="stop2353" /></linearGradient><linearGradient | ||
150 | + id="linearGradient2341"><stop | ||
151 | + id="stop2343" | ||
152 | + offset="0" | ||
153 | + style="stop-color:#000000;stop-opacity:1;" /><stop | ||
154 | + id="stop2345" | ||
155 | + offset="1" | ||
156 | + style="stop-color:#000000;stop-opacity:0;" /></linearGradient><linearGradient | ||
157 | + id="linearGradient2329"><stop | ||
158 | + style="stop-color:#000000;stop-opacity:0.18556701;" | ||
159 | + offset="0" | ||
160 | + id="stop2331" /><stop | ||
161 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
162 | + offset="1" | ||
163 | + id="stop2333" /></linearGradient><linearGradient | ||
164 | + inkscape:collect="always" | ||
165 | + id="linearGradient2319"><stop | ||
166 | + style="stop-color:#000000;stop-opacity:1;" | ||
167 | + offset="0" | ||
168 | + id="stop2321" /><stop | ||
169 | + style="stop-color:#000000;stop-opacity:0;" | ||
170 | + offset="1" | ||
171 | + id="stop2323" /></linearGradient><linearGradient | ||
172 | + id="linearGradient2307"><stop | ||
173 | + style="stop-color:#edd400;stop-opacity:1;" | ||
174 | + offset="0" | ||
175 | + id="stop2309" /><stop | ||
176 | + style="stop-color:#998800;stop-opacity:1;" | ||
177 | + offset="1" | ||
178 | + id="stop2311" /></linearGradient><linearGradient | ||
179 | + inkscape:collect="always" | ||
180 | + id="linearGradient2299"><stop | ||
181 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
182 | + offset="0" | ||
183 | + id="stop2301" /><stop | ||
184 | + style="stop-color:#ffffff;stop-opacity:0;" | ||
185 | + offset="1" | ||
186 | + id="stop2303" /></linearGradient><linearGradient | ||
187 | + id="XMLID_2_" | ||
188 | + gradientUnits="userSpaceOnUse" | ||
189 | + x1="80.223602" | ||
190 | + y1="117.5205" | ||
191 | + x2="48.046001" | ||
192 | + y2="59.7995" | ||
193 | + gradientTransform="matrix(0.314683,0,0,0.314683,4.128264,3.742874)"> | ||
194 | + <stop | ||
195 | + offset="0" | ||
196 | + style="stop-color:#CCCCCC" | ||
197 | + id="stop17" /> | ||
198 | + <stop | ||
199 | + offset="0.9831" | ||
200 | + style="stop-color:#FFFFFF" | ||
201 | + id="stop19" /> | ||
202 | + <midPointStop | ||
203 | + offset="0" | ||
204 | + style="stop-color:#CCCCCC" | ||
205 | + id="midPointStop48" /> | ||
206 | + <midPointStop | ||
207 | + offset="0.5" | ||
208 | + style="stop-color:#CCCCCC" | ||
209 | + id="midPointStop50" /> | ||
210 | + <midPointStop | ||
211 | + offset="0.9831" | ||
212 | + style="stop-color:#FFFFFF" | ||
213 | + id="midPointStop52" /> | ||
214 | + </linearGradient><linearGradient | ||
215 | + inkscape:collect="always" | ||
216 | + xlink:href="#XMLID_2_" | ||
217 | + id="linearGradient1514" | ||
218 | + gradientUnits="userSpaceOnUse" | ||
219 | + gradientTransform="matrix(0.336922,0,0,0.166888,17.98288,15.46151)" | ||
220 | + x1="52.006104" | ||
221 | + y1="166.1331" | ||
222 | + x2="14.049017" | ||
223 | + y2="-42.218513" /><linearGradient | ||
224 | + id="XMLID_39_" | ||
225 | + gradientUnits="userSpaceOnUse" | ||
226 | + x1="64.387703" | ||
227 | + y1="65.124001" | ||
228 | + x2="64.387703" | ||
229 | + y2="35.569" | ||
230 | + gradientTransform="matrix(0.354101,0,0,0.354101,1.638679,-0.08364921)"> | ||
231 | + <stop | ||
232 | + offset="0" | ||
233 | + style="stop-color:#FFFFFF" | ||
234 | + id="stop336" /> | ||
235 | + <stop | ||
236 | + offset="0.8539" | ||
237 | + style="stop-color:#FF6200" | ||
238 | + id="stop338" /> | ||
239 | + <stop | ||
240 | + offset="1" | ||
241 | + style="stop-color:#F25D00" | ||
242 | + id="stop340" /> | ||
243 | + <midPointStop | ||
244 | + offset="0" | ||
245 | + style="stop-color:#FFFFFF" | ||
246 | + id="midPointStop335" /> | ||
247 | + <midPointStop | ||
248 | + offset="0.5" | ||
249 | + style="stop-color:#FFFFFF" | ||
250 | + id="midPointStop337" /> | ||
251 | + <midPointStop | ||
252 | + offset="0.8539" | ||
253 | + style="stop-color:#FF6200" | ||
254 | + id="midPointStop339" /> | ||
255 | + <midPointStop | ||
256 | + offset="0.5" | ||
257 | + style="stop-color:#FF6200" | ||
258 | + id="midPointStop341" /> | ||
259 | + <midPointStop | ||
260 | + offset="1" | ||
261 | + style="stop-color:#F25D00" | ||
262 | + id="midPointStop343" /> | ||
263 | + </linearGradient><radialGradient | ||
264 | + inkscape:collect="always" | ||
265 | + xlink:href="#linearGradient2299" | ||
266 | + id="radialGradient2305" | ||
267 | + cx="7.5326638" | ||
268 | + cy="24.202574" | ||
269 | + fx="7.5326638" | ||
270 | + fy="24.202574" | ||
271 | + r="8.2452126" | ||
272 | + gradientTransform="matrix(4.100086,0,0,4.201322,-25.41506,-78.53967)" | ||
273 | + gradientUnits="userSpaceOnUse" /><radialGradient | ||
274 | + inkscape:collect="always" | ||
275 | + xlink:href="#linearGradient2307" | ||
276 | + id="radialGradient2313" | ||
277 | + cx="19.985598" | ||
278 | + cy="36.77816" | ||
279 | + fx="19.985598" | ||
280 | + fy="36.77816" | ||
281 | + r="1.0821035" | ||
282 | + gradientTransform="matrix(1.125263,0,0,0.982744,-3.428678,0.565787)" | ||
283 | + gradientUnits="userSpaceOnUse" /><radialGradient | ||
284 | + inkscape:collect="always" | ||
285 | + xlink:href="#linearGradient2319" | ||
286 | + id="radialGradient2325" | ||
287 | + cx="20.443665" | ||
288 | + cy="37.425831" | ||
289 | + fx="20.443665" | ||
290 | + fy="37.425831" | ||
291 | + r="1.0821035" | ||
292 | + gradientTransform="matrix(1.125263,0,0,0.982744,-3.428678,0.731106)" | ||
293 | + gradientUnits="userSpaceOnUse" /><linearGradient | ||
294 | + inkscape:collect="always" | ||
295 | + xlink:href="#linearGradient2329" | ||
296 | + id="linearGradient2335" | ||
297 | + x1="17.602522" | ||
298 | + y1="26.057423" | ||
299 | + x2="17.682528" | ||
300 | + y2="32.654099" | ||
301 | + gradientUnits="userSpaceOnUse" | ||
302 | + gradientTransform="matrix(0.898789,0,0,1.071914,0.478025,-2.080838)" /><radialGradient | ||
303 | + inkscape:collect="always" | ||
304 | + xlink:href="#linearGradient2341" | ||
305 | + id="radialGradient2339" | ||
306 | + gradientUnits="userSpaceOnUse" | ||
307 | + gradientTransform="matrix(4.100086,0,0,-4.201322,-5.198109,105.3535)" | ||
308 | + cx="11.68129" | ||
309 | + cy="19.554111" | ||
310 | + fx="11.68129" | ||
311 | + fy="19.554111" | ||
312 | + r="8.2452126" /><radialGradient | ||
313 | + inkscape:collect="always" | ||
314 | + xlink:href="#linearGradient2349" | ||
315 | + id="radialGradient2355" | ||
316 | + cx="24.023088" | ||
317 | + cy="40.56913" | ||
318 | + fx="24.023088" | ||
319 | + fy="40.56913" | ||
320 | + r="16.28684" | ||
321 | + gradientTransform="matrix(1,0,0,0.43125,0,23.07369)" | ||
322 | + gradientUnits="userSpaceOnUse" /><radialGradient | ||
323 | + inkscape:collect="always" | ||
324 | + xlink:href="#linearGradient2368" | ||
325 | + id="radialGradient2374" | ||
326 | + cx="29.913452" | ||
327 | + cy="30.442923" | ||
328 | + fx="29.913452" | ||
329 | + fy="30.442923" | ||
330 | + r="4.001883" | ||
331 | + gradientTransform="matrix(3.751495,0,0,3.147818,-82.00907,-65.70704)" | ||
332 | + gradientUnits="userSpaceOnUse" /><radialGradient | ||
333 | + inkscape:collect="always" | ||
334 | + xlink:href="#linearGradient2378" | ||
335 | + id="radialGradient2384" | ||
336 | + cx="24.195112" | ||
337 | + cy="10.577631" | ||
338 | + fx="24.195112" | ||
339 | + fy="10.577631" | ||
340 | + r="15.242914" | ||
341 | + gradientTransform="matrix(1.125263,-3.585417e-8,4.269819e-8,1.340059,-3.006704,1.355395)" | ||
342 | + gradientUnits="userSpaceOnUse" /><linearGradient | ||
343 | + inkscape:collect="always" | ||
344 | + xlink:href="#linearGradient2390" | ||
345 | + id="linearGradient2396" | ||
346 | + x1="30.603519" | ||
347 | + y1="37.337803" | ||
348 | + x2="30.603519" | ||
349 | + y2="36.112415" | ||
350 | + gradientUnits="userSpaceOnUse" | ||
351 | + gradientTransform="matrix(1.263867,0,0,0.859794,-6.499556,8.390924)" /><linearGradient | ||
352 | + inkscape:collect="always" | ||
353 | + xlink:href="#linearGradient2406" | ||
354 | + id="linearGradient2412" | ||
355 | + x1="17.850183" | ||
356 | + y1="28.939463" | ||
357 | + x2="19.040216" | ||
358 | + y2="41.03223" | ||
359 | + gradientUnits="userSpaceOnUse" | ||
360 | + gradientTransform="matrix(0.888785,0,0,1.08932,2.41099,-1.524336)" /><radialGradient | ||
361 | + inkscape:collect="always" | ||
362 | + xlink:href="#linearGradient9647" | ||
363 | + id="radialGradient2239" | ||
364 | + cx="24.30225" | ||
365 | + cy="33.30225" | ||
366 | + fx="24.30225" | ||
367 | + fy="33.30225" | ||
368 | + r="12.30225" | ||
369 | + gradientUnits="userSpaceOnUse" | ||
370 | + gradientTransform="matrix(1.693981,0,0,1.693981,-16.86529,-25.11111)" /><linearGradient | ||
371 | + id="linearGradient9647"><stop | ||
372 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
373 | + offset="0" | ||
374 | + id="stop9649" /><stop | ||
375 | + style="stop-color:#dbdbdb;stop-opacity:1;" | ||
376 | + offset="1" | ||
377 | + id="stop9651" /></linearGradient><linearGradient | ||
378 | + inkscape:collect="always" | ||
379 | + xlink:href="#linearGradient2256" | ||
380 | + id="linearGradient2262" | ||
381 | + x1="21.75" | ||
382 | + y1="15.80225" | ||
383 | + x2="24.30225" | ||
384 | + y2="35.05225" | ||
385 | + gradientUnits="userSpaceOnUse" | ||
386 | + gradientTransform="translate(0,-2)" /><linearGradient | ||
387 | + id="linearGradient2256"><stop | ||
388 | + style="stop-color:#ff0202;stop-opacity:1;" | ||
389 | + offset="0" | ||
390 | + id="stop2258" /><stop | ||
391 | + style="stop-color:#ff9b9b;stop-opacity:1;" | ||
392 | + offset="1" | ||
393 | + id="stop2260" /></linearGradient><radialGradient | ||
394 | + r="12.30225" | ||
395 | + fy="33.30225" | ||
396 | + fx="24.30225" | ||
397 | + cy="33.30225" | ||
398 | + cx="24.30225" | ||
399 | + gradientTransform="matrix(1.693981,0,0,1.693981,-5.6354248,-11.964506)" | ||
400 | + gradientUnits="userSpaceOnUse" | ||
401 | + id="radialGradient3047" | ||
402 | + xlink:href="#linearGradient9647" | ||
403 | + inkscape:collect="always" /><linearGradient | ||
404 | + y2="35.05225" | ||
405 | + x2="24.30225" | ||
406 | + y1="15.80225" | ||
407 | + x1="21.75" | ||
408 | + gradientTransform="translate(11.229865,11.146604)" | ||
409 | + gradientUnits="userSpaceOnUse" | ||
410 | + id="linearGradient3049" | ||
411 | + xlink:href="#linearGradient2256" | ||
412 | + inkscape:collect="always" /><radialGradient | ||
413 | + inkscape:collect="always" | ||
414 | + xlink:href="#linearGradient21644" | ||
415 | + id="radialGradient21650" | ||
416 | + cx="25.125" | ||
417 | + cy="36.75" | ||
418 | + fx="25.125" | ||
419 | + fy="36.75" | ||
420 | + r="15.75" | ||
421 | + gradientTransform="matrix(1,0,0,0.595238,0,14.875)" | ||
422 | + gradientUnits="userSpaceOnUse" /><linearGradient | ||
423 | + inkscape:collect="always" | ||
424 | + id="linearGradient21644"><stop | ||
425 | + style="stop-color:#000000;stop-opacity:1;" | ||
426 | + offset="0" | ||
427 | + id="stop21646" /><stop | ||
428 | + style="stop-color:#000000;stop-opacity:0;" | ||
429 | + offset="1" | ||
430 | + id="stop21648" /></linearGradient><linearGradient | ||
431 | + inkscape:collect="always" | ||
432 | + xlink:href="#linearGradient4981" | ||
433 | + id="linearGradient4987" | ||
434 | + x1="23.995985" | ||
435 | + y1="20.105337" | ||
436 | + x2="41.047836" | ||
437 | + y2="37.959785" | ||
438 | + gradientUnits="userSpaceOnUse" | ||
439 | + gradientTransform="translate(23.026616,19.550612)" /><linearGradient | ||
440 | + id="linearGradient4981"><stop | ||
441 | + style="stop-color:#cc0000;stop-opacity:1;" | ||
442 | + offset="0" | ||
443 | + id="stop4983" /><stop | ||
444 | + style="stop-color:#b30000;stop-opacity:1.0000000;" | ||
445 | + offset="1.0000000" | ||
446 | + id="stop4985" /></linearGradient><linearGradient | ||
447 | + inkscape:collect="always" | ||
448 | + xlink:href="#linearGradient11780" | ||
449 | + id="linearGradient2057" | ||
450 | + x1="15.737001" | ||
451 | + y1="12.5036" | ||
452 | + x2="53.570126" | ||
453 | + y2="47.374317" | ||
454 | + gradientUnits="userSpaceOnUse" | ||
455 | + gradientTransform="translate(23.026616,19.550612)" /><linearGradient | ||
456 | + id="linearGradient11780"><stop | ||
457 | + style="stop-color:#ff8b8b;stop-opacity:1.0000000;" | ||
458 | + offset="0.0000000" | ||
459 | + id="stop11782" /><stop | ||
460 | + style="stop-color:#ec1b1b;stop-opacity:1.0000000;" | ||
461 | + offset="1.0000000" | ||
462 | + id="stop11784" /></linearGradient><radialGradient | ||
463 | + inkscape:collect="always" | ||
464 | + xlink:href="#linearGradient2248" | ||
465 | + id="radialGradient2254" | ||
466 | + cx="16.75" | ||
467 | + cy="10.666344" | ||
468 | + fx="16.75" | ||
469 | + fy="10.666344" | ||
470 | + r="21.25" | ||
471 | + gradientTransform="matrix(4.154957,0,0,3.198723,-29.818914,-1.9585976)" | ||
472 | + gradientUnits="userSpaceOnUse" /><linearGradient | ||
473 | + inkscape:collect="always" | ||
474 | + id="linearGradient2248"><stop | ||
475 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
476 | + offset="0" | ||
477 | + id="stop2250" /><stop | ||
478 | + style="stop-color:#ffffff;stop-opacity:0;" | ||
479 | + offset="1" | ||
480 | + id="stop2252" /></linearGradient><radialGradient | ||
481 | + inkscape:collect="always" | ||
482 | + xlink:href="#linearGradient9647-3" | ||
483 | + id="radialGradient2239-7" | ||
484 | + cx="24.30225" | ||
485 | + cy="33.30225" | ||
486 | + fx="24.30225" | ||
487 | + fy="33.30225" | ||
488 | + r="12.30225" | ||
489 | + gradientUnits="userSpaceOnUse" | ||
490 | + gradientTransform="matrix(1.693981,0,0,1.693981,6.1613255,-3.5604976)" /><linearGradient | ||
491 | + id="linearGradient9647-3"><stop | ||
492 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
493 | + offset="0" | ||
494 | + id="stop9649-3" /><stop | ||
495 | + style="stop-color:#dbdbdb;stop-opacity:1;" | ||
496 | + offset="1" | ||
497 | + id="stop9651-2" /></linearGradient><linearGradient | ||
498 | + inkscape:collect="always" | ||
499 | + xlink:href="#linearGradient2256-0" | ||
500 | + id="linearGradient2262-5" | ||
501 | + x1="21.75" | ||
502 | + y1="15.80225" | ||
503 | + x2="24.30225" | ||
504 | + y2="35.05225" | ||
505 | + gradientUnits="userSpaceOnUse" | ||
506 | + gradientTransform="translate(23.026616,19.550612)" /><linearGradient | ||
507 | + id="linearGradient2256-0"><stop | ||
508 | + style="stop-color:#ff0202;stop-opacity:1;" | ||
509 | + offset="0" | ||
510 | + id="stop2258-2" /><stop | ||
511 | + style="stop-color:#ff9b9b;stop-opacity:1;" | ||
512 | + offset="1" | ||
513 | + id="stop2260-8" /></linearGradient><radialGradient | ||
514 | + r="15.75" | ||
515 | + fy="36.75" | ||
516 | + fx="25.125" | ||
517 | + cy="36.75" | ||
518 | + cx="25.125" | ||
519 | + gradientTransform="matrix(1,0,0,0.595238,0,14.875)" | ||
520 | + gradientUnits="userSpaceOnUse" | ||
521 | + id="radialGradient3090" | ||
522 | + xlink:href="#linearGradient21644" | ||
523 | + inkscape:collect="always" /><radialGradient | ||
524 | + inkscape:collect="always" | ||
525 | + xlink:href="#linearGradient21644" | ||
526 | + id="radialGradient3205" | ||
527 | + gradientUnits="userSpaceOnUse" | ||
528 | + gradientTransform="matrix(1,0,0,0.595238,0,14.875)" | ||
529 | + cx="25.125" | ||
530 | + cy="36.75" | ||
531 | + fx="25.125" | ||
532 | + fy="36.75" | ||
533 | + r="15.75" /><linearGradient | ||
534 | + inkscape:collect="always" | ||
535 | + xlink:href="#linearGradient4981" | ||
536 | + id="linearGradient3207" | ||
537 | + gradientUnits="userSpaceOnUse" | ||
538 | + gradientTransform="translate(23.026616,19.550612)" | ||
539 | + x1="23.995985" | ||
540 | + y1="20.105337" | ||
541 | + x2="41.047836" | ||
542 | + y2="37.959785" /><linearGradient | ||
543 | + inkscape:collect="always" | ||
544 | + xlink:href="#linearGradient11780" | ||
545 | + id="linearGradient3209" | ||
546 | + gradientUnits="userSpaceOnUse" | ||
547 | + gradientTransform="translate(23.026616,19.550612)" | ||
548 | + x1="15.737001" | ||
549 | + y1="12.5036" | ||
550 | + x2="53.570126" | ||
551 | + y2="47.374317" /><radialGradient | ||
552 | + inkscape:collect="always" | ||
553 | + xlink:href="#linearGradient2248" | ||
554 | + id="radialGradient3211" | ||
555 | + gradientUnits="userSpaceOnUse" | ||
556 | + gradientTransform="matrix(4.154957,0,0,3.198723,-29.818914,-1.9585976)" | ||
557 | + cx="16.75" | ||
558 | + cy="10.666344" | ||
559 | + fx="16.75" | ||
560 | + fy="10.666344" | ||
561 | + r="21.25" /><radialGradient | ||
562 | + inkscape:collect="always" | ||
563 | + xlink:href="#linearGradient9647-3" | ||
564 | + id="radialGradient3213" | ||
565 | + gradientUnits="userSpaceOnUse" | ||
566 | + gradientTransform="matrix(1.693981,0,0,1.693981,6.1613255,-3.5604976)" | ||
567 | + cx="24.30225" | ||
568 | + cy="33.30225" | ||
569 | + fx="24.30225" | ||
570 | + fy="33.30225" | ||
571 | + r="12.30225" /><linearGradient | ||
572 | + inkscape:collect="always" | ||
573 | + xlink:href="#linearGradient2256-0" | ||
574 | + id="linearGradient3215" | ||
575 | + gradientUnits="userSpaceOnUse" | ||
576 | + gradientTransform="translate(23.026616,19.550612)" | ||
577 | + x1="21.75" | ||
578 | + y1="15.80225" | ||
579 | + x2="24.30225" | ||
580 | + y2="35.05225" /><radialGradient | ||
581 | + inkscape:collect="always" | ||
582 | + xlink:href="#linearGradient21644" | ||
583 | + id="radialGradient3218" | ||
584 | + gradientUnits="userSpaceOnUse" | ||
585 | + gradientTransform="matrix(1.173803,0,0,0.3571428,17.76075,50.050612)" | ||
586 | + cx="25.125" | ||
587 | + cy="36.75" | ||
588 | + fx="25.125" | ||
589 | + fy="36.75" | ||
590 | + r="15.75" /><linearGradient | ||
591 | + inkscape:collect="always" | ||
592 | + xlink:href="#linearGradient4981" | ||
593 | + id="linearGradient3221" | ||
594 | + gradientUnits="userSpaceOnUse" | ||
595 | + gradientTransform="translate(23.026616,19.550612)" | ||
596 | + x1="23.995985" | ||
597 | + y1="20.105337" | ||
598 | + x2="41.047836" | ||
599 | + y2="37.959785" /><linearGradient | ||
600 | + inkscape:collect="always" | ||
601 | + xlink:href="#linearGradient11780" | ||
602 | + id="linearGradient3224" | ||
603 | + gradientUnits="userSpaceOnUse" | ||
604 | + gradientTransform="translate(23.026616,19.550612)" | ||
605 | + x1="15.737001" | ||
606 | + y1="12.5036" | ||
607 | + x2="53.570126" | ||
608 | + y2="47.374317" /><radialGradient | ||
609 | + inkscape:collect="always" | ||
610 | + xlink:href="#linearGradient2248" | ||
611 | + id="radialGradient3227" | ||
612 | + gradientUnits="userSpaceOnUse" | ||
613 | + gradientTransform="matrix(4.154957,0,0,3.198723,-29.818914,-1.9585976)" | ||
614 | + cx="16.75" | ||
615 | + cy="10.666344" | ||
616 | + fx="16.75" | ||
617 | + fy="10.666344" | ||
618 | + r="21.25" /><radialGradient | ||
619 | + inkscape:collect="always" | ||
620 | + xlink:href="#linearGradient9647-3" | ||
621 | + id="radialGradient3230" | ||
622 | + gradientUnits="userSpaceOnUse" | ||
623 | + gradientTransform="matrix(1.693981,0,0,1.693981,6.1613255,-3.5604976)" | ||
624 | + cx="24.30225" | ||
625 | + cy="33.30225" | ||
626 | + fx="24.30225" | ||
627 | + fy="33.30225" | ||
628 | + r="12.30225" /><linearGradient | ||
629 | + inkscape:collect="always" | ||
630 | + xlink:href="#linearGradient2256-0" | ||
631 | + id="linearGradient3232" | ||
632 | + gradientUnits="userSpaceOnUse" | ||
633 | + gradientTransform="translate(23.026616,19.550612)" | ||
634 | + x1="21.75" | ||
635 | + y1="15.80225" | ||
636 | + x2="24.30225" | ||
637 | + y2="35.05225" /><radialGradient | ||
638 | + inkscape:collect="always" | ||
639 | + xlink:href="#linearGradient21644-3" | ||
640 | + id="radialGradient3218-2" | ||
641 | + gradientUnits="userSpaceOnUse" | ||
642 | + gradientTransform="matrix(1.173803,0,0,0.3571428,17.76075,50.050612)" | ||
643 | + cx="25.125" | ||
644 | + cy="36.75" | ||
645 | + fx="25.125" | ||
646 | + fy="36.75" | ||
647 | + r="15.75" /><linearGradient | ||
648 | + inkscape:collect="always" | ||
649 | + id="linearGradient21644-3"><stop | ||
650 | + style="stop-color:#000000;stop-opacity:1;" | ||
651 | + offset="0" | ||
652 | + id="stop21646-9" /><stop | ||
653 | + style="stop-color:#000000;stop-opacity:0;" | ||
654 | + offset="1" | ||
655 | + id="stop21648-9" /></linearGradient><linearGradient | ||
656 | + inkscape:collect="always" | ||
657 | + xlink:href="#linearGradient4981-1" | ||
658 | + id="linearGradient3221-9" | ||
659 | + gradientUnits="userSpaceOnUse" | ||
660 | + gradientTransform="translate(23.026616,19.550612)" | ||
661 | + x1="23.995985" | ||
662 | + y1="20.105337" | ||
663 | + x2="41.047836" | ||
664 | + y2="37.959785" /><linearGradient | ||
665 | + id="linearGradient4981-1"><stop | ||
666 | + style="stop-color:#cc0000;stop-opacity:1;" | ||
667 | + offset="0" | ||
668 | + id="stop4983-4" /><stop | ||
669 | + style="stop-color:#b30000;stop-opacity:1.0000000;" | ||
670 | + offset="1.0000000" | ||
671 | + id="stop4985-7" /></linearGradient><linearGradient | ||
672 | + inkscape:collect="always" | ||
673 | + xlink:href="#linearGradient11780-3" | ||
674 | + id="linearGradient3224-7" | ||
675 | + gradientUnits="userSpaceOnUse" | ||
676 | + gradientTransform="translate(23.026616,19.550612)" | ||
677 | + x1="15.737001" | ||
678 | + y1="12.5036" | ||
679 | + x2="53.570126" | ||
680 | + y2="47.374317" /><linearGradient | ||
681 | + id="linearGradient11780-3"><stop | ||
682 | + style="stop-color:#ff8b8b;stop-opacity:1.0000000;" | ||
683 | + offset="0.0000000" | ||
684 | + id="stop11782-9" /><stop | ||
685 | + style="stop-color:#ec1b1b;stop-opacity:1.0000000;" | ||
686 | + offset="1.0000000" | ||
687 | + id="stop11784-6" /></linearGradient><radialGradient | ||
688 | + inkscape:collect="always" | ||
689 | + xlink:href="#linearGradient2248-9" | ||
690 | + id="radialGradient3227-6" | ||
691 | + gradientUnits="userSpaceOnUse" | ||
692 | + gradientTransform="matrix(4.154957,0,0,3.198723,-29.818914,-1.9585976)" | ||
693 | + cx="16.75" | ||
694 | + cy="10.666344" | ||
695 | + fx="16.75" | ||
696 | + fy="10.666344" | ||
697 | + r="21.25" /><linearGradient | ||
698 | + inkscape:collect="always" | ||
699 | + id="linearGradient2248-9"><stop | ||
700 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
701 | + offset="0" | ||
702 | + id="stop2250-3" /><stop | ||
703 | + style="stop-color:#ffffff;stop-opacity:0;" | ||
704 | + offset="1" | ||
705 | + id="stop2252-5" /></linearGradient><radialGradient | ||
706 | + inkscape:collect="always" | ||
707 | + xlink:href="#linearGradient9647-3-4" | ||
708 | + id="radialGradient3230-9" | ||
709 | + gradientUnits="userSpaceOnUse" | ||
710 | + gradientTransform="matrix(1.693981,0,0,1.693981,6.1613255,-3.5604976)" | ||
711 | + cx="24.30225" | ||
712 | + cy="33.30225" | ||
713 | + fx="24.30225" | ||
714 | + fy="33.30225" | ||
715 | + r="12.30225" /><linearGradient | ||
716 | + id="linearGradient9647-3-4"><stop | ||
717 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
718 | + offset="0" | ||
719 | + id="stop9649-3-2" /><stop | ||
720 | + style="stop-color:#dbdbdb;stop-opacity:1;" | ||
721 | + offset="1" | ||
722 | + id="stop9651-2-0" /></linearGradient><linearGradient | ||
723 | + inkscape:collect="always" | ||
724 | + xlink:href="#linearGradient2256-0-0" | ||
725 | + id="linearGradient3232-1" | ||
726 | + gradientUnits="userSpaceOnUse" | ||
727 | + gradientTransform="translate(23.026616,19.550612)" | ||
728 | + x1="21.75" | ||
729 | + y1="15.80225" | ||
730 | + x2="24.30225" | ||
731 | + y2="35.05225" /><linearGradient | ||
732 | + id="linearGradient2256-0-0"><stop | ||
733 | + style="stop-color:#ff0202;stop-opacity:1;" | ||
734 | + offset="0" | ||
735 | + id="stop2258-2-7" /><stop | ||
736 | + style="stop-color:#ff9b9b;stop-opacity:1;" | ||
737 | + offset="1" | ||
738 | + id="stop2260-8-0" /></linearGradient><radialGradient | ||
739 | + r="12.30225" | ||
740 | + fy="33.30225" | ||
741 | + fx="24.30225" | ||
742 | + cy="33.30225" | ||
743 | + cx="24.30225" | ||
744 | + gradientTransform="matrix(1.693981,0,0,1.693981,6.1613255,-3.5604976)" | ||
745 | + gradientUnits="userSpaceOnUse" | ||
746 | + id="radialGradient3276" | ||
747 | + xlink:href="#linearGradient9647-3-4" | ||
748 | + inkscape:collect="always" /><linearGradient | ||
749 | + y2="35.05225" | ||
750 | + x2="24.30225" | ||
751 | + y1="15.80225" | ||
752 | + x1="21.75" | ||
753 | + gradientTransform="translate(23.026616,19.550612)" | ||
754 | + gradientUnits="userSpaceOnUse" | ||
755 | + id="linearGradient3278" | ||
756 | + xlink:href="#linearGradient2256-0-0" | ||
757 | + inkscape:collect="always" /><radialGradient | ||
758 | + inkscape:collect="always" | ||
759 | + xlink:href="#linearGradient21644-3-0" | ||
760 | + id="radialGradient3218-2-4" | ||
761 | + gradientUnits="userSpaceOnUse" | ||
762 | + gradientTransform="matrix(1.173803,0,0,0.3571428,17.76075,50.050612)" | ||
763 | + cx="25.125" | ||
764 | + cy="36.75" | ||
765 | + fx="25.125" | ||
766 | + fy="36.75" | ||
767 | + r="15.75" /><linearGradient | ||
768 | + id="linearGradient21644-3-0"><stop | ||
769 | + style="stop-color:#000000;stop-opacity:1;" | ||
770 | + offset="0" | ||
771 | + id="stop21646-9-1" /><stop | ||
772 | + style="stop-color:#000000;stop-opacity:0;" | ||
773 | + offset="1" | ||
774 | + id="stop21648-9-8" /></linearGradient><linearGradient | ||
775 | + inkscape:collect="always" | ||
776 | + xlink:href="#linearGradient4981-1-6" | ||
777 | + id="linearGradient3221-9-6" | ||
778 | + gradientUnits="userSpaceOnUse" | ||
779 | + gradientTransform="translate(23.026616,19.550612)" | ||
780 | + x1="23.995985" | ||
781 | + y1="20.105337" | ||
782 | + x2="41.047836" | ||
783 | + y2="37.959785" /><linearGradient | ||
784 | + id="linearGradient4981-1-6"><stop | ||
785 | + style="stop-color:#cc0000;stop-opacity:1;" | ||
786 | + offset="0" | ||
787 | + id="stop4983-4-0" /><stop | ||
788 | + style="stop-color:#b30000;stop-opacity:1.0000000;" | ||
789 | + offset="1.0000000" | ||
790 | + id="stop4985-7-7" /></linearGradient><linearGradient | ||
791 | + inkscape:collect="always" | ||
792 | + xlink:href="#linearGradient11780-3-5" | ||
793 | + id="linearGradient3224-7-4" | ||
794 | + gradientUnits="userSpaceOnUse" | ||
795 | + gradientTransform="translate(23.026616,19.550612)" | ||
796 | + x1="15.737001" | ||
797 | + y1="12.5036" | ||
798 | + x2="53.570126" | ||
799 | + y2="47.374317" /><linearGradient | ||
800 | + id="linearGradient11780-3-5"><stop | ||
801 | + style="stop-color:#ff8b8b;stop-opacity:1.0000000;" | ||
802 | + offset="0.0000000" | ||
803 | + id="stop11782-9-4" /><stop | ||
804 | + style="stop-color:#ec1b1b;stop-opacity:1.0000000;" | ||
805 | + offset="1.0000000" | ||
806 | + id="stop11784-6-8" /></linearGradient><radialGradient | ||
807 | + inkscape:collect="always" | ||
808 | + xlink:href="#linearGradient2248-9-9" | ||
809 | + id="radialGradient3227-6-4" | ||
810 | + gradientUnits="userSpaceOnUse" | ||
811 | + gradientTransform="matrix(4.154957,0,0,3.198723,-29.818914,-1.9585976)" | ||
812 | + cx="16.75" | ||
813 | + cy="10.666344" | ||
814 | + fx="16.75" | ||
815 | + fy="10.666344" | ||
816 | + r="21.25" /><linearGradient | ||
817 | + inkscape:collect="always" | ||
818 | + id="linearGradient2248-9-9"><stop | ||
819 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
820 | + offset="0" | ||
821 | + id="stop2250-3-5" /><stop | ||
822 | + style="stop-color:#ffffff;stop-opacity:0;" | ||
823 | + offset="1" | ||
824 | + id="stop2252-5-3" /></linearGradient><radialGradient | ||
825 | + r="12.30225" | ||
826 | + fy="33.30225" | ||
827 | + fx="24.30225" | ||
828 | + cy="33.30225" | ||
829 | + cx="24.30225" | ||
830 | + gradientTransform="matrix(1.693981,0,0,1.693981,6.1613255,-3.5604976)" | ||
831 | + gradientUnits="userSpaceOnUse" | ||
832 | + id="radialGradient3276-7" | ||
833 | + xlink:href="#linearGradient9647-3-4-6" | ||
834 | + inkscape:collect="always" /><linearGradient | ||
835 | + id="linearGradient9647-3-4-6"><stop | ||
836 | + style="stop-color:#ffffff;stop-opacity:1;" | ||
837 | + offset="0" | ||
838 | + id="stop9649-3-2-7" /><stop | ||
839 | + style="stop-color:#dbdbdb;stop-opacity:1;" | ||
840 | + offset="1" | ||
841 | + id="stop9651-2-0-1" /></linearGradient><linearGradient | ||
842 | + y2="35.05225" | ||
843 | + x2="24.30225" | ||
844 | + y1="15.80225" | ||
845 | + x1="21.75" | ||
846 | + gradientTransform="translate(23.026616,19.550612)" | ||
847 | + gradientUnits="userSpaceOnUse" | ||
848 | + id="linearGradient3278-2" | ||
849 | + xlink:href="#linearGradient2256-0-0-1" | ||
850 | + inkscape:collect="always" /><linearGradient | ||
851 | + id="linearGradient2256-0-0-1"><stop | ||
852 | + style="stop-color:#ff0202;stop-opacity:1;" | ||
853 | + offset="0" | ||
854 | + id="stop2258-2-7-8" /><stop | ||
855 | + style="stop-color:#ff9b9b;stop-opacity:1;" | ||
856 | + offset="1" | ||
857 | + id="stop2260-8-0-4" /></linearGradient><radialGradient | ||
858 | + r="12.30225" | ||
859 | + fy="33.30225" | ||
860 | + fx="24.30225" | ||
861 | + cy="33.30225" | ||
862 | + cx="24.30225" | ||
863 | + gradientTransform="matrix(1.693981,0,0,1.693981,6.1613255,-3.5604976)" | ||
864 | + gradientUnits="userSpaceOnUse" | ||
865 | + id="radialGradient3812" | ||
866 | + xlink:href="#linearGradient9647-3-4-6" | ||
867 | + inkscape:collect="always" /><linearGradient | ||
868 | + y2="35.05225" | ||
869 | + x2="24.30225" | ||
870 | + y1="15.80225" | ||
871 | + x1="21.75" | ||
872 | + gradientTransform="translate(23.026616,19.550612)" | ||
873 | + gradientUnits="userSpaceOnUse" | ||
874 | + id="linearGradient3814" | ||
875 | + xlink:href="#linearGradient2256-0-0-1" | ||
876 | + inkscape:collect="always" /><radialGradient | ||
877 | + inkscape:collect="always" | ||
878 | + xlink:href="#linearGradient9647-3-4-6" | ||
879 | + id="radialGradient3886" | ||
880 | + gradientUnits="userSpaceOnUse" | ||
881 | + gradientTransform="matrix(0.85754753,0,0,0.85754753,16.064712,11.20392)" | ||
882 | + cx="24.30225" | ||
883 | + cy="33.30225" | ||
884 | + fx="24.30225" | ||
885 | + fy="33.30225" | ||
886 | + r="12.30225" /><linearGradient | ||
887 | + inkscape:collect="always" | ||
888 | + xlink:href="#linearGradient2256-0-0-1" | ||
889 | + id="linearGradient3888" | ||
890 | + gradientUnits="userSpaceOnUse" | ||
891 | + gradientTransform="matrix(0.50623208,0,0,0.50623208,24.602463,22.903505)" | ||
892 | + x1="21.75" | ||
893 | + y1="15.80225" | ||
894 | + x2="24.30225" | ||
895 | + y2="35.05225" /><radialGradient | ||
896 | + inkscape:collect="always" | ||
897 | + xlink:href="#linearGradient2248-9-9" | ||
898 | + id="radialGradient3891" | ||
899 | + gradientUnits="userSpaceOnUse" | ||
900 | + gradientTransform="matrix(2.1094827,0,0,1.5765366,-2.293898,12.776643)" | ||
901 | + cx="16.75" | ||
902 | + cy="10.666344" | ||
903 | + fx="16.75" | ||
904 | + fy="10.666344" | ||
905 | + r="21.25" /><linearGradient | ||
906 | + inkscape:collect="always" | ||
907 | + xlink:href="#linearGradient11780-3-5" | ||
908 | + id="linearGradient3894" | ||
909 | + gradientUnits="userSpaceOnUse" | ||
910 | + gradientTransform="matrix(0.50623208,0,0,0.50623208,24.602463,22.903505)" | ||
911 | + x1="15.737001" | ||
912 | + y1="12.5036" | ||
913 | + x2="53.570126" | ||
914 | + y2="47.374317" /><linearGradient | ||
915 | + inkscape:collect="always" | ||
916 | + xlink:href="#linearGradient4981-1-6" | ||
917 | + id="linearGradient3897" | ||
918 | + gradientUnits="userSpaceOnUse" | ||
919 | + gradientTransform="matrix(0.50623208,0,0,0.50623208,24.602463,22.903505)" | ||
920 | + x1="23.995985" | ||
921 | + y1="20.105337" | ||
922 | + x2="41.047836" | ||
923 | + y2="37.959785" /><radialGradient | ||
924 | + inkscape:collect="always" | ||
925 | + xlink:href="#linearGradient21644-3-0" | ||
926 | + id="radialGradient3900" | ||
927 | + gradientUnits="userSpaceOnUse" | ||
928 | + gradientTransform="matrix(0.75877044,0,0,0.21650012,17.801926,37.031146)" | ||
929 | + cx="25.125" | ||
930 | + cy="36.75" | ||
931 | + fx="25.125" | ||
932 | + fy="36.75" | ||
933 | + r="15.75" /><linearGradient | ||
934 | + inkscape:collect="always" | ||
935 | + xlink:href="#linearGradient4700" | ||
936 | + id="linearGradient4706" | ||
937 | + x1="42" | ||
938 | + y1="40.46875" | ||
939 | + x2="30.3125" | ||
940 | + y2="29.09375" | ||
941 | + gradientUnits="userSpaceOnUse" /><linearGradient | ||
942 | + inkscape:collect="always" | ||
943 | + xlink:href="#linearGradient4711" | ||
944 | + id="linearGradient4717" | ||
945 | + x1="29.3125" | ||
946 | + y1="28.25" | ||
947 | + x2="44.125" | ||
948 | + y2="42.5625" | ||
949 | + gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview | ||
950 | + inkscape:cy="18.229536" | ||
951 | + inkscape:cx="35.718843" | ||
952 | + inkscape:zoom="8" | ||
953 | + inkscape:window-height="827" | ||
954 | + inkscape:window-width="1440" | ||
955 | + inkscape:pageshadow="2" | ||
956 | + inkscape:pageopacity="0.0" | ||
957 | + borderopacity="0.21568627" | ||
958 | + bordercolor="#666666" | ||
959 | + pagecolor="#ffffff" | ||
960 | + id="base" | ||
961 | + inkscape:showpageshadow="false" | ||
962 | + inkscape:window-x="0" | ||
963 | + inkscape:window-y="0" | ||
964 | + inkscape:current-layer="layer3" | ||
965 | + fill="#555753" | ||
966 | + showgrid="false" | ||
967 | + stroke="#a40000" | ||
968 | + showguides="true" | ||
969 | + inkscape:guide-bbox="true" | ||
970 | + inkscape:window-maximized="1" /> | ||
971 | + | ||
972 | +<g | ||
973 | + inkscape:groupmode="layer" | ||
974 | + id="layer1" | ||
975 | + inkscape:label="Home" | ||
976 | + style="display:inline" | ||
977 | + sodipodi:insensitive="true"><g | ||
978 | + style="display:inline;overflow:visible" | ||
979 | + id="g3710"><g | ||
980 | + transform="matrix(0.02158196,0,0,0.01859457,43.12251,41.63767)" | ||
981 | + id="g5022" | ||
982 | + style="display:inline"><rect | ||
983 | + style="opacity:0.40206185;color:#000000;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" | ||
984 | + id="rect4173" | ||
985 | + width="1339.6335" | ||
986 | + height="478.35718" | ||
987 | + x="-1559.2523" | ||
988 | + y="-150.69685" /><path | ||
989 | + inkscape:connector-curvature="0" | ||
990 | + style="opacity:0.40206185;color:#000000;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" | ||
991 | + d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z" | ||
992 | + id="path5058" | ||
993 | + sodipodi:nodetypes="cccc" /><path | ||
994 | + inkscape:connector-curvature="0" | ||
995 | + sodipodi:nodetypes="cccc" | ||
996 | + id="path5018" | ||
997 | + d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z" | ||
998 | + style="opacity:0.40206185;color:#000000;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /></g><path | ||
999 | + inkscape:connector-curvature="0" | ||
1000 | + sodipodi:nodetypes="ccccccccc" | ||
1001 | + id="rect1512" | ||
1002 | + d="m 21.619576,8.1833733 5.957459,0 c 0.839732,0 13.886475,15.4353277 13.886475,16.3406587 l -0.443521,18.496745 c 0,0.905333 -0.67603,1.634177 -1.515762,1.634177 l -31.4572774,0 c -0.8397329,0 -1.5157625,-0.728844 -1.5157625,-1.634177 l 0.056478,-18.496745 c 0,-0.905331 14.1921789,-16.3406587 15.0319109,-16.3406587 z" | ||
1003 | + style="color:#000000;fill:url(#linearGradient1514);fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:1.0000006;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" /><path | ||
1004 | + inkscape:connector-curvature="0" | ||
1005 | + d="m 46.963575,45.735573 -45.3248988,0 0,-45.32489746 45.3248988,0 0,45.32489746 z" | ||
1006 | + id="path5" | ||
1007 | + style="fill:none" /><path | ||
1008 | + inkscape:connector-curvature="0" | ||
1009 | + sodipodi:nodetypes="ccccc" | ||
1010 | + clip-rule="evenodd" | ||
1011 | + d="m 23,29 -0.04574,15.090942 -11.842791,0 L 11,29 23,29 z" | ||
1012 | + id="path2327" | ||
1013 | + style="fill:url(#linearGradient2335);fill-opacity:1;fill-rule:evenodd" /><path | ||
1014 | + inkscape:connector-curvature="0" | ||
1015 | + style="opacity:0.3125;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" | ||
1016 | + d="m 21.780459,9.405584 5.559097,0 c 0.783582,0 13.000869,14.399588 13.000869,15.244172 l -0.347158,18.212311 c 0,0.459259 -0.143737,0.653465 -0.512375,0.653465 l -31.3872026,0.01428 c -0.3686377,0 -0.5839636,-0.07992 -0.5839636,-0.45355 L 7.7250676,24.649756 c 0,-0.844584 13.2718124,-15.244172 14.0553914,-15.244172 z" | ||
1017 | + id="path2357" | ||
1018 | + sodipodi:nodetypes="ccccccccc" /><path | ||
1019 | + inkscape:connector-curvature="0" | ||
1020 | + sodipodi:nodetypes="ccccccc" | ||
1021 | + style="opacity:0.2;fill:url(#radialGradient2384);fill-opacity:1;fill-rule:evenodd" | ||
1022 | + id="path23" | ||
1023 | + d="M 7.2075295,27.943053 7.1532728,30.538247 25.521437,17.358993 40.807832,28.513421 40.879142,28.201707 24.508686,12.297576 7.2075295,27.943053 z" | ||
1024 | + clip-rule="evenodd" /><path | ||
1025 | + inkscape:connector-curvature="0" | ||
1026 | + sodipodi:nodetypes="ccccc" | ||
1027 | + style="fill:url(#linearGradient2412);fill-opacity:1;fill-rule:evenodd" | ||
1028 | + id="path188" | ||
1029 | + d="m 22,30 0,14.090942 -9.811029,0 L 12,30 22,30 z" | ||
1030 | + clip-rule="evenodd" /><path | ||
1031 | + inkscape:connector-curvature="0" | ||
1032 | + clip-rule="evenodd" | ||
1033 | + d="m 19.576856,36.44767 c 0.67279,0 1.216616,0.474605 1.216616,1.058507 0,0.589811 -0.543826,1.068355 -1.216616,1.068355 -0.672272,0 -1.218686,-0.478544 -1.218686,-1.068355 5.15e-4,-0.583902 0.546414,-1.058507 1.218686,-1.058507 z" | ||
1034 | + id="path2315" | ||
1035 | + style="opacity:0.40909089;fill:url(#radialGradient2325);fill-opacity:1;fill-rule:evenodd" /><path | ||
1036 | + inkscape:connector-curvature="0" | ||
1037 | + style="fill:url(#radialGradient2313);fill-opacity:1;fill-rule:evenodd" | ||
1038 | + id="path217" | ||
1039 | + d="m 19.462314,35.932229 c 0.672789,0 1.216615,0.474605 1.216615,1.058507 0,0.589809 -0.543826,1.068353 -1.216615,1.068353 -0.672273,0 -1.218687,-0.478544 -1.218687,-1.068353 5.15e-4,-0.583902 0.546414,-1.058507 1.218687,-1.058507 z" | ||
1040 | + clip-rule="evenodd" /><path | ||
1041 | + inkscape:connector-curvature="0" | ||
1042 | + sodipodi:nodetypes="ccccccccccccc" | ||
1043 | + style="fill:url(#XMLID_39_)" | ||
1044 | + id="path342" | ||
1045 | + d="m 24.447748,11.559337 18.92706,17.169868 0.494679,0.391991 0.403676,-0.171385 -0.37287,-0.761673 L 43.622679,27.964702 24.447748,12.392396 5.0582327,28.135731 4.8206309,28.279851 4.603921,28.986637 5.0373408,29.115885 5.4218948,28.807462 24.447748,11.559337 z" /><path | ||
1046 | + inkscape:connector-curvature="0" | ||
1047 | + sodipodi:nodetypes="cccccccccc" | ||
1048 | + d="M 24.330168,2.2713382 2.4484294,20.372675 1.8237005,27.538603 3.8236367,29.602926 c 0,0 20.4073813,-17.157285 20.6240933,-17.327963 L 44.08027,29.818223 45.978694,27.494226 44.362903,20.382852 24.44773,2.1668788 24.330168,2.2713382 z" | ||
1049 | + id="path362" | ||
1050 | + style="fill:#ef2929;stroke:#a40000" /><path | ||
1051 | + inkscape:connector-curvature="0" | ||
1052 | + sodipodi:nodetypes="ccccc" | ||
1053 | + id="path1536" | ||
1054 | + d="M 2.8413446,20.613129 2.5497894,27.236494 24.369219,8.980075 24.298891,3.0867443 2.8413446,20.613129 z" | ||
1055 | + style="opacity:0.40909089;color:#000000;fill:url(#radialGradient2305);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /><path | ||
1056 | + inkscape:connector-curvature="0" | ||
1057 | + style="opacity:0.13636367;color:#000000;fill:url(#radialGradient2339);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" | ||
1058 | + d="M 24.483763,8.7509884 24.583223,2.9098867 43.912186,20.56184 45.403998,27.062652 24.483763,8.7509884 z" | ||
1059 | + id="path2337" | ||
1060 | + sodipodi:nodetypes="ccccc" /><path | ||
1061 | + inkscape:connector-curvature="0" | ||
1062 | + sodipodi:nodetypes="ccccccccc" | ||
1063 | + id="rect2361" | ||
1064 | + d="m 27.102228,27.719824 9.039995,0 c 0.770595,0 1.390967,0.62037 1.390967,1.390967 l -0.008,9.079221 c 0,0.770596 -0.596322,1.265969 -1.366918,1.265969 l -9.056083,0 c -0.770597,0 -1.390967,-0.620373 -1.390967,-1.390969 l 0,-8.954221 c 0,-0.770597 0.62037,-1.390967 1.390967,-1.390967 z" | ||
1065 | + style="opacity:0.31818183;color:#000000;fill:none;stroke:#ffffff;stroke-width:0.99999934;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" /><rect | ||
1066 | + ry="0.38128215" | ||
1067 | + rx="0.38128215" | ||
1068 | + y="28.514256" | ||
1069 | + x="26.507767" | ||
1070 | + height="9.9624557" | ||
1071 | + width="10.001333" | ||
1072 | + id="rect3263" | ||
1073 | + style="color:#000000;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:0.9999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" /><path | ||
1074 | + inkscape:connector-curvature="0" | ||
1075 | + sodipodi:nodetypes="ccccc" | ||
1076 | + id="rect2363" | ||
1077 | + d="m 27.107118,34.408261 c 3.617983,0.331177 5.527724,-1.445704 8.868152,-1.55274 L 36,29.00603 27.088388,29 l 0.01873,5.408261 z" | ||
1078 | + style="opacity:0.39772728;color:#000000;fill:url(#radialGradient2374);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999958;marker:none;visibility:visible;display:inline;overflow:visible" /></g></g><g | ||
1079 | + inkscape:groupmode="layer" | ||
1080 | + id="layer3" | ||
1081 | + inkscape:label="Cancel" | ||
1082 | + style="display:inline" | ||
1083 | + sodipodi:insensitive="true"><path | ||
1084 | + inkscape:connector-curvature="0" | ||
1085 | + id="path21642-1" | ||
1086 | + d="m 47.662816,44.987526 c -0.120652,1.646851 -3.213412,2.606775 -5.88153,3.03684 -4.362088,0.658404 -9.413,0.503003 -13.246573,-0.867841 -2.049624,-0.673315 -3.29125,-2.200566 -1.810314,-3.341428 2.178762,-1.659613 6.251742,-2.183438 9.862965,-2.236334 3.69133,-0.006 7.82464,0.471868 10.226986,2.081485 0.520681,0.38489 0.853108,0.849828 0.848466,1.327278 z" | ||
1087 | + style="opacity:0.63068183;color:#000000;fill:url(#radialGradient3900);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /><rect | ||
1088 | + style="fill:url(#linearGradient4706);fill-opacity:1;fill-rule:nonzero;stroke:#850000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1089 | + id="rect4692" | ||
1090 | + width="21.625" | ||
1091 | + height="21.9375" | ||
1092 | + x="25.9375" | ||
1093 | + y="24.0625" | ||
1094 | + rx="0.38128215" | ||
1095 | + ry="0.38128215" /><rect | ||
1096 | + style="fill:none;stroke:url(#linearGradient4717);stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;overflow:visible" | ||
1097 | + id="rect4709" | ||
1098 | + width="20.875" | ||
1099 | + height="21" | ||
1100 | + x="26.3125" | ||
1101 | + y="24.5625" | ||
1102 | + rx="0.38128215" | ||
1103 | + ry="0.38128215" /><path | ||
1104 | + style="fill:#cc2e2e;fill-opacity:0.89138579;stroke:none;display:inline;overflow:visible" | ||
1105 | + d="m 26.4375,24.8125 20.625,0.125 L 47,39.4375 C 41.4375,36.625 39.859375,37.3125 37.195313,37.765625 35.025662,38.134656 32.65625,40.125 26.5,39.625 z" | ||
1106 | + id="rect4720" | ||
1107 | + inkscape:connector-curvature="0" | ||
1108 | + sodipodi:nodetypes="cccscc" /><path | ||
1109 | + inkscape:connector-curvature="0" | ||
1110 | + id="path2787-5" | ||
1111 | + d="m 33.090545,29.231406 c -0.720061,0.72006 -1.440121,1.44012 -2.160181,2.160181 1.271499,1.271499 2.542997,2.542997 3.814496,3.814497 -1.271499,1.271499 -2.542997,2.542997 -3.814496,3.814496 0.72006,0.720061 1.44012,1.440121 2.160181,2.160182 1.271499,-1.271499 2.542997,-2.542999 3.814496,-3.814498 1.271499,1.271499 2.542998,2.542999 3.814497,3.814498 0.72006,-0.720061 1.440121,-1.440121 2.160181,-2.160182 -1.271499,-1.271499 -2.542998,-2.542997 -3.814497,-3.814496 1.271499,-1.2715 2.542998,-2.542998 3.814497,-3.814497 -0.72006,-0.720061 -1.440121,-1.440121 -2.160181,-2.160181 -1.271499,1.271499 -2.542998,2.542998 -3.814497,3.814497 -1.271499,-1.271499 -2.542997,-2.542998 -3.814496,-3.814497 z" | ||
1112 | + style="fill:url(#radialGradient3886);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3888);stroke-width:0.50623184;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;overflow:visible" /></g></svg> | ||
0 | \ No newline at end of file | 1113 | \ No newline at end of file |
public/designs/icons/tango/style.css
1 | -@import url(ie6.css); | ||
2 | - | ||
3 | /******************SMALL ICONS********************/ | 1 | /******************SMALL ICONS********************/ |
4 | .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) } | 2 | .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) } |
5 | .icon-home { background-image: url(Tango/16x16/actions/go-home.png) } | 3 | .icon-home { background-image: url(Tango/16x16/actions/go-home.png) } |
4 | +.icon-home-not { background-image: url(mod/16x16/actions/go-home-not.png) } | ||
6 | .icon-new, | 5 | .icon-new, |
7 | -.icon-suggest { background-image: url(Tango/16x16/actions/filenew.png) } | ||
8 | -.icon-close { background-image: url(Tango/16x16/actions/gtk-cancel.png) } | 6 | +.icon-suggest { background-image: url(Tango/16x16/actions/filenew.png) } |
7 | +.icon-close { background-image: url(Tango/16x16/actions/gtk-cancel.png) } | ||
9 | .icon-newfolder { background-image: url(Tango/16x16/actions/folder-new.png) } | 8 | .icon-newfolder { background-image: url(Tango/16x16/actions/folder-new.png) } |
10 | .icon-folder { background-image: url(Tango/16x16/places/folder.png) } | 9 | .icon-folder { background-image: url(Tango/16x16/places/folder.png) } |
11 | -.icon-parent-folder { background-image: url(Tango/16x16/places/folder_home.png) } | 10 | +.icon-parent-folder { background-image: url(Tango/16x16/places/folder_home.png) } |
12 | .icon-newblog { background-image: url(mod/16x16/apps/text-editor.png) } | 11 | .icon-newblog { background-image: url(mod/16x16/apps/text-editor.png) } |
13 | .icon-blog { background-image: url(mod/16x16/apps/text-editor.png) } | 12 | .icon-blog { background-image: url(mod/16x16/apps/text-editor.png) } |
14 | -/*.icon-open { background-image: url(folder-open.gif) } UNUSED*/ | ||
15 | -/*.icon-cms { background-image: url(abiword_48.png) } UNUSED*/ | ||
16 | -.icon-save { background-image: url(Tango/16x16/actions/filesave.png) } | ||
17 | -.icon-send { background-image: url(Tango/16x16/actions/stock_mail-forward.png) } | ||
18 | -.icon-cancel { background-image: url(Tango/16x16/actions/gtk-cancel.png) } | ||
19 | -.icon-person { background-image: url(Tango/16x16/apps/system-config-users.png) } | ||
20 | -.icon-product { background-image: url(Tango/16x16/mimetypes/package.png) } | 13 | +/*.icon-open { background-image: url(folder-open.gif) } UNUSED*/ |
14 | +/*.icon-cms { background-image: url(abiword_48.png) } UNUSED*/ | ||
15 | +.icon-save { background-image: url(Tango/16x16/actions/filesave.png) } | ||
16 | +.icon-send { background-image: url(Tango/16x16/actions/stock_mail-forward.png) } | ||
17 | +.icon-cancel { background-image: url(Tango/16x16/actions/gtk-cancel.png) } | ||
18 | +.icon-person { background-image: url(Tango/16x16/apps/system-config-users.png) } | ||
19 | +.icon-product { background-image: url(Tango/16x16/mimetypes/package.png) } | ||
21 | .icon-delete { background-image: url(Tango/16x16/places/user-trash.png) } | 20 | .icon-delete { background-image: url(Tango/16x16/places/user-trash.png) } |
22 | -/*.icon-find { background-image: url(noosfero-find.png) } UNUSED*/ | ||
23 | -.icon-back { background-image: url(Tango/16x16/actions/back.png) } | ||
24 | -.icon-next { background-image: url(Tango/16x16/actions/go-next.png) } | ||
25 | -.icon-add { background-image: url(Tango/16x16/actions/add.png) } | ||
26 | -.icon-remove { background-image: url(Tango/16x16/actions/gtk-remove.png) } | ||
27 | -.icon-more { background-image: url(Tango/16x16/actions/add.png) } | ||
28 | -.icon-up { background-image: url(Tango/16x16/actions/go-up.png) } | ||
29 | -.icon-down { background-image: url(Tango/16x16/actions/go-down.png) } | ||
30 | -.icon-left { background-image: url(Tango/16x16/actions/go-previous.png) } | ||
31 | -.icon-right { background-image: url(Tango/16x16/actions/go-next.png) } | ||
32 | -.icon-up-disabled { background-image: url(Tango/16x16/actions/go-up.png); opacity: 0.25; filter:alpha(opacity=25); } | ||
33 | -.icon-down-disabled { background-image: url(Tango/16x16/actions/go-down.png); opacity: 0.25; filter:alpha(opacity=25); } | ||
34 | -.icon-left-disabled { background-image: url(Tango/16x16/actions/go-previous.png); opacity: 0.25; filter:alpha(opacity=25); } | ||
35 | -.icon-right-disabled { background-image: url(Tango/16x16/actions/go-next.png); opacity: 0.25; filter:alpha(opacity=25); } | ||
36 | -.icon-up-red { background-image: url(mod/16x16/actions/go-up-red.png) } | ||
37 | -.icon-forward { background-image: url(Tango/16x16/actions/go-next.png) } | ||
38 | -.icon-search { background-image: url(Tango/16x16/actions/search.png) } | ||
39 | -.icon-ok { background-image: url(Tango/16x16/actions/media-playback-start.png) } | ||
40 | -.icon-login { background-image: url(mod/16x16/actions/log-in.png) } | ||
41 | -.icon-help { background-image: url(Tango/16x16/apps/gnome-help.png) } | ||
42 | -.icon-firefox { background-image: url(firefox-24x24.gif) } | ||
43 | -.icon-help32on { background-image: url(Tango/32x32/apps/gnome-help.png) } | ||
44 | -.icon-help32off { background-image: url(mod/32x32/apps/gnome-help-red.png) } | 21 | +/*.icon-find { background-image: url(noosfero-find.png) } UNUSED*/ |
22 | +.icon-back { background-image: url(Tango/16x16/actions/back.png) } | ||
23 | +.icon-next { background-image: url(Tango/16x16/actions/go-next.png) } | ||
24 | +.icon-add { background-image: url(Tango/16x16/actions/add.png) } | ||
25 | +.icon-remove { background-image: url(Tango/16x16/actions/gtk-remove.png) } | ||
26 | +.icon-more { background-image: url(Tango/16x16/actions/add.png) } | ||
27 | +.icon-up { background-image: url(Tango/16x16/actions/go-up.png) } | ||
28 | +.icon-down { background-image: url(Tango/16x16/actions/go-down.png) } | ||
29 | +.icon-left { background-image: url(Tango/16x16/actions/go-previous.png) } | ||
30 | +.icon-right { background-image: url(Tango/16x16/actions/go-next.png) } | ||
31 | +.icon-up-disabled { background-image: url(Tango/16x16/actions/go-up.png); opacity: 0.25; filter:alpha(opacity=25); } | ||
32 | +.icon-down-disabled { background-image: url(Tango/16x16/actions/go-down.png); opacity: 0.25; filter:alpha(opacity=25); } | ||
33 | +.icon-left-disabled { background-image: url(Tango/16x16/actions/go-previous.png); opacity: 0.25; filter:alpha(opacity=25); } | ||
34 | +.icon-right-disabled { background-image: url(Tango/16x16/actions/go-next.png); opacity: 0.25; filter:alpha(opacity=25); } | ||
35 | +.icon-up-red { background-image: url(mod/16x16/actions/go-up-red.png) } | ||
36 | +.icon-forward { background-image: url(Tango/16x16/actions/go-next.png) } | ||
37 | +.icon-search { background-image: url(Tango/16x16/actions/search.png) } | ||
38 | +.icon-ok { background-image: url(Tango/16x16/actions/media-playback-start.png) } | ||
39 | +.icon-login { background-image: url(mod/16x16/actions/log-in.png) } | ||
40 | +.icon-help { background-image: url(Tango/16x16/apps/gnome-help.png) } | ||
41 | +.icon-firefox { background-image: url(firefox-24x24.gif) } | ||
42 | +.icon-help32on { background-image: url(Tango/32x32/apps/gnome-help.png) } | ||
43 | +.icon-help32off { background-image: url(mod/32x32/apps/gnome-help-red.png) } | ||
45 | .icon-spread { background-image: url(mod/16x16/actions/spread.png) } | 44 | .icon-spread { background-image: url(mod/16x16/actions/spread.png) } |
46 | -.icon-todo { background-image: url(Tango/16x16/actions/stock_paste.png) } | ||
47 | -.icon-eyes { background-image: url(Tango/16x16/actions/gtk-print-preview.png) } | ||
48 | -/*.icon-menu- { background-image: url(menu-without-ico-HC.gif) }*/ | ||
49 | -.icon-menu-home { background-image: url(Tango/16x16/actions/go-home.png) } | ||
50 | -/*.icon-menu-blog { background-image: url(blog-HC.gif) } UNUSED*/ | ||
51 | -/*.icon-menu-album { background-image: url(album-HC.gif) } UNUSED*/ | ||
52 | -.icon-menu-product { background-image: url(Tango/16x16/mimetypes/package.png) } | ||
53 | -.icon-menu-enterprise { background-image: url(Tango/16x16/actions/go-home.png) } | ||
54 | -.icon-menu-community { background-image: url(Tango/16x16/apps/system-config-users.png) } | ||
55 | -/*.icon-menu-edit { background-image: url(edit-HC.gif) } UNUSED */ | ||
56 | -.icon-menu-ctrl-panel { background-image: url(Tango/16x16/categories/preferences-desktop.png) } | ||
57 | -.icon-menu-admin { background-image: url(Tango/16x16/categories/preferences-system.png) } | ||
58 | -.icon-menu-my-groups { background-image: url(Tango/16x16/apps/system-config-users.png) } | ||
59 | -.icon-menu-login { background-image: url(mod/16x16/actions/log-in.png) } | ||
60 | -.icon-menu-logout { background-image: url(mod/16x16/actions/log-out.png) } | ||
61 | -.icon-menu-search { background-image: url(Tango/16x16/actions/search.png) } | ||
62 | -/*.icon-menu-ed-design { background-image: url(edit-design-HC.gif) } UNUSED */ | ||
63 | -.icon-menu-events { background-image: url(Tango/16x16/mimetypes/stock_calendar.png) } | ||
64 | -.icon-event { background-image: url(Tango/16x16/mimetypes/stock_calendar.png) } | ||
65 | -.icon-newevent { background-image: url(Tango/16x16/mimetypes/stock_calendar.png) } | ||
66 | -.icon-menu-articles { background-image: url(Tango/16x16/apps/text-editor.png) } | ||
67 | -/*.icon-menu-comments { background-image: url(blog-HC.gif) } UNUSED */ | ||
68 | -.icon-menu-people { background-image: url(mod/16x16/apps/user.png) } | ||
69 | -.icon-menu-mail { background-image: url(Tango/16x16/apps/email.png) } | ||
70 | -.icon-upload-file { background-image: url(Tango/16x16/actions/filesave.png) } | ||
71 | -.icon-newupload-file { background-image: url(Tango/16x16/actions/filesave.png) } | ||
72 | -.icon-slideshow { background-image: url(Tango/16x16/mimetypes/x-office-presentation.png) } | 45 | +.icon-todo { background-image: url(Tango/16x16/actions/stock_paste.png) } |
46 | +.icon-eyes { background-image: url(Tango/16x16/actions/find.png) } | ||
47 | +/*.icon-menu- { background-image: url(menu-without-ico-HC.gif) }*/ | ||
48 | +.icon-menu-home { background-image: url(Tango/16x16/actions/go-home.png) } | ||
49 | +/*.icon-menu-blog { background-image: url(blog-HC.gif) } UNUSED*/ | ||
50 | +/*.icon-menu-album { background-image: url(album-HC.gif) } UNUSED*/ | ||
51 | +.icon-menu-product { background-image: url(Tango/16x16/mimetypes/package.png) } | ||
52 | +.icon-menu-enterprise { background-image: url(Tango/16x16/actions/go-home.png) } | ||
53 | +.icon-menu-community { background-image: url(Tango/16x16/apps/system-config-users.png) } | ||
54 | +/*.icon-menu-edit { background-image: url(edit-HC.gif) } UNUSED */ | ||
55 | +.icon-menu-ctrl-panel { background-image: url(Tango/16x16/categories/preferences-desktop.png) } | ||
56 | +.icon-menu-admin { background-image: url(Tango/16x16/categories/preferences-system.png) } | ||
57 | +.icon-menu-my-groups { background-image: url(Tango/16x16/apps/system-config-users.png) } | ||
58 | +.icon-menu-login { background-image: url(mod/16x16/actions/log-in.png) } | ||
59 | +.icon-menu-logout { background-image: url(mod/16x16/actions/log-out.png) } | ||
60 | +.icon-menu-search { background-image: url(Tango/16x16/actions/search.png) } | ||
61 | +/*.icon-menu-ed-design { background-image: url(edit-design-HC.gif) } UNUSED */ | ||
62 | +.icon-menu-events { background-image: url(Tango/16x16/mimetypes/stock_calendar.png) } | ||
63 | +.icon-event { background-image: url(Tango/16x16/mimetypes/stock_calendar.png) } | ||
64 | +.icon-newevent { background-image: url(Tango/16x16/mimetypes/stock_calendar.png) } | ||
65 | +.icon-menu-articles { background-image: url(Tango/16x16/apps/text-editor.png) } | ||
66 | +/*.icon-menu-comments { background-image: url(blog-HC.gif) } UNUSED */ | ||
67 | +.icon-menu-people { background-image: url(mod/16x16/apps/user.png) } | ||
68 | +.icon-menu-mail { background-image: url(Tango/16x16/apps/email.png) } | ||
69 | +.icon-upload-file { background-image: url(Tango/16x16/actions/filesave.png) } | ||
70 | +.icon-newupload-file { background-image: url(Tango/16x16/actions/filesave.png) } | ||
71 | +.icon-slideshow { background-image: url(Tango/16x16/mimetypes/x-office-presentation.png) } | ||
73 | .icon-photos { background-image: url(Tango/16x16/devices/camera-photo.png) } | 72 | .icon-photos { background-image: url(Tango/16x16/devices/camera-photo.png) } |
74 | 73 | ||
75 | -.icon-text-html { background-image: url(Tango/16x16/mimetypes/text-html.png) } | 74 | +.icon-text-html { background-image: url(Tango/16x16/mimetypes/text-html.png) } |
76 | .icon-text-plain { background-image: url(Tango/16x16/mimetypes/text-x-generic.png) } | 75 | .icon-text-plain { background-image: url(Tango/16x16/mimetypes/text-x-generic.png) } |
77 | -.icon-image-svg-xml { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } | 76 | +.icon-image-svg-xml { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } |
78 | .icon-application-octet-stream { background-image: url(Tango/16x16/mimetypes/binary.png) } | 77 | .icon-application-octet-stream { background-image: url(Tango/16x16/mimetypes/binary.png) } |
79 | -.icon-application-x-gzip { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-x-gzip.png) } | ||
80 | -.icon-application-postscript { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-postscript.png) } | ||
81 | -.icon-application-pdf { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-pdf.png) } | ||
82 | -.icon-application-ogg { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-ogg.png) } | ||
83 | -.icon-video-mpeg { background-image: url(Tango/16x16/mimetypes/video-x-generic.png) } | ||
84 | -.icon-application-vnd-oasis-opendocument-text { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.text.png) } | 78 | +.icon-application-x-gzip { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-x-gzip.png) } |
79 | +.icon-application-postscript { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-postscript.png) } | ||
80 | +.icon-application-pdf { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-pdf.png) } | ||
81 | +.icon-application-ogg { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-ogg.png) } | ||
82 | +.icon-video, .icon-video-mpeg { background-image: url(Tango/16x16/mimetypes/video-x-generic.png) } | ||
83 | +.icon-application-vnd-oasis-opendocument-text { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.text.png) } | ||
85 | .icon-application-vnd-oasis-opendocument-spreadsheet { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.spreadsheet.png) } | 84 | .icon-application-vnd-oasis-opendocument-spreadsheet { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.spreadsheet.png) } |
86 | -.icon-application-vnd-oasis-opendocument-presentation { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.presentation.png) } | 85 | +.icon-application-vnd-oasis-opendocument-presentation { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.presentation.png) } |
87 | 86 | ||
88 | -.icon-media-pause { background-image: url(Tango/16x16/actions/media-playback-pause.png) } | ||
89 | -.icon-media-play { background-image: url(Tango/16x16/actions/media-playback-start.png) } | ||
90 | -.icon-media-prev { background-image: url(Tango/16x16/actions/media-skip-backward.png) } | ||
91 | -.icon-media-next { background-image: url(Tango/16x16/actions/media-skip-forward.png) } | 87 | +.icon-media-pause { background-image: url(Tango/16x16/actions/media-playback-pause.png) } |
88 | +.icon-media-play { background-image: url(Tango/16x16/actions/media-playback-start.png) } | ||
89 | +.icon-media-prev { background-image: url(Tango/16x16/actions/media-skip-backward.png) } | ||
90 | +.icon-media-next { background-image: url(Tango/16x16/actions/media-skip-forward.png) } | ||
92 | .icon-lock { background-image: url(Tango/16x16/actions/lock.png) } | 91 | .icon-lock { background-image: url(Tango/16x16/actions/lock.png) } |
93 | -.icon-chat { background-image: url(Tango/16x16/apps/internet-group-chat.png); background-repeat: no-repeat } | ||
94 | -.icon-reply { background-image: url(Tango/16x16/actions/mail-reply-sender.png) } | ||
95 | -.icon-newforum { background-image: url(Tango/16x16/apps/internet-group-chat.png) } | ||
96 | -.icon-forum { background-image: url(Tango/16x16/apps/system-users.png) } | ||
97 | -.icon-gallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } | 92 | +.icon-chat { background-image: url(Tango/16x16/apps/internet-group-chat.png); background-repeat: no-repeat } |
93 | +.icon-reply { background-image: url(Tango/16x16/actions/mail-reply-sender.png) } | ||
94 | +.icon-newforum { background-image: url(Tango/16x16/apps/internet-group-chat.png) } | ||
95 | +.icon-forum { background-image: url(Tango/16x16/apps/system-users.png) } | ||
96 | +.icon-gallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } | ||
98 | .icon-newgallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } | 97 | .icon-newgallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } |
99 | -.icon-locale { background-image: url(Tango/16x16/apps/preferences-desktop-locale.png) } | ||
100 | -.icon-user-removed { background-image: url(Tango/16x16/actions/gtk-cancel.png) } | ||
101 | -.icon-user-unknown { background-image: url(Tango/16x16/status/dialog-error.png) } | ||
102 | -.icon-alert { background-image: url(Tango/16x16/status/dialog-warning.png) } | 98 | +.icon-locale { background-image: url(Tango/16x16/apps/preferences-desktop-locale.png) } |
99 | +.icon-user-removed { background-image: url(Tango/16x16/actions/gtk-cancel.png) } | ||
100 | +.icon-user-unknown { background-image: url(Tango/16x16/status/dialog-error.png) } | ||
101 | +.icon-alert { background-image: url(Tango/16x16/status/dialog-warning.png) } | ||
103 | 102 | ||
104 | /******************LARGE ICONS********************/ | 103 | /******************LARGE ICONS********************/ |
105 | -.image-gallery-item .folder { background-image: url(mod/96x96/places/folder.png) } | ||
106 | -.image-gallery-item .gallery { background-image: url(mod/96x96/mimetypes/image-x-generic.png) } | 104 | +.image-gallery-item .folder { background-image: url(mod/96x96/places/folder.png) } |
105 | +.image-gallery-item .gallery { background-image: url(mod/96x96/mimetypes/image-x-generic.png) } |
public/designs/themes/base/style.css
@@ -89,7 +89,7 @@ body, th, td, input { | @@ -89,7 +89,7 @@ body, th, td, input { | ||
89 | color: #555753; | 89 | color: #555753; |
90 | } | 90 | } |
91 | 91 | ||
92 | -#controlpanel, #logout, #openchat, #manage-enterprises { | 92 | +#controlpanel, #logout, #openchat, .manage-groups { |
93 | margin-left: 25px; | 93 | margin-left: 25px; |
94 | } | 94 | } |
95 | 95 | ||
@@ -822,12 +822,6 @@ div#notice { | @@ -822,12 +822,6 @@ div#notice { | ||
822 | margin-bottom: 0px; | 822 | margin-bottom: 0px; |
823 | } | 823 | } |
824 | 824 | ||
825 | -X.sep { | ||
826 | - background: url(imgs/blog-sep.png) 50% 50% repeat-x; | ||
827 | - padding: 10px 20px; | ||
828 | - margin: 10px -19px; | ||
829 | -} | ||
830 | - | ||
831 | /* ==> search-results.css <== */ | 825 | /* ==> search-results.css <== */ |
832 | 826 | ||
833 | 827 | ||
@@ -1019,6 +1013,46 @@ hr.pre-posts, hr.sep-posts { | @@ -1019,6 +1013,46 @@ hr.pre-posts, hr.sep-posts { | ||
1019 | background: transparent; | 1013 | background: transparent; |
1020 | } | 1014 | } |
1021 | 1015 | ||
1016 | +/************* uploaded file *****************/ | ||
1017 | + | ||
1018 | +#article .gallery-navigation { | ||
1019 | + padding: 10px 0; | ||
1020 | +} | ||
1021 | + | ||
1022 | +#article .gallery-navigation .previous { | ||
1023 | + margin-right: 10px; | ||
1024 | +} | ||
1025 | + | ||
1026 | +#article .gallery-navigation .next { | ||
1027 | + margin-left: 10px; | ||
1028 | +} | ||
1029 | + | ||
1030 | +#article .gallery-navigation .total-of-images { | ||
1031 | + font-weight: bold; | ||
1032 | +} | ||
1033 | + | ||
1034 | +#article .uploaded-file-description { | ||
1035 | + background: #f6f6f6; | ||
1036 | + border-top: 1px solid #ccc; | ||
1037 | + border-bottom: 1px solid #ccc; | ||
1038 | + padding: 1em; | ||
1039 | +} | ||
1040 | +#article .uploaded-file-description.empty { | ||
1041 | + display: none; | ||
1042 | +} | ||
1043 | + | ||
1044 | +#article.file-generic .download-link { | ||
1045 | + display: block; | ||
1046 | + margin-bottom: 10px; | ||
1047 | +} | ||
1048 | +#article.file-generic .download-link span { | ||
1049 | + font-size: 150%; | ||
1050 | + padding-right: 5px; | ||
1051 | +} | ||
1052 | +#article.file-generic .download-link a { | ||
1053 | + font-size: 180%; | ||
1054 | + text-decoration: none; | ||
1055 | +} | ||
1022 | 1056 | ||
1023 | /**************************** Comments *******************************/ | 1057 | /**************************** Comments *******************************/ |
1024 | 1058 |
public/javascripts/application.js
@@ -709,7 +709,7 @@ jQuery(function($) { | @@ -709,7 +709,7 @@ jQuery(function($) { | ||
709 | document.location.href = this.href; | 709 | document.location.href = this.href; |
710 | }) | 710 | }) |
711 | } | 711 | } |
712 | - $('#manage-enterprises-link').live('click', function() { | 712 | + $('.manage-groups > a').live('click', function() { |
713 | toggleMenu(this); | 713 | toggleMenu(this); |
714 | return false; | 714 | return false; |
715 | }); | 715 | }); |
@@ -853,6 +853,12 @@ Array.min = function(array) { | @@ -853,6 +853,12 @@ Array.min = function(array) { | ||
853 | return Math.min.apply(Math, array); | 853 | return Math.min.apply(Math, array); |
854 | }; | 854 | }; |
855 | 855 | ||
856 | +function hideAndGetUrl(link) { | ||
857 | + link.hide(); | ||
858 | + url = jQuery(link).attr('href'); | ||
859 | + jQuery.get(url); | ||
860 | +} | ||
861 | + | ||
856 | jQuery(function($){ | 862 | jQuery(function($){ |
857 | $('.submit-with-keypress').live('keydown', function(e) { | 863 | $('.submit-with-keypress').live('keydown', function(e) { |
858 | field = this; | 864 | field = this; |
@@ -875,12 +881,21 @@ jQuery(function($){ | @@ -875,12 +881,21 @@ jQuery(function($){ | ||
875 | } | 881 | } |
876 | }); | 882 | }); |
877 | 883 | ||
878 | - $('.view-all-comments').live('click', function(e) { | ||
879 | - var link = this; | ||
880 | - $(link).parent().find('.profile-wall-activities-comments').show(); | ||
881 | - $(link).hide(); | 884 | + $('#content').delegate( '.view-all-comments a', 'click', function(e) { |
885 | + hideAndGetUrl(this); | ||
882 | return false; | 886 | return false; |
887 | + }); | ||
888 | + | ||
889 | + $('#content').delegate('.view-more-replies a', 'click', function(e) { | ||
890 | + hideAndGetUrl(this); | ||
891 | + return false; | ||
883 | }); | 892 | }); |
893 | + | ||
894 | + $('#content').delegate('.view-more-comments a', 'click', function(e) { | ||
895 | + hideAndGetUrl(this); | ||
896 | + return false; | ||
897 | + }); | ||
898 | + | ||
884 | $('.focus-on-comment').live('click', function(e) { | 899 | $('.focus-on-comment').live('click', function(e) { |
885 | var link = this; | 900 | var link = this; |
886 | $(link).parents('.profile-activity-item').find('textarea').focus(); | 901 | $(link).parents('.profile-activity-item').find('textarea').focus(); |
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +function removeTaskBox(button, url, task_box_id, msg) { | ||
2 | + var $ = jQuery; | ||
3 | + if (msg && !confirm(msg)) { | ||
4 | + return; | ||
5 | + } | ||
6 | + button = $(button); | ||
7 | + button.addClass('task-button-loading'); | ||
8 | + $.post(url, function (data) { | ||
9 | + if (data.ok) { | ||
10 | + $('#' + task_box_id).slideUp(); | ||
11 | + } else { | ||
12 | + button.removeClass('task-button-loading'); | ||
13 | + button.addClass('task-button-failure'); | ||
14 | + } | ||
15 | + }); | ||
16 | +} | ||
17 | + | ||
18 | +function toggleDetails(link, msg_hide, msg_show) { | ||
19 | + var $ = jQuery; | ||
20 | + $(link).toggleClass('icon-up icon-down'); | ||
21 | + details = $(link).closest('.task_box').find('.suggest-article-details'); | ||
22 | + if (details.css('display') == 'none') { | ||
23 | + link.innerHTML = msg_hide; | ||
24 | + } else { | ||
25 | + link.innerHTML = msg_show; | ||
26 | + } | ||
27 | + details.slideToggle(); | ||
28 | +} |
public/stylesheets/application.css
@@ -882,6 +882,40 @@ code input { | @@ -882,6 +882,40 @@ code input { | ||
882 | .webkit #manage-enterprises .simplemenu-submenu { | 882 | .webkit #manage-enterprises .simplemenu-submenu { |
883 | top: 20px; | 883 | top: 20px; |
884 | } | 884 | } |
885 | +#manage-communities { | ||
886 | + display: inline-block; | ||
887 | + margin-right: 5px; | ||
888 | + position: relative; | ||
889 | +} | ||
890 | +#manage-communities .ui-icon { | ||
891 | + position: absolute; | ||
892 | + top: 0; | ||
893 | + right: -20px; | ||
894 | +} | ||
895 | +#manage-communities .simplemenu-submenu { | ||
896 | + text-align: left; | ||
897 | + left: -20px; | ||
898 | + width: 200px; | ||
899 | +} | ||
900 | +#manage-communities .simplemenu-item { | ||
901 | + padding: 5px 0; | ||
902 | +} | ||
903 | +#manage-communities .simplemenu-item a { | ||
904 | + background-repeat: no-repeat; | ||
905 | + padding-left: 20px; | ||
906 | +} | ||
907 | +#manage-communities .simplemenu-item a span { | ||
908 | + display: none; | ||
909 | +} | ||
910 | +.msie8 #manage-communities-link { /* IE8 hack */ | ||
911 | + border: 0px solid; | ||
912 | +} | ||
913 | +.msie8 #manage-communities .simplemenu-submenu { | ||
914 | + top: 16px; | ||
915 | +} | ||
916 | +.webkit #manage-communities .simplemenu-submenu { | ||
917 | + top: 20px; | ||
918 | +} | ||
885 | #article { | 919 | #article { |
886 | position: relative; | 920 | position: relative; |
887 | text-align: justify; | 921 | text-align: justify; |
@@ -1552,6 +1586,7 @@ a.button.disabled, input.disabled { | @@ -1552,6 +1586,7 @@ a.button.disabled, input.disabled { | ||
1552 | .map { | 1586 | .map { |
1553 | clear: both; | 1587 | clear: both; |
1554 | } | 1588 | } |
1589 | + | ||
1555 | /*********************************************************** | 1590 | /*********************************************************** |
1556 | * style for blocks | 1591 | * style for blocks |
1557 | ***********************************************************/ | 1592 | ***********************************************************/ |
@@ -3102,7 +3137,7 @@ table.cms-articles a.icon { | @@ -3102,7 +3137,7 @@ table.cms-articles a.icon { | ||
3102 | text-overflow: ellipsis; | 3137 | text-overflow: ellipsis; |
3103 | } | 3138 | } |
3104 | 3139 | ||
3105 | -table.cms-articles a.icon, table.cms-articles a.icon-parent-folder { | 3140 | +table.cms-articles a.icon, table.cms-articles a.icon-parent-folder, .cms-homepage a.icon { |
3106 | padding: 0px 0px 3px 20px; | 3141 | padding: 0px 0px 3px 20px; |
3107 | background-repeat: no-repeat; | 3142 | background-repeat: no-repeat; |
3108 | } | 3143 | } |
@@ -3121,6 +3156,14 @@ table.cms-articles .icon:hover { | @@ -3121,6 +3156,14 @@ table.cms-articles .icon:hover { | ||
3121 | border-right: 1px solid #ccc; | 3156 | border-right: 1px solid #ccc; |
3122 | } | 3157 | } |
3123 | 3158 | ||
3159 | +.cms-homepage a.icon { | ||
3160 | + border: none; | ||
3161 | +} | ||
3162 | + | ||
3163 | +.cms-homepage a:hover { | ||
3164 | + background-color: transparent; | ||
3165 | +} | ||
3166 | + | ||
3124 | .select-article-type { | 3167 | .select-article-type { |
3125 | padding: 5px 20px; | 3168 | padding: 5px 20px; |
3126 | width: 455px; | 3169 | width: 455px; |
@@ -3176,6 +3219,14 @@ table.cms-articles .icon:hover { | @@ -3176,6 +3219,14 @@ table.cms-articles .icon:hover { | ||
3176 | background: #eeeeec; | 3219 | background: #eeeeec; |
3177 | border: 1px solid #d3d7cf; | 3220 | border: 1px solid #d3d7cf; |
3178 | } | 3221 | } |
3222 | + | ||
3223 | +.controller-cms .article-mime { | ||
3224 | + max-width: 90px; | ||
3225 | + overflow: hidden; | ||
3226 | + text-overflow: ellipsis; | ||
3227 | + white-space: nowrap; | ||
3228 | +} | ||
3229 | + | ||
3179 | .controller-cms .article-controls { | 3230 | .controller-cms .article-controls { |
3180 | white-space: nowrap; | 3231 | white-space: nowrap; |
3181 | } | 3232 | } |
@@ -3446,26 +3497,7 @@ div#article-parent { | @@ -3446,26 +3497,7 @@ div#article-parent { | ||
3446 | .article-body-uploaded-file { | 3497 | .article-body-uploaded-file { |
3447 | text-align: center; | 3498 | text-align: center; |
3448 | } | 3499 | } |
3449 | -/************* uploaded file *****************/ | ||
3450 | 3500 | ||
3451 | -#article .gallery-navigation { | ||
3452 | - padding: 10px 0; | ||
3453 | -} | ||
3454 | -#article .gallery-navigation .left { | ||
3455 | - margin-right: 10px; | ||
3456 | -} | ||
3457 | -#article .gallery-navigation .right { | ||
3458 | - margin-left: 10px; | ||
3459 | -} | ||
3460 | -#article .gallery-navigation .total-of-images { | ||
3461 | - font-weight: bold; | ||
3462 | -} | ||
3463 | -#article .uploaded-file-description { | ||
3464 | - background: #f6f6f6; | ||
3465 | - border-top: 1px solid #ccc; | ||
3466 | - border-bottom: 1px solid #ccc; | ||
3467 | - padding: 1em; | ||
3468 | -} | ||
3469 | /* ==> public/stylesheets/controller_events.css <== */ | 3501 | /* ==> public/stylesheets/controller_events.css <== */ |
3470 | #agenda { | 3502 | #agenda { |
3471 | position: relative; | 3503 | position: relative; |
@@ -5681,6 +5713,10 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | @@ -5681,6 +5713,10 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | ||
5681 | padding-left: 20px; | 5713 | padding-left: 20px; |
5682 | } | 5714 | } |
5683 | 5715 | ||
5716 | +.view-more-comments, .view-more-replies { | ||
5717 | + text-align: center; | ||
5718 | +} | ||
5719 | + | ||
5684 | /* Profile activity relative dimensions */ | 5720 | /* Profile activity relative dimensions */ |
5685 | 5721 | ||
5686 | #leave_scrap { | 5722 | #leave_scrap { |
script/development
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | +set -e | ||
4 | + | ||
3 | export RAILS_ENV=development | 5 | export RAILS_ENV=development |
4 | 6 | ||
5 | stop() { | 7 | stop() { |
@@ -9,6 +11,7 @@ stop() { | @@ -9,6 +11,7 @@ stop() { | ||
9 | } | 11 | } |
10 | 12 | ||
11 | start() { | 13 | start() { |
14 | + rake db:abort_if_pending_migrations | ||
12 | ./script/feed-updater start | 15 | ./script/feed-updater start |
13 | ./script/delayed_job start | 16 | ./script/delayed_job start |
14 | trap stop INT TERM | 17 | trap stop INT TERM |
script/quick-start
@@ -67,10 +67,25 @@ else | @@ -67,10 +67,25 @@ else | ||
67 | fi | 67 | fi |
68 | 68 | ||
69 | # create the database with sample data | 69 | # create the database with sample data |
70 | -run cp config/database.yml.pgsql config/database.yml | ||
71 | -sudo -u postgres createuser $USER --no-superuser --createdb --no-createrole | ||
72 | -sed -ri "s/username: noosfero/username: $USER/" config/database.yml | ||
73 | -sudo -u postgres createdb noosfero_development -O $USER | 70 | +if test -e config/database.yml; then |
71 | + say 'Not updating existent database.yml.' | ||
72 | + say 'If you wish to automatic reconfigure your database connection, you can delete config/database.yml and run this script again.' | ||
73 | +else | ||
74 | + say 'Configuring Noosfero to use PostgreSQL, with your user.' | ||
75 | + run cp config/database.yml.pgsql config/database.yml | ||
76 | + sed -ri "s/username: noosfero/username: $USER/" config/database.yml | ||
77 | + sudo -u postgres createuser $USER --no-superuser --createdb --no-createrole | ||
78 | +fi | ||
79 | +DB_USER="$( | ||
80 | + grep username: config/database.yml | head -n1 | sed -r 's/.*:\s*([^ ]+).*/\1/' | ||
81 | +)" | ||
82 | +if test -n "$DB_USER"; then | ||
83 | + say "DB user: $DB_USER" | ||
84 | +else | ||
85 | + say 'It looks like your database.yml have no user defined' | ||
86 | + DB_USER=$USER | ||
87 | +fi | ||
88 | +sudo -u postgres createdb noosfero_development -O $DB_USER | ||
74 | run rake db:schema:load | 89 | run rake db:schema:load |
75 | run rake db:data:minimal | 90 | run rake db:data:minimal |
76 | run rake db:test:prepare | 91 | run rake db:test:prepare |
test/functional/cms_controller_test.rb
@@ -109,6 +109,18 @@ class CmsControllerTest < ActionController::TestCase | @@ -109,6 +109,18 @@ class CmsControllerTest < ActionController::TestCase | ||
109 | assert_no_tag :tag => 'a', :content => 'Use as homepage', :attributes => { :href => "/myprofile/#{profile.identifier}/cms/set_home_page/#{folder.id}" } | 109 | assert_no_tag :tag => 'a', :content => 'Use as homepage', :attributes => { :href => "/myprofile/#{profile.identifier}/cms/set_home_page/#{folder.id}" } |
110 | end | 110 | end |
111 | 111 | ||
112 | + should 'display the profile homepage if can change homepage' do | ||
113 | + env = Environment.default; env.disable('cant_change_homepage') | ||
114 | + get :index, :profile => profile.identifier | ||
115 | + assert_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"} | ||
116 | + end | ||
117 | + | ||
118 | + should 'not display the profile homepage if cannot change homepage' do | ||
119 | + env = Environment.default; env.enable('cant_change_homepage') | ||
120 | + get :index, :profile => profile.identifier | ||
121 | + assert_no_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"} | ||
122 | + end | ||
123 | + | ||
112 | should 'be able to set home page' do | 124 | should 'be able to set home page' do |
113 | a = profile.articles.build(:name => 'my new home page') | 125 | a = profile.articles.build(:name => 'my new home page') |
114 | a.save! | 126 | a.save! |
@@ -119,6 +131,7 @@ class CmsControllerTest < ActionController::TestCase | @@ -119,6 +131,7 @@ class CmsControllerTest < ActionController::TestCase | ||
119 | 131 | ||
120 | profile.reload | 132 | profile.reload |
121 | assert_equal a, profile.home_page | 133 | assert_equal a, profile.home_page |
134 | + assert_match /configured/, session[:notice] | ||
122 | end | 135 | end |
123 | 136 | ||
124 | should 'be able to set home page even when profile description is invalid' do | 137 | should 'be able to set home page even when profile description is invalid' do |
@@ -154,6 +167,37 @@ class CmsControllerTest < ActionController::TestCase | @@ -154,6 +167,37 @@ class CmsControllerTest < ActionController::TestCase | ||
154 | assert_redirected_to profile.url | 167 | assert_redirected_to profile.url |
155 | end | 168 | end |
156 | 169 | ||
170 | + should 'be able to reset home page' do | ||
171 | + a = profile.articles.build(:name => 'my new home page') | ||
172 | + a.save! | ||
173 | + | ||
174 | + profile.home_page = a | ||
175 | + profile.save! | ||
176 | + | ||
177 | + post :set_home_page, :profile => profile.identifier, :id => nil | ||
178 | + | ||
179 | + profile.reload | ||
180 | + assert_equal nil, profile.home_page | ||
181 | + assert_match /reseted/, session[:notice] | ||
182 | + end | ||
183 | + | ||
184 | + should 'display default home page' do | ||
185 | + profile.home_page = nil | ||
186 | + profile.save! | ||
187 | + get :index, :profile => profile.identifier | ||
188 | + assert_tag :tag => 'div', :attributes => { :class => "cms-homepage" }, :descendant => { :tag => "span", :content => /Profile Information/ } | ||
189 | + end | ||
190 | + | ||
191 | + should 'display article as home page' do | ||
192 | + a = profile.articles.build(:name => 'my new home page') | ||
193 | + a.save! | ||
194 | + profile.home_page = a | ||
195 | + profile.save! | ||
196 | + Article.stubs(:short_description).returns('short description') | ||
197 | + get :index, :profile => profile.identifier | ||
198 | + assert_tag :tag => 'div', :attributes => { :class => "cms-homepage" }, :descendant => { :tag => "a", :content => /my new home page/ } | ||
199 | + end | ||
200 | + | ||
157 | should 'set last_changed_by when creating article' do | 201 | should 'set last_changed_by when creating article' do |
158 | login_as(profile.identifier) | 202 | login_as(profile.identifier) |
159 | 203 | ||
@@ -940,8 +984,8 @@ class CmsControllerTest < ActionController::TestCase | @@ -940,8 +984,8 @@ class CmsControllerTest < ActionController::TestCase | ||
940 | :article => {:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')} | 984 | :article => {:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')} |
941 | 985 | ||
942 | process_delayed_job_queue | 986 | process_delayed_job_queue |
943 | - file = profile.articles.find_by_name('rails.png') | ||
944 | - assert File.exists?(file.class.icon_name(file)) | 987 | + file = FilePresenter.for profile.articles.find_by_name('rails.png') |
988 | + assert File.exists?(file.icon_name) | ||
945 | file.destroy | 989 | file.destroy |
946 | end | 990 | end |
947 | 991 | ||
@@ -951,8 +995,8 @@ class CmsControllerTest < ActionController::TestCase | @@ -951,8 +995,8 @@ class CmsControllerTest < ActionController::TestCase | ||
951 | :article => {:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')} | 995 | :article => {:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')} |
952 | 996 | ||
953 | process_delayed_job_queue | 997 | process_delayed_job_queue |
954 | - file = profile.articles.find_by_name('rails.png') | ||
955 | - assert File.exists?(file.class.icon_name(file)) | 998 | + file = FilePresenter.for profile.articles.find_by_name('rails.png') |
999 | + assert File.exists?(file.icon_name) | ||
956 | file.destroy | 1000 | file.destroy |
957 | end | 1001 | end |
958 | 1002 |
test/functional/content_viewer_controller_test.rb
@@ -1271,4 +1271,12 @@ class ContentViewerControllerTest < ActionController::TestCase | @@ -1271,4 +1271,12 @@ class ContentViewerControllerTest < ActionController::TestCase | ||
1271 | assert_tag :tag => 'strong', :content => /bold/ | 1271 | assert_tag :tag => 'strong', :content => /bold/ |
1272 | end | 1272 | end |
1273 | 1273 | ||
1274 | + should 'display link to download of non-recognized file types on its page' do | ||
1275 | + file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'bin/unknown'), :profile => profile) | ||
1276 | + get :view_page, file.url.merge(:view=>:true) | ||
1277 | + assert_tag :tag => 'a', | ||
1278 | + :content => file.filename, | ||
1279 | + :attributes => { :href => file.public_filename } | ||
1280 | + end | ||
1281 | + | ||
1274 | end | 1282 | end |
test/functional/memberships_controller_test.rb
@@ -245,4 +245,17 @@ class MembershipsControllerTest < ActionController::TestCase | @@ -245,4 +245,17 @@ class MembershipsControllerTest < ActionController::TestCase | ||
245 | assert_tag :tag => 'input', :attributes => {:id => 'community_plugin2', :type => 'hidden', :value => 'Plugin 2'} | 245 | assert_tag :tag => 'input', :attributes => {:id => 'community_plugin2', :type => 'hidden', :value => 'Plugin 2'} |
246 | end | 246 | end |
247 | 247 | ||
248 | + should 'redirect to back_to parameter when create a new community' do | ||
249 | + back_to = '/' | ||
250 | + post :new_community, :profile => profile.identifier, :community => { :name => 'My shiny new community', :description => 'This is a community devoted to anything interesting we find in the internet '}, :back_to => back_to | ||
251 | + assert_response :redirect | ||
252 | + assert_redirected_to back_to | ||
253 | + end | ||
254 | + | ||
255 | + should 'cancel button redirect to back_to parameter' do | ||
256 | + back_to = '/' | ||
257 | + get :new_community, :profile => profile.identifier, :back_to => back_to | ||
258 | + assert_tag :tag => 'a', :attributes => { :class => 'button icon-cancel with-text', :href => back_to } | ||
259 | + end | ||
260 | + | ||
248 | end | 261 | end |
test/functional/profile_controller_test.rb
@@ -17,11 +17,11 @@ class ProfileControllerTest < ActionController::TestCase | @@ -17,11 +17,11 @@ class ProfileControllerTest < ActionController::TestCase | ||
17 | def test_local_files_reference | 17 | def test_local_files_reference |
18 | assert_local_files_reference | 18 | assert_local_files_reference |
19 | end | 19 | end |
20 | - | 20 | + |
21 | def test_valid_xhtml | 21 | def test_valid_xhtml |
22 | assert_valid_xhtml | 22 | assert_valid_xhtml |
23 | end | 23 | end |
24 | - | 24 | + |
25 | noosfero_test :profile => 'testuser' | 25 | noosfero_test :profile => 'testuser' |
26 | 26 | ||
27 | should 'list friends' do | 27 | should 'list friends' do |
@@ -68,7 +68,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -68,7 +68,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
68 | assert_template 'members' | 68 | assert_template 'members' |
69 | assert_kind_of Array, assigns(:members) | 69 | assert_kind_of Array, assigns(:members) |
70 | end | 70 | end |
71 | - | 71 | + |
72 | should 'list favorite enterprises' do | 72 | should 'list favorite enterprises' do |
73 | get :favorite_enterprises | 73 | get :favorite_enterprises |
74 | 74 | ||
@@ -96,7 +96,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -96,7 +96,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
96 | end | 96 | end |
97 | 97 | ||
98 | should 'not show enterprises link to enterprise' do | 98 | should 'not show enterprises link to enterprise' do |
99 | - ent = fast_create(Enterprise, :identifier => 'test_enterprise1', :name => 'Test enteprise1') | 99 | + ent = fast_create(Enterprise, :identifier => 'test_enterprise1', :name => 'Test enterprise1') |
100 | get :index, :profile => ent.identifier | 100 | get :index, :profile => ent.identifier |
101 | assert_no_tag :tag => 'a', :content => 'Enterprises', :attributes => { :href => /profile\/#{ent.identifier}\/enterprises$/ } | 101 | assert_no_tag :tag => 'a', :content => 'Enterprises', :attributes => { :href => /profile\/#{ent.identifier}\/enterprises$/ } |
102 | end | 102 | end |
@@ -318,7 +318,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -318,7 +318,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
318 | get :profile_info, :profile => 'my-test-enterprise', :block_id => block.id | 318 | get :profile_info, :profile => 'my-test-enterprise', :block_id => block.id |
319 | assert_no_match /\/contact\/my-test-enterprise\/new/, @response.body | 319 | assert_no_match /\/contact\/my-test-enterprise\/new/, @response.body |
320 | end | 320 | end |
321 | - | 321 | + |
322 | should 'display contact button only if friends' do | 322 | should 'display contact button only if friends' do |
323 | friend = create_user_full('friend_user').person | 323 | friend = create_user_full('friend_user').person |
324 | friend.user.activate | 324 | friend.user.activate |
@@ -560,7 +560,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -560,7 +560,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
560 | assert_response 403 | 560 | assert_response 403 |
561 | end | 561 | end |
562 | 562 | ||
563 | - should 'allow environment admin to unblock enteprises' do | 563 | + should 'allow environment admin to unblock enterprises' do |
564 | login_as(profile.identifier) | 564 | login_as(profile.identifier) |
565 | enterprise = fast_create(Enterprise) | 565 | enterprise = fast_create(Enterprise) |
566 | enterprise.environment.add_admin(profile) | 566 | enterprise.environment.add_admin(profile) |
@@ -734,7 +734,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -734,7 +734,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
734 | end | 734 | end |
735 | 735 | ||
736 | should 'see the activities_items paginated' do | 736 | should 'see the activities_items paginated' do |
737 | - p1= Person.first | 737 | + p1 = create_user('some').person |
738 | ActionTracker::Record.destroy_all | 738 | ActionTracker::Record.destroy_all |
739 | 40.times{Scrap.create!(defaults_for_scrap(:sender => p1, :receiver => p1))} | 739 | 40.times{Scrap.create!(defaults_for_scrap(:sender => p1, :receiver => p1))} |
740 | login_as(p1.identifier) | 740 | login_as(p1.identifier) |
@@ -881,7 +881,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -881,7 +881,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
881 | assert_template 'index' | 881 | assert_template 'index' |
882 | end | 882 | end |
883 | 883 | ||
884 | - should 'the network activity be visible to uses not logged in on communities and enteprises' do | 884 | + should 'the network activity be visible to uses not logged in on communities and enterprises' do |
885 | p1= Person.first | 885 | p1= Person.first |
886 | community = fast_create(Community) | 886 | community = fast_create(Community) |
887 | p2= fast_create(Person) | 887 | p2= fast_create(Person) |
@@ -1091,7 +1091,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1091,7 +1091,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
1091 | login_as(profile.identifier) | 1091 | login_as(profile.identifier) |
1092 | person = fast_create(Person) | 1092 | person = fast_create(Person) |
1093 | at = fast_create(ActionTracker::Record, :user_id => person.id) | 1093 | at = fast_create(ActionTracker::Record, :user_id => person.id) |
1094 | - atn = fast_create(ActionTrackerNotification, :profile_id => profile.id, :action_tracker_id => at.id) | 1094 | + atn = fast_create(ActionTrackerNotification, :profile_id => profile.id, :action_tracker_id => at.id) |
1095 | get :index, :profile => person.identifier | 1095 | get :index, :profile => person.identifier |
1096 | assert_no_tag :tag => 'div', :attributes => {:id => 'profile-network'} | 1096 | assert_no_tag :tag => 'div', :attributes => {:id => 'profile-network'} |
1097 | 1097 | ||
@@ -1103,7 +1103,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1103,7 +1103,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
1103 | should "not show the scrap button on network activity if the user is himself" do | 1103 | should "not show the scrap button on network activity if the user is himself" do |
1104 | login_as(profile.identifier) | 1104 | login_as(profile.identifier) |
1105 | at = fast_create(ActionTracker::Record, :user_id => profile.id) | 1105 | at = fast_create(ActionTracker::Record, :user_id => profile.id) |
1106 | - atn = fast_create(ActionTrackerNotification, :profile_id => profile.id, :action_tracker_id => at.id) | 1106 | + atn = fast_create(ActionTrackerNotification, :profile_id => profile.id, :action_tracker_id => at.id) |
1107 | get :index, :profile => profile.identifier | 1107 | get :index, :profile => profile.identifier |
1108 | assert_no_tag :tag => 'p', :attributes => {:class => 'profile-network-send-message'} | 1108 | assert_no_tag :tag => 'p', :attributes => {:class => 'profile-network-send-message'} |
1109 | end | 1109 | end |
@@ -1131,7 +1131,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1131,7 +1131,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
1131 | at = fast_create(ActionTracker::Record, :user_id => profile.id) | 1131 | at = fast_create(ActionTracker::Record, :user_id => profile.id) |
1132 | profile.public_profile=false | 1132 | profile.public_profile=false |
1133 | profile.save | 1133 | profile.save |
1134 | - atn = fast_create(ActionTrackerNotification, :profile_id => profile.id, :action_tracker_id => at.id) | 1134 | + atn = fast_create(ActionTrackerNotification, :profile_id => profile.id, :action_tracker_id => at.id) |
1135 | get :index, :profile => profile.identifier | 1135 | get :index, :profile => profile.identifier |
1136 | assert_equal [at], profile.tracked_actions | 1136 | assert_equal [at], profile.tracked_actions |
1137 | assert_no_tag :tag => 'li', :attributes => {:id => "profile-activity-item-#{atn.id}"} | 1137 | assert_no_tag :tag => 'li', :attributes => {:id => "profile-activity-item-#{atn.id}"} |
@@ -1170,6 +1170,58 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1170,6 +1170,58 @@ class ProfileControllerTest < ActionController::TestCase | ||
1170 | assert_redirected_to :controller => 'account', :action => 'login' | 1170 | assert_redirected_to :controller => 'account', :action => 'login' |
1171 | end | 1171 | end |
1172 | 1172 | ||
1173 | + should "not index display activities comments" do | ||
1174 | + login_as(profile.identifier) | ||
1175 | + article = TinyMceArticle.create!(:profile => profile, :name => 'An Article about Free Software') | ||
1176 | + ActionTracker::Record.destroy_all | ||
1177 | + activity = ActionTracker::Record.create!(:user_id => profile.id, :user_type => 'Profile', :verb => 'create_article', :target_id => article.id, :target_type => 'Article', :params => {'name' => article.name, 'url' => article.url, 'lead' => article.lead, 'first_image' => article.first_image}) | ||
1178 | + 20.times {comment = fast_create(Comment, :source_id => article, :title => 'a comment', :body => 'lalala', :created_at => Time.now)} | ||
1179 | + article.reload | ||
1180 | + get :index, :profile => profile.identifier | ||
1181 | + assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments'}, :children => {:count => 0 } | ||
1182 | + end | ||
1183 | + | ||
1184 | + should "view more comments paginated" do | ||
1185 | + login_as(profile.identifier) | ||
1186 | + article = TinyMceArticle.create!(:profile => profile, :name => 'An Article about Free Software') | ||
1187 | + ActionTracker::Record.destroy_all | ||
1188 | + activity = ActionTracker::Record.create!(:user_id => profile.id, :user_type => 'Profile', :verb => 'create_article', :target_id => article.id, :target_type => 'Article', :params => {'name' => article.name, 'url' => article.url, 'lead' => article.lead, 'first_image' => article.first_image}) | ||
1189 | + 20.times {comment = fast_create(Comment, :source_id => article, :title => 'a comment', :body => 'lalala', :created_at => Time.now)} | ||
1190 | + article.reload | ||
1191 | + assert_equal 20, article.comments.count | ||
1192 | + get :more_comments, :activity => activity.id, :comment_page => 2 | ||
1193 | + assert_response :success | ||
1194 | + assert_template '_comment' | ||
1195 | + assert_select_rjs :insert_html do | ||
1196 | + assert_select 'li', 5 # 5 comments per page | ||
1197 | + end | ||
1198 | + end | ||
1199 | + | ||
1200 | + should "not index display scraps replies" do | ||
1201 | + login_as(profile.identifier) | ||
1202 | + Scrap.destroy_all | ||
1203 | + scrap = fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id) | ||
1204 | + 20.times {fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id, :scrap_id => scrap.id)} | ||
1205 | + profile.reload | ||
1206 | + get :index, :profile => profile.identifier | ||
1207 | + assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments scrap-replies'}, :children => {:count => 0 } | ||
1208 | + end | ||
1209 | + | ||
1210 | + should "view more replies paginated" do | ||
1211 | + login_as(profile.identifier) | ||
1212 | + Scrap.destroy_all | ||
1213 | + scrap = fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id) | ||
1214 | + 20.times {fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id, :scrap_id => scrap.id)} | ||
1215 | + profile.reload | ||
1216 | + assert_equal 20, scrap.replies.count | ||
1217 | + get :more_replies, :activity => scrap.id, :comment_page => 2 | ||
1218 | + assert_response :success | ||
1219 | + assert_template '_profile_scrap' | ||
1220 | + assert_select_rjs :insert_html do | ||
1221 | + assert_select 'li', 5 # 5 replies per page | ||
1222 | + end | ||
1223 | + end | ||
1224 | + | ||
1173 | should 'render empty response for not logged in users in check_membership' do | 1225 | should 'render empty response for not logged in users in check_membership' do |
1174 | get :check_membership | 1226 | get :check_membership |
1175 | assert_equal '', @response.body | 1227 | assert_equal '', @response.body |
@@ -1276,7 +1328,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1276,7 +1328,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
1276 | login_as(profile.identifier) | 1328 | login_as(profile.identifier) |
1277 | get :index, :profile => profile.identifier | 1329 | get :index, :profile => profile.identifier |
1278 | 1330 | ||
1279 | - assert_tag :tag => 'p', :content => 'A scrap', :attributes => { :class => 'profile-activity-text'} | 1331 | + assert_tag :tag => 'p', :content => 'A scrap', :attributes => { :class => 'profile-activity-text'} |
1280 | assert_tag :tag => 'div', :attributes => { :class => 'profile-activity-lead' }, :descendant => { :tag => 'a', :content => 'An article about free software' } | 1332 | assert_tag :tag => 'div', :attributes => { :class => 'profile-activity-lead' }, :descendant => { :tag => 'a', :content => 'An article about free software' } |
1281 | end | 1333 | end |
1282 | 1334 | ||
@@ -1331,30 +1383,6 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1331,30 +1383,6 @@ class ProfileControllerTest < ActionController::TestCase | ||
1331 | assert_equal "Comment successfully added.", assigns(:message) | 1383 | assert_equal "Comment successfully added.", assigns(:message) |
1332 | end | 1384 | end |
1333 | 1385 | ||
1334 | - should 'display comment in wall if user was removed' do | ||
1335 | - UserStampSweeper.any_instance.stubs(:current_user).returns(profile) | ||
1336 | - article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') | ||
1337 | - to_be_removed = create_user('removed_user').person | ||
1338 | - comment = Comment.create!(:author => to_be_removed, :title => 'Test Comment', :body => 'My author does not exist =(', :source_id => article.id, :source_type => 'Article') | ||
1339 | - to_be_removed.destroy | ||
1340 | - | ||
1341 | - login_as(profile.identifier) | ||
1342 | - get :index, :profile => profile.identifier | ||
1343 | - | ||
1344 | - assert_tag :tag => 'span', :content => '(removed user)', :attributes => {:class => 'comment-user-status comment-user-status-wall icon-user-removed'} | ||
1345 | - end | ||
1346 | - | ||
1347 | - should 'display comment in wall from non logged users' do | ||
1348 | - UserStampSweeper.any_instance.stubs(:current_user).returns(profile) | ||
1349 | - article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') | ||
1350 | - comment = Comment.create!(:name => 'outside user', :email => 'outside@localhost.localdomain', :title => 'Test Comment', :body => 'My author does not exist =(', :source_id => article.id, :source_type => 'Article') | ||
1351 | - | ||
1352 | - login_as(profile.identifier) | ||
1353 | - get :index, :profile => profile.identifier | ||
1354 | - | ||
1355 | - assert_tag :tag => 'span', :content => '(unauthenticated user)', :attributes => {:class => 'comment-user-status comment-user-status-wall icon-user-unknown'} | ||
1356 | - end | ||
1357 | - | ||
1358 | should 'add locale on mailing' do | 1386 | should 'add locale on mailing' do |
1359 | community = fast_create(Community) | 1387 | community = fast_create(Community) |
1360 | create_user_with_permission('profile_moderator_user', 'send_mail_to_members', community) | 1388 | create_user_with_permission('profile_moderator_user', 'send_mail_to_members', community) |
@@ -1549,6 +1577,109 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1549,6 +1577,109 @@ class ProfileControllerTest < ActionController::TestCase | ||
1549 | assert_tag :tag => 'td', :content => 'e-Mail:' | 1577 | assert_tag :tag => 'td', :content => 'e-Mail:' |
1550 | end | 1578 | end |
1551 | 1579 | ||
1580 | + should 'not display list of communities to manage on menu by default' do | ||
1581 | + user = create_user('community_admin').person | ||
1582 | + community = fast_create(Community) | ||
1583 | + community.add_admin(user) | ||
1584 | + | ||
1585 | + login_as(user.identifier) | ||
1586 | + get :index | ||
1587 | + assert_no_tag :tag => 'div', :attributes => {:id => 'manage-communities'} | ||
1588 | + end | ||
1589 | + | ||
1590 | + should 'display list of communities to manage on menu if enabled' do | ||
1591 | + user = create_user('community_admin').person | ||
1592 | + env = user.environment | ||
1593 | + community = fast_create(Community) | ||
1594 | + community.add_admin(user) | ||
1595 | + | ||
1596 | + Environment.any_instance.stubs(:enabled?).returns(false) | ||
1597 | + Environment.any_instance.stubs(:enabled?).with(:display_my_communities_on_user_menu).returns(true) | ||
1598 | + | ||
1599 | + login_as(user.identifier) | ||
1600 | + get :index | ||
1601 | + assert_tag :tag => 'div', :attributes => {:id => 'manage-communities'} | ||
1602 | + | ||
1603 | + end | ||
1604 | + | ||
1605 | + should 'build menu to the community panel of communities the user can manage if enabled' do | ||
1606 | + u = create_user('other_other_ze').person | ||
1607 | + u2 = create_user('guy_that_will_be_admin_of_all').person # because the first member of each community is an admin | ||
1608 | + | ||
1609 | + Environment.any_instance.stubs(:enabled?).returns(false) | ||
1610 | + Environment.any_instance.stubs(:enabled?).with(:display_my_communities_on_user_menu).returns(true) | ||
1611 | + | ||
1612 | + Environment.any_instance.stubs(:required_person_fields).returns([]) | ||
1613 | + u.data = { :email => 'test@test.com', :fields_privacy => { } } | ||
1614 | + u.save! | ||
1615 | + c1 = fast_create(Community, :name => 'community_1') | ||
1616 | + c2 = fast_create(Community, :name => 'community_2') | ||
1617 | + c3 = fast_create(Community, :name => 'community_3') | ||
1618 | + c4 = fast_create(Community, :name => 'community_4') | ||
1619 | + | ||
1620 | + c1.add_admin(u2) | ||
1621 | + c2.add_admin(u2) | ||
1622 | + c3.add_admin(u2) | ||
1623 | + | ||
1624 | + c1.add_member(u) | ||
1625 | + c2.add_member(u) | ||
1626 | + c3.add_member(u) | ||
1627 | + c1.add_admin(u) | ||
1628 | + c2.add_admin(u) | ||
1629 | + | ||
1630 | + login_as(u.identifier) | ||
1631 | + | ||
1632 | + get :index | ||
1633 | + | ||
1634 | + assert_tag :tag => 'div', :attributes => {:id => 'manage-communities'} | ||
1635 | + assert_select '#manage-communities li > a' do |links| | ||
1636 | + assert_equal 2, links.length | ||
1637 | + assert_match /community_1/, links.to_s | ||
1638 | + assert_match /community_2/, links.to_s | ||
1639 | + assert_no_match /community_3/, links.to_s | ||
1640 | + assert_no_match /community_4/, links.to_s | ||
1641 | + end | ||
1642 | + end | ||
1643 | + | ||
1644 | + should 'build menu to the enterprise panel if enabled' do | ||
1645 | + u = create_user('other_other_ze').person | ||
1646 | + | ||
1647 | + Environment.any_instance.stubs(:enabled?).returns(false) | ||
1648 | + Environment.any_instance.stubs(:enabled?).with(:display_my_enterprises_on_user_menu).returns(true) | ||
1649 | + | ||
1650 | + Environment.any_instance.stubs(:required_person_fields).returns([]) | ||
1651 | + u.data = { :email => 'test@test.com', :fields_privacy => { } } | ||
1652 | + u.save! | ||
1653 | + e1 = fast_create(Enterprise, :identifier => 'test_enterprise1', :name => 'Test enterprise1') | ||
1654 | + e2 = fast_create(Enterprise, :identifier => 'test_enterprise2', :name => 'Test enterprise2') | ||
1655 | + | ||
1656 | + e1.add_member(u) | ||
1657 | + | ||
1658 | + login_as(u.identifier) | ||
1659 | + | ||
1660 | + get :index | ||
1661 | + | ||
1662 | + assert_tag :tag => 'div', :attributes => {:id => 'manage-enterprises'} | ||
1663 | + assert_select '#manage-enterprises li > a' do |links| | ||
1664 | + assert_equal 1, links.length | ||
1665 | + assert_match /Test enterprise1/, links.to_s | ||
1666 | + assert_no_match /Test enterprise_2/, links.to_s | ||
1667 | + end | ||
1668 | + end | ||
1669 | + | ||
1670 | + should 'not build menu to the enterprise panel if not enabled' do | ||
1671 | + user = create_user('enterprise_admin').person | ||
1672 | + enterprise = fast_create(Enterprise) | ||
1673 | + enterprise.add_admin(user) | ||
1674 | + | ||
1675 | + Environment.any_instance.stubs(:enabled?).returns(false) | ||
1676 | + Environment.any_instance.stubs(:enabled?).with(:display_my_enterprises_on_user_menu).returns(false) | ||
1677 | + | ||
1678 | + login_as(user.identifier) | ||
1679 | + get :index | ||
1680 | + assert_no_tag :tag => 'div', :attributes => {:id => 'manage-enterprises'} | ||
1681 | + end | ||
1682 | + | ||
1552 | should 'show enterprises field if enterprises are enabled on environment' do | 1683 | should 'show enterprises field if enterprises are enabled on environment' do |
1553 | person = fast_create(Person) | 1684 | person = fast_create(Person) |
1554 | environment = person.environment | 1685 | environment = person.environment |
test/functional/spam_controller_test.rb
@@ -4,37 +4,55 @@ class SpamControllerTest < ActionController::TestCase | @@ -4,37 +4,55 @@ class SpamControllerTest < ActionController::TestCase | ||
4 | 4 | ||
5 | def setup | 5 | def setup |
6 | @profile = create_user.person | 6 | @profile = create_user.person |
7 | - @article = fast_create(TextileArticle, :profile_id => @profile.id) | ||
8 | - @spam = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com') | ||
9 | 7 | ||
8 | + @community = fast_create(Community, :name => 'testcommunity') | ||
9 | + @community.add_admin(@profile) | ||
10 | + @article = fast_create(TextileArticle, :profile_id => @community.id) | ||
11 | + @spam_comment = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com') | ||
12 | + | ||
13 | + @spam_suggest_article = SuggestArticle.create!(:name => 'spammer', :article_name => 'Spam article', :email => 'spammer@shady.place', :article_body => "Something you don't need", :target => @community, :spam => true) | ||
10 | login_as @profile.identifier | 14 | login_as @profile.identifier |
11 | end | 15 | end |
12 | 16 | ||
13 | - test "should only list spammy comments" do | 17 | + test "should only list spammy comments and spammy suggest articles" do |
14 | ham = fast_create(Comment, :source_id => @article.id) | 18 | ham = fast_create(Comment, :source_id => @article.id) |
15 | 19 | ||
16 | - get :index, :profile => @profile.identifier | 20 | + get :index, :profile => @community.identifier |
17 | 21 | ||
18 | - assert_equivalent [@spam], assigns(:spam) | 22 | + assert_equivalent [@spam_comment], assigns(:comment_spam) |
23 | + assert_equivalent [@spam_suggest_article], assigns(:task_spam) | ||
19 | end | 24 | end |
20 | 25 | ||
21 | test "should mark comments as ham" do | 26 | test "should mark comments as ham" do |
22 | - post :index, :profile => @profile.identifier, :mark_comment_as_ham => @spam.id | 27 | + post :index, :profile => @community.identifier, :mark_comment_as_ham => @spam_comment.id |
28 | + | ||
29 | + @spam_comment.reload | ||
30 | + assert @spam_comment.ham? | ||
31 | + end | ||
32 | + | ||
33 | + test "should mark suggest article as ham" do | ||
34 | + post :index, :profile => @community.identifier, :mark_task_as_ham => @spam_suggest_article.id | ||
23 | 35 | ||
24 | - @spam.reload | ||
25 | - assert @spam.ham? | 36 | + @spam_suggest_article.reload |
37 | + assert @spam_suggest_article.ham? | ||
26 | end | 38 | end |
27 | 39 | ||
28 | test "should remove comments" do | 40 | test "should remove comments" do |
29 | - post :index, :profile => @profile.identifier, :remove_comment => @spam.id | 41 | + post :index, :profile => @community.identifier, :remove_comment => @spam_comment.id |
42 | + | ||
43 | + assert !Comment.exists?(@spam_comment.id) | ||
44 | + end | ||
45 | + | ||
46 | + test "should remove suggest articles" do | ||
47 | + post :index, :profile => @community.identifier, :remove_task => @spam_suggest_article.id | ||
30 | 48 | ||
31 | - assert !Comment.exists?(@spam.id) | 49 | + assert !SuggestArticle.exists?(@spam_suggest_article.id) |
32 | end | 50 | end |
33 | 51 | ||
34 | should 'properly render spam that have replies' do | 52 | should 'properly render spam that have replies' do |
35 | - reply_spam = fast_create(Comment, :source_id => @article_id, :reply_of_id => @spam.id) | 53 | + reply_spam = fast_create(Comment, :source_id => @article_id, :reply_of_id => @spam_comment.id) |
36 | 54 | ||
37 | - get :index, :profile => @profile.identifier | 55 | + get :index, :profile => @community.identifier |
38 | assert_response :success | 56 | assert_response :success |
39 | end | 57 | end |
40 | 58 |
test/functional/tasks_controller_test.rb
@@ -38,6 +38,17 @@ class TasksControllerTest < ActionController::TestCase | @@ -38,6 +38,17 @@ class TasksControllerTest < ActionController::TestCase | ||
38 | assert_kind_of Array, assigns(:tasks) | 38 | assert_kind_of Array, assigns(:tasks) |
39 | end | 39 | end |
40 | 40 | ||
41 | + should 'list pending tasks without spam' do | ||
42 | + requestor = fast_create(Person) | ||
43 | + task_spam = Task.create!(:requestor => requestor, :target => profile, :spam => true) | ||
44 | + task_ham = Task.create!(:requestor => requestor, :target => profile, :spam => false) | ||
45 | + | ||
46 | + get :index | ||
47 | + assert_response :success | ||
48 | + assert_includes assigns(:tasks), task_ham | ||
49 | + assert_not_includes assigns(:tasks), task_spam | ||
50 | + end | ||
51 | + | ||
41 | should 'list processed tasks' do | 52 | should 'list processed tasks' do |
42 | get :processed | 53 | get :processed |
43 | 54 | ||
@@ -46,6 +57,17 @@ class TasksControllerTest < ActionController::TestCase | @@ -46,6 +57,17 @@ class TasksControllerTest < ActionController::TestCase | ||
46 | assert_kind_of Array, assigns(:tasks) | 57 | assert_kind_of Array, assigns(:tasks) |
47 | end | 58 | end |
48 | 59 | ||
60 | + should 'list processed tasks without spam' do | ||
61 | + requestor = fast_create(Person) | ||
62 | + task_spam = Task.create!(:status => Task::Status::FINISHED, :requestor => requestor, :target => profile, :spam => true) | ||
63 | + task_ham = Task.create!(:status => Task::Status::FINISHED, :requestor => requestor, :target => profile, :spam => false) | ||
64 | + | ||
65 | + get :processed | ||
66 | + assert_response :success | ||
67 | + assert_includes assigns(:tasks), task_ham | ||
68 | + assert_not_includes assigns(:tasks), task_spam | ||
69 | + end | ||
70 | + | ||
49 | should 'be able to finish a task' do | 71 | should 'be able to finish a task' do |
50 | t = profile.tasks.build; t.save! | 72 | t = profile.tasks.build; t.save! |
51 | 73 | ||
@@ -140,6 +162,15 @@ class TasksControllerTest < ActionController::TestCase | @@ -140,6 +162,15 @@ class TasksControllerTest < ActionController::TestCase | ||
140 | assert_includes assigns(:tasks), task | 162 | assert_includes assigns(:tasks), task |
141 | end | 163 | end |
142 | 164 | ||
165 | + should 'list tasks that this profile created without spam' do | ||
166 | + task_spam = Ticket.create!(:name => 'test', :requestor => profile, :spam => true) | ||
167 | + task_ham = Ticket.create!(:name => 'test', :requestor => profile, :spam => false) | ||
168 | + get :list_requested, :profile => profile.identifier | ||
169 | + | ||
170 | + assert_includes assigns(:tasks), task_ham | ||
171 | + assert_not_includes assigns(:tasks), task_spam | ||
172 | + end | ||
173 | + | ||
143 | should 'set target of ticket when creating it' do | 174 | should 'set target of ticket when creating it' do |
144 | f = create_user('friend').person | 175 | f = create_user('friend').person |
145 | profile.add_friend f | 176 | profile.add_friend f |
test/unit/application_helper_test.rb
@@ -591,8 +591,8 @@ class ApplicationHelperTest < ActiveSupport::TestCase | @@ -591,8 +591,8 @@ class ApplicationHelperTest < ActiveSupport::TestCase | ||
591 | end | 591 | end |
592 | 592 | ||
593 | should 'include item in usermenu for environment enabled features' do | 593 | should 'include item in usermenu for environment enabled features' do |
594 | - env = Environment.new | ||
595 | - env.enable('xmpp_chat') | 594 | + env = fast_create(Environment) |
595 | + env.enable('xmpp_chat', false) | ||
596 | stubs(:environment).returns(env) | 596 | stubs(:environment).returns(env) |
597 | 597 | ||
598 | @controller = ApplicationController.new | 598 | @controller = ApplicationController.new |
@@ -791,6 +791,55 @@ class ApplicationHelperTest < ActiveSupport::TestCase | @@ -791,6 +791,55 @@ class ApplicationHelperTest < ActiveSupport::TestCase | ||
791 | '<br style=\'clear: left;\' /></div>', result | 791 | '<br style=\'clear: left;\' /></div>', result |
792 | end | 792 | end |
793 | 793 | ||
794 | + should 'not filter html if source does not have macros' do | ||
795 | + class Plugin1 < Noosfero::Plugin | ||
796 | + end | ||
797 | + | ||
798 | + class Plugin1::Macro1 < Noosfero::Plugin::Macro | ||
799 | + def parse(params, inner_html, source) | ||
800 | + 'Test1' | ||
801 | + end | ||
802 | + end | ||
803 | + | ||
804 | + environment = Environment.default | ||
805 | + environment.enable_plugin(Plugin1) | ||
806 | + @plugins = Noosfero::Plugin::Manager.new(environment, self) | ||
807 | + macro1_name = Plugin1::Macro1.identifier | ||
808 | + source = mock | ||
809 | + source.stubs(:has_macro?).returns(false) | ||
810 | + | ||
811 | + html = "<div class='macro nonEdit' data-macro='#{macro1_name}' data-macro-param='123'></div>" | ||
812 | + parsed_html = filter_html(html, source) | ||
813 | + | ||
814 | + assert_no_match /Test1/, parsed_html | ||
815 | + end | ||
816 | + | ||
817 | + should 'not convert macro if source is nil' do | ||
818 | + profile = create_user('testuser').person | ||
819 | + article = fast_create(Article, :profile_id => profile.id) | ||
820 | + class Plugin1 < Noosfero::Plugin; end | ||
821 | + | ||
822 | + environment = Environment.default | ||
823 | + environment.enable_plugin(Plugin1) | ||
824 | + @plugins = Noosfero::Plugin::Manager.new(environment, self) | ||
825 | + | ||
826 | + expects(:convert_macro).never | ||
827 | + filter_html(article.body, nil) | ||
828 | + end | ||
829 | + | ||
830 | + should 'not convert macro if there is no macro plugin active' do | ||
831 | + profile = create_user('testuser').person | ||
832 | + article = fast_create(Article, :profile_id => profile.id) | ||
833 | + class Plugin1 < Noosfero::Plugin; end | ||
834 | + | ||
835 | + environment = Environment.default | ||
836 | + environment.enable_plugin(Plugin1) | ||
837 | + @plugins = Noosfero::Plugin::Manager.new(environment, self) | ||
838 | + | ||
839 | + expects(:convert_macro).never | ||
840 | + filter_html(article.body, article) | ||
841 | + end | ||
842 | + | ||
794 | protected | 843 | protected |
795 | include NoosferoTestHelper | 844 | include NoosferoTestHelper |
796 | 845 |
test/unit/article_block_test.rb
@@ -110,9 +110,12 @@ class ArticleBlockTest < ActiveSupport::TestCase | @@ -110,9 +110,12 @@ class ArticleBlockTest < ActiveSupport::TestCase | ||
110 | block.article = image | 110 | block.article = image |
111 | block.save! | 111 | block.save! |
112 | 112 | ||
113 | - expects(:image_tag).with(image.public_filename(:display), :class => image.css_class_name, :style => 'max-width: 100%').returns('image') | ||
114 | - | ||
115 | - assert_match(/image/, instance_eval(&block.content)) | 113 | + assert_tag_in_string instance_eval(&block.content), |
114 | + :tag => 'img', | ||
115 | + :attributes => { | ||
116 | + :src => image.public_filename(:display), | ||
117 | + :class => /file-image/ | ||
118 | + } | ||
116 | end | 119 | end |
117 | 120 | ||
118 | should 'not display gallery pages navigation in content' do | 121 | should 'not display gallery pages navigation in content' do |
@@ -123,8 +126,6 @@ class ArticleBlockTest < ActiveSupport::TestCase | @@ -123,8 +126,6 @@ class ArticleBlockTest < ActiveSupport::TestCase | ||
123 | block.article = image | 126 | block.article = image |
124 | block.save! | 127 | block.save! |
125 | 128 | ||
126 | - expects(:image_tag).with(image.public_filename(:display), :class => image.css_class_name, :style => 'max-width: 100%').returns('image') | ||
127 | - | ||
128 | assert_no_match(/Previous/, instance_eval(&block.content)) | 129 | assert_no_match(/Previous/, instance_eval(&block.content)) |
129 | end | 130 | end |
130 | 131 |
test/unit/article_test.rb
@@ -1744,4 +1744,33 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1744,4 +1744,33 @@ class ArticleTest < ActiveSupport::TestCase | ||
1744 | assert_nil article.author_id | 1744 | assert_nil article.author_id |
1745 | end | 1745 | end |
1746 | 1746 | ||
1747 | + should 'identify if belongs to forum' do | ||
1748 | + p = create_user('user_forum_test').person | ||
1749 | + forum = fast_create(Forum, :name => 'Forum test', :profile_id => p.id) | ||
1750 | + post = fast_create(TextileArticle, :name => 'First post', :profile_id => p.id, :parent_id => forum.id) | ||
1751 | + assert post.belongs_to_forum? | ||
1752 | + end | ||
1753 | + | ||
1754 | + should 'not belongs to forum' do | ||
1755 | + p = create_user('user_forum_test').person | ||
1756 | + blog = fast_create(Blog, :name => 'Not Forum', :profile_id => p.id) | ||
1757 | + a = fast_create(TextileArticle, :name => 'Not forum post', :profile_id => p.id, :parent_id => blog.id) | ||
1758 | + assert !a.belongs_to_forum? | ||
1759 | + end | ||
1760 | + | ||
1761 | + should 'not belongs to forum if do not have a parent' do | ||
1762 | + p = create_user('user_forum_test').person | ||
1763 | + a = fast_create(TextileArticle, :name => 'Orphan post', :profile_id => p.id) | ||
1764 | + assert !a.belongs_to_forum? | ||
1765 | + end | ||
1766 | + | ||
1767 | + should 'save image on create article' do | ||
1768 | + assert_difference Article, :count do | ||
1769 | + p = Article.create!(:name => 'test', :image_builder => { | ||
1770 | + :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') | ||
1771 | + }, :profile_id => @profile.id) | ||
1772 | + assert_equal p.image(true).filename, 'rails.png' | ||
1773 | + end | ||
1774 | + end | ||
1775 | + | ||
1747 | end | 1776 | end |
test/unit/block_test.rb
@@ -156,4 +156,13 @@ class BlockTest < ActiveSupport::TestCase | @@ -156,4 +156,13 @@ class BlockTest < ActiveSupport::TestCase | ||
156 | assert_equal box.environment, block.environment | 156 | assert_equal box.environment, block.environment |
157 | end | 157 | end |
158 | 158 | ||
159 | + should 'inform conditions for expiration on profile context' do | ||
160 | + conditions = Block.expire_on | ||
161 | + assert conditions[:profile].kind_of?(Array) | ||
162 | + end | ||
163 | + | ||
164 | + should 'inform conditions for expiration on environment context' do | ||
165 | + conditions = Block.expire_on | ||
166 | + assert conditions[:environment].kind_of?(Array) | ||
167 | + end | ||
159 | end | 168 | end |
test/unit/blog_helper_test.rb
@@ -94,10 +94,10 @@ class BlogHelperTest < ActiveSupport::TestCase | @@ -94,10 +94,10 @@ class BlogHelperTest < ActiveSupport::TestCase | ||
94 | should 'display link to file if post is an uploaded_file' do | 94 | should 'display link to file if post is an uploaded_file' do |
95 | file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :profile => profile, :published => true, :parent => blog) | 95 | file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :profile => profile, :published => true, :parent => blog) |
96 | 96 | ||
97 | - expects(:article_to_html).with(file).returns('TO HTML') | ||
98 | - | ||
99 | result = display_post(file) | 97 | result = display_post(file) |
100 | - assert_tag_in_string result, :content => /TO HTML/ | 98 | + assert_tag_in_string result, :tag => 'a', |
99 | + :attributes => { :href => file.public_filename }, | ||
100 | + :content => file.filename | ||
101 | end | 101 | end |
102 | 102 | ||
103 | should 'display image if post is an image' do | 103 | should 'display image if post is an image' do |
test/unit/category_test.rb
@@ -168,11 +168,11 @@ class CategoryTest < ActiveSupport::TestCase | @@ -168,11 +168,11 @@ class CategoryTest < ActiveSupport::TestCase | ||
168 | should "limit the possibile display colors" do | 168 | should "limit the possibile display colors" do |
169 | c = Category.new(:name => 'test category', :environment_id => @env.id) | 169 | c = Category.new(:name => 'test category', :environment_id => @env.id) |
170 | 170 | ||
171 | - c.display_color = 10 | 171 | + c.display_color = 16 |
172 | c.valid? | 172 | c.valid? |
173 | assert c.errors.invalid?(:display_color) | 173 | assert c.errors.invalid?(:display_color) |
174 | 174 | ||
175 | - valid = %w[ 1 2 3 4 ].map { |item| item.to_i } | 175 | + valid = (1..15).map { |item| item.to_i } |
176 | valid.each do |item| | 176 | valid.each do |item| |
177 | c.display_color = item | 177 | c.display_color = item |
178 | c.valid? | 178 | c.valid? |
test/unit/cms_helper_test.rb
@@ -41,6 +41,7 @@ class CmsHelperTest < ActiveSupport::TestCase | @@ -41,6 +41,7 @@ class CmsHelperTest < ActiveSupport::TestCase | ||
41 | should 'display image and link if article is an image' do | 41 | should 'display image and link if article is an image' do |
42 | profile = fast_create(Profile) | 42 | profile = fast_create(Profile) |
43 | file = UploadedFile.create!(:profile => profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | 43 | file = UploadedFile.create!(:profile => profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) |
44 | + file = FilePresenter.for file | ||
44 | icon = icon_for_article(file) | 45 | icon = icon_for_article(file) |
45 | expects(:image_tag).with(icon).returns('icon') | 46 | expects(:image_tag).with(icon).returns('icon') |
46 | 47 |
test/unit/comment_test.rb
@@ -285,22 +285,6 @@ class CommentTest < ActiveSupport::TestCase | @@ -285,22 +285,6 @@ class CommentTest < ActiveSupport::TestCase | ||
285 | assert_equal [c1,c3], c.reload.children | 285 | assert_equal [c1,c3], c.reload.children |
286 | end | 286 | end |
287 | 287 | ||
288 | - should "return activities comments as a thread" do | ||
289 | - person = fast_create(Person) | ||
290 | - a = TextileArticle.create!(:profile => person, :name => 'My article', :body => 'Article body') | ||
291 | - c0 = Comment.create!(:source => a, :body => 'My comment', :author => person) | ||
292 | - c1 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person) | ||
293 | - c2 = Comment.create!(:reply_of_id => c1.id, :source => a, :body => 'bla', :author => person) | ||
294 | - c3 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person) | ||
295 | - c4 = Comment.create!(:source => a, :body => 'My comment', :author => person) | ||
296 | - result = a.activity.comments_as_thread | ||
297 | - assert_equal c0, result[0] | ||
298 | - assert_equal [c1, c3], result[0].replies | ||
299 | - assert_equal [c2], result[0].replies[0].replies | ||
300 | - assert_equal c4, result[1] | ||
301 | - assert result[1].replies.empty? | ||
302 | - end | ||
303 | - | ||
304 | should 'provide author url for authenticated user' do | 288 | should 'provide author url for authenticated user' do |
305 | author = Person.new | 289 | author = Person.new |
306 | author.expects(:url).returns('http://blabla.net/author') | 290 | author.expects(:url).returns('http://blabla.net/author') |
@@ -447,7 +431,7 @@ class CommentTest < ActiveSupport::TestCase | @@ -447,7 +431,7 @@ class CommentTest < ActiveSupport::TestCase | ||
447 | end | 431 | end |
448 | 432 | ||
449 | class EverythingIsSpam < Noosfero::Plugin | 433 | class EverythingIsSpam < Noosfero::Plugin |
450 | - def check_comment_for_spam(comment) | 434 | + def check_for_spam(comment) |
451 | comment.spam! | 435 | comment.spam! |
452 | end | 436 | end |
453 | end | 437 | end |
@@ -469,11 +453,11 @@ class CommentTest < ActiveSupport::TestCase | @@ -469,11 +453,11 @@ class CommentTest < ActiveSupport::TestCase | ||
469 | attr_accessor :marked_as_ham | 453 | attr_accessor :marked_as_ham |
470 | end | 454 | end |
471 | 455 | ||
472 | - def comment_marked_as_spam(c) | 456 | + def marked_as_spam(c) |
473 | self.class.marked_as_spam = c | 457 | self.class.marked_as_spam = c |
474 | end | 458 | end |
475 | 459 | ||
476 | - def comment_marked_as_ham(c) | 460 | + def marked_as_ham(c) |
477 | self.class.marked_as_ham = c | 461 | self.class.marked_as_ham = c |
478 | end | 462 | end |
479 | end | 463 | end |
@@ -523,7 +507,6 @@ class CommentTest < ActiveSupport::TestCase | @@ -523,7 +507,6 @@ class CommentTest < ActiveSupport::TestCase | ||
523 | comment.spam! | 507 | comment.spam! |
524 | log = File.open('log/test_spammers.log') | 508 | log = File.open('log/test_spammers.log') |
525 | assert_match "Comment-id: #{comment.id} IP: 192.168.0.1", log.read | 509 | assert_match "Comment-id: #{comment.id} IP: 192.168.0.1", log.read |
526 | - SpammerLogger.clean_log | ||
527 | end | 510 | end |
528 | 511 | ||
529 | should 'not need moderation if article is not moderated' do | 512 | should 'not need moderation if article is not moderated' do |
test/unit/content_viewer_helper_test.rb
@@ -18,8 +18,15 @@ class ContentViewerHelperTest < ActiveSupport::TestCase | @@ -18,8 +18,15 @@ class ContentViewerHelperTest < ActiveSupport::TestCase | ||
18 | result = article_title(post) | 18 | result = article_title(post) |
19 | assert_tag_in_string result, :tag => 'span', :content => show_date(post.published_at) | 19 | assert_tag_in_string result, :tag => 'span', :content => show_date(post.published_at) |
20 | end | 20 | end |
21 | + | ||
22 | + should 'display published-at for forum posts' do | ||
23 | + forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id) | ||
24 | + post = TextileArticle.create!(:name => 'post test', :profile => profile, :parent => forum) | ||
25 | + result = article_title(post) | ||
26 | + assert_tag_in_string result, :tag => 'span', :content => show_date(post.published_at) | ||
27 | + end | ||
21 | 28 | ||
22 | - should 'not display published-at for non-blog posts' do | 29 | + should 'not display published-at for non-blog and non-forum posts' do |
23 | article = TextileArticle.create!(:name => 'article for test', :profile => profile) | 30 | article = TextileArticle.create!(:name => 'article for test', :profile => profile) |
24 | result = article_title(article) | 31 | result = article_title(article) |
25 | assert_no_match /<span class="date">#{show_date(article.published_at)}<\/span><span class="author">, by .*#{profile.identifier}/, result | 32 | assert_no_match /<span class="date">#{show_date(article.published_at)}<\/span><span class="author">, by .*#{profile.identifier}/, result |
test/unit/environment_statistics_block_test.rb
@@ -84,8 +84,8 @@ class EnvironmentStatisticsBlockTest < ActiveSupport::TestCase | @@ -84,8 +84,8 @@ class EnvironmentStatisticsBlockTest < ActiveSupport::TestCase | ||
84 | end | 84 | end |
85 | 85 | ||
86 | should 'not display enterprises if disabled' do | 86 | should 'not display enterprises if disabled' do |
87 | - env = Environment.new | ||
88 | - env.enable('disable_asset_enterprises') | 87 | + env = fast_create(Environment) |
88 | + env.enable('disable_asset_enterprises', false) | ||
89 | 89 | ||
90 | block = EnvironmentStatisticsBlock.new | 90 | block = EnvironmentStatisticsBlock.new |
91 | block.stubs(:owner).returns(env) | 91 | block.stubs(:owner).returns(env) |
test/unit/environment_test.rb
@@ -34,22 +34,22 @@ class EnvironmentTest < ActiveSupport::TestCase | @@ -34,22 +34,22 @@ class EnvironmentTest < ActiveSupport::TestCase | ||
34 | end | 34 | end |
35 | 35 | ||
36 | def test_features | 36 | def test_features |
37 | - v = Environment.new | ||
38 | - v.enable('feature1') | 37 | + v = fast_create(Environment) |
38 | + v.enable('feature1', false) | ||
39 | assert v.enabled?('feature1') | 39 | assert v.enabled?('feature1') |
40 | - v.disable('feature1') | 40 | + v.disable('feature1', false) |
41 | assert !v.enabled?('feature1') | 41 | assert !v.enabled?('feature1') |
42 | end | 42 | end |
43 | 43 | ||
44 | def test_enabled_features | 44 | def test_enabled_features |
45 | - v = Environment.new | ||
46 | - v.enabled_features = [ 'feature1', 'feature2' ] | 45 | + v = fast_create(Environment) |
46 | + v.enable('feature1', false) | ||
47 | + v.enable('feature2', false) | ||
47 | assert v.enabled?('feature1') && v.enabled?('feature2') && !v.enabled?('feature3') | 48 | assert v.enabled?('feature1') && v.enabled?('feature2') && !v.enabled?('feature3') |
48 | end | 49 | end |
49 | 50 | ||
50 | def test_enabled_features_no_features_enabled | 51 | def test_enabled_features_no_features_enabled |
51 | - v = Environment.new | ||
52 | - v.enabled_features = nil | 52 | + v = fast_create(Environment) |
53 | assert !v.enabled?('feature1') && !v.enabled?('feature2') && !v.enabled?('feature3') | 53 | assert !v.enabled?('feature1') && !v.enabled?('feature2') && !v.enabled?('feature3') |
54 | end | 54 | end |
55 | 55 | ||
@@ -1074,10 +1074,10 @@ class EnvironmentTest < ActiveSupport::TestCase | @@ -1074,10 +1074,10 @@ class EnvironmentTest < ActiveSupport::TestCase | ||
1074 | end | 1074 | end |
1075 | 1075 | ||
1076 | should 'get enabled features' do | 1076 | should 'get enabled features' do |
1077 | - env = Environment.new | ||
1078 | - env.enable('feature1') | ||
1079 | - env.enable('feature2') | ||
1080 | - env.disable('feature3') | 1077 | + env = fast_create(Environment) |
1078 | + env.enable('feature1', false) | ||
1079 | + env.enable('feature2', false) | ||
1080 | + env.disable('feature3', false) | ||
1081 | 1081 | ||
1082 | assert_includes env.enabled_features.keys, 'feature1' | 1082 | assert_includes env.enabled_features.keys, 'feature1' |
1083 | assert_includes env.enabled_features.keys, 'feature2' | 1083 | assert_includes env.enabled_features.keys, 'feature2' |
@@ -0,0 +1,61 @@ | @@ -0,0 +1,61 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class FilePresenterTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'notify about deprecated method UploadedFile.icon_name' do | ||
6 | + profile = fast_create(Profile) | ||
7 | + file = UploadedFile.create!( | ||
8 | + :profile => profile, | ||
9 | + :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') | ||
10 | + ) | ||
11 | + assert_raise NoMethodError do | ||
12 | + UploadedFile.icon_name file | ||
13 | + end | ||
14 | + ENV.stubs('[]').with('RAILS_ENV').returns('other') | ||
15 | + Rails.logger.expects(:warn) # must warn on any other RAILS_ENV | ||
16 | + stubs(:puts) | ||
17 | + UploadedFile.icon_name file | ||
18 | + end | ||
19 | + | ||
20 | + should 'notify about deprecated method UploadedFile#to_html' do | ||
21 | + profile = fast_create(Profile) | ||
22 | + file = UploadedFile.create!( | ||
23 | + :profile => profile, | ||
24 | + :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') | ||
25 | + ) | ||
26 | + assert_raise NoMethodError do | ||
27 | + file.to_html | ||
28 | + end | ||
29 | + ENV.stubs('[]').with('RAILS_ENV').returns('other') | ||
30 | + Rails.logger.expects(:warn) # must warn on any other RAILS_ENV | ||
31 | + stubs(:puts) | ||
32 | + file.to_html | ||
33 | + end | ||
34 | + | ||
35 | + should 'return a thumbnail as icon for images ' do | ||
36 | + f = UploadedFile.new | ||
37 | + f.stubs(:image?).returns(true) | ||
38 | + p = FilePresenter.for f | ||
39 | + p.expects(:public_filename).with(:icon).returns('/path/to/file.xyz') | ||
40 | + assert_equal '/path/to/file.xyz', p.icon_name | ||
41 | + end | ||
42 | + | ||
43 | + should 'not crach when accepts? method receives a pure article' do | ||
44 | + assert_nothing_raised do | ||
45 | + FilePresenter.for Article.new | ||
46 | + end | ||
47 | + end | ||
48 | + | ||
49 | + should 'not crach when accepts? method receives a non-sense object' do | ||
50 | + assert_nothing_raised do | ||
51 | + FilePresenter.for nil | ||
52 | + end | ||
53 | + assert_nothing_raised do | ||
54 | + FilePresenter.for({:key => 'value'}) | ||
55 | + end | ||
56 | + assert_nothing_raised do | ||
57 | + FilePresenter.for 'a string' | ||
58 | + end | ||
59 | + end | ||
60 | + | ||
61 | +end |
test/unit/folder_helper_test.rb
@@ -26,6 +26,7 @@ class FolderHelperTest < ActiveSupport::TestCase | @@ -26,6 +26,7 @@ class FolderHelperTest < ActiveSupport::TestCase | ||
26 | should 'display icon for images' do | 26 | should 'display icon for images' do |
27 | profile = fast_create(Profile) | 27 | profile = fast_create(Profile) |
28 | file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile) | 28 | file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile) |
29 | + file = FilePresenter.for file | ||
29 | process_delayed_job_queue | 30 | process_delayed_job_queue |
30 | 31 | ||
31 | assert_match /rails_icon\.png/, icon_for_article(file.reload) | 32 | assert_match /rails_icon\.png/, icon_for_article(file.reload) |
test/unit/link_list_block_test.rb
@@ -23,7 +23,6 @@ class LinkListBlockTest < ActiveSupport::TestCase | @@ -23,7 +23,6 @@ class LinkListBlockTest < ActiveSupport::TestCase | ||
23 | 23 | ||
24 | should 'list links' do | 24 | should 'list links' do |
25 | l = LinkListBlock.new(:links => [{:name => 'products', :address => '/cat/products'}]) | 25 | l = LinkListBlock.new(:links => [{:name => 'products', :address => '/cat/products'}]) |
26 | - l.expects(:links).returns([{:name => 'products', :address => '/cat/products'}]) | ||
27 | assert_match /products/, l.content | 26 | assert_match /products/, l.content |
28 | end | 27 | end |
29 | 28 | ||
@@ -83,4 +82,8 @@ class LinkListBlockTest < ActiveSupport::TestCase | @@ -83,4 +82,8 @@ class LinkListBlockTest < ActiveSupport::TestCase | ||
83 | assert_equal 'always', block.display | 82 | assert_equal 'always', block.display |
84 | end | 83 | end |
85 | 84 | ||
85 | + should 'have options for links target' do | ||
86 | + assert_equivalent LinkListBlock::TARGET_OPTIONS.map {|t|t[1]}, ['_self', '_blank', '_new'] | ||
87 | + end | ||
88 | + | ||
86 | end | 89 | end |
test/unit/plugin_manager_test.rb
@@ -61,6 +61,10 @@ class PluginManagerTest < ActiveSupport::TestCase | @@ -61,6 +61,10 @@ class PluginManagerTest < ActiveSupport::TestCase | ||
61 | end | 61 | end |
62 | 62 | ||
63 | should 'dispatch_first method returns the first plugin response if there is many plugins to responde the event' do | 63 | should 'dispatch_first method returns the first plugin response if there is many plugins to responde the event' do |
64 | + class Noosfero::Plugin | ||
65 | + def random_event | ||
66 | + end | ||
67 | + end | ||
64 | 68 | ||
65 | class Plugin1 < Noosfero::Plugin | 69 | class Plugin1 < Noosfero::Plugin |
66 | def random_event | 70 | def random_event |
test/unit/profile_list_block_test.rb
@@ -2,6 +2,8 @@ require File.dirname(__FILE__) + '/../test_helper' | @@ -2,6 +2,8 @@ require File.dirname(__FILE__) + '/../test_helper' | ||
2 | 2 | ||
3 | class ProfileListBlockTest < ActiveSupport::TestCase | 3 | class ProfileListBlockTest < ActiveSupport::TestCase |
4 | 4 | ||
5 | + include ActionView::Helpers::TagHelper | ||
6 | + | ||
5 | should 'describe itself' do | 7 | should 'describe itself' do |
6 | assert_not_equal Block.description, ProfileListBlock.description | 8 | assert_not_equal Block.description, ProfileListBlock.description |
7 | end | 9 | end |
@@ -32,6 +34,7 @@ class ProfileListBlockTest < ActiveSupport::TestCase | @@ -32,6 +34,7 @@ class ProfileListBlockTest < ActiveSupport::TestCase | ||
32 | self.expects(:profile_image_link).with(person2, :minor).once | 34 | self.expects(:profile_image_link).with(person2, :minor).once |
33 | self.expects(:profile_image_link).with(person3, :minor).once | 35 | self.expects(:profile_image_link).with(person3, :minor).once |
34 | 36 | ||
37 | + self.stubs(:tag).returns('<div></div>') | ||
35 | self.expects(:content_tag).returns('<div></div>').at_least_once | 38 | self.expects(:content_tag).returns('<div></div>').at_least_once |
36 | self.expects(:block_title).returns('block title').at_least_once | 39 | self.expects(:block_title).returns('block title').at_least_once |
37 | 40 |
test/unit/spammer_logger_test.rb
1 | require File.dirname(__FILE__) + '/../test_helper' | 1 | require File.dirname(__FILE__) + '/../test_helper' |
2 | 2 | ||
3 | class SpammerLoggerTest < ActiveSupport::TestCase | 3 | class SpammerLoggerTest < ActiveSupport::TestCase |
4 | - | ||
5 | - def setup | ||
6 | - SpammerLogger.reload_log | ||
7 | - end | ||
8 | - | ||
9 | - def teardown | ||
10 | - SpammerLogger.clean_log | ||
11 | - end | ||
12 | - | ||
13 | should 'log the spammer ip' do | 4 | should 'log the spammer ip' do |
14 | SpammerLogger.log('192.168.0.1') | 5 | SpammerLogger.log('192.168.0.1') |
15 | log = File.open('log/test_spammers.log') | 6 | log = File.open('log/test_spammers.log') |
@@ -22,5 +13,4 @@ class SpammerLoggerTest < ActiveSupport::TestCase | @@ -22,5 +13,4 @@ class SpammerLoggerTest < ActiveSupport::TestCase | ||
22 | log = File.open('log/test_spammers.log') | 13 | log = File.open('log/test_spammers.log') |
23 | assert_match "Comment-id: #{comment.id} IP: 192.168.0.1", log.read | 14 | assert_match "Comment-id: #{comment.id} IP: 192.168.0.1", log.read |
24 | end | 15 | end |
25 | - | ||
26 | end | 16 | end |
test/unit/suggest_article_test.rb
@@ -150,5 +150,78 @@ class SuggestArticleTest < ActiveSupport::TestCase | @@ -150,5 +150,78 @@ class SuggestArticleTest < ActiveSupport::TestCase | ||
150 | assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, email.subject) | 150 | assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, email.subject) |
151 | end | 151 | end |
152 | 152 | ||
153 | + class EverythingIsSpam < Noosfero::Plugin | ||
154 | + def check_for_spam(object) | ||
155 | + object.spam! | ||
156 | + end | ||
157 | + end | ||
158 | + | ||
159 | + should 'delegate spam detection to plugins' do | ||
160 | + Environment.default.enable_plugin(EverythingIsSpam) | ||
161 | + | ||
162 | + t1 = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com') | ||
163 | + | ||
164 | + EverythingIsSpam.any_instance.expects(:check_for_spam) | ||
165 | + | ||
166 | + t1.check_for_spam | ||
167 | + end | ||
168 | + | ||
169 | + class SpamNotification < Noosfero::Plugin | ||
170 | + class << self | ||
171 | + attr_accessor :marked_as_spam | ||
172 | + attr_accessor :marked_as_ham | ||
173 | + end | ||
174 | + | ||
175 | + def check_for_spam(c) | ||
176 | + # do nothing | ||
177 | + end | ||
178 | + | ||
179 | + def marked_as_spam(c) | ||
180 | + self.class.marked_as_spam = c | ||
181 | + end | ||
182 | + | ||
183 | + def marked_as_ham(c) | ||
184 | + self.class.marked_as_ham = c | ||
185 | + end | ||
186 | + end | ||
187 | + | ||
188 | + should 'notify plugins of suggest_articles being marked as spam' do | ||
189 | + Environment.default.enable_plugin(SpamNotification) | ||
190 | + | ||
191 | + t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') | ||
192 | + | ||
193 | + t.spam! | ||
194 | + process_delayed_job_queue | ||
195 | + | ||
196 | + assert_equal t, SpamNotification.marked_as_spam | ||
197 | + end | ||
198 | + | ||
199 | + should 'notify plugins of suggest_articles being marked as ham' do | ||
200 | + Environment.default.enable_plugin(SpamNotification) | ||
201 | + | ||
202 | + t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') | ||
203 | + | ||
204 | + t.ham! | ||
205 | + process_delayed_job_queue | ||
206 | + | ||
207 | + assert_equal t, SpamNotification.marked_as_ham | ||
208 | + end | ||
209 | + | ||
210 | + should 'store User-Agent' do | ||
211 | + t = SuggestArticle.new(:user_agent => 'foo') | ||
212 | + assert_equal 'foo', t.user_agent | ||
213 | + end | ||
214 | + | ||
215 | + should 'store referrer' do | ||
216 | + t = SuggestArticle.new(:referrer => 'bar') | ||
217 | + assert_equal 'bar', t.referrer | ||
218 | + end | ||
219 | + | ||
220 | + should 'log spammer ip after marking comment as spam' do | ||
221 | + t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com', :ip_address => '192.168.0.1') | ||
222 | + t.spam! | ||
223 | + log = File.open('log/test_spammers.log') | ||
224 | + assert_match "SuggestArticle-id: #{t.id} IP: 192.168.0.1", log.read | ||
225 | + end | ||
153 | 226 | ||
154 | end | 227 | end |
test/unit/task_test.rb
@@ -372,6 +372,55 @@ class TaskTest < ActiveSupport::TestCase | @@ -372,6 +372,55 @@ class TaskTest < ActiveSupport::TestCase | ||
372 | assert_includes Task.closed, canceled | 372 | assert_includes Task.closed, canceled |
373 | end | 373 | end |
374 | 374 | ||
375 | + should 'be ham by default' do # ham means not spam | ||
376 | + assert_equal false, Task.create.spam | ||
377 | + end | ||
378 | + | ||
379 | + should 'be able to mark tasks as spam/ham/unknown' do | ||
380 | + t = Task.new | ||
381 | + t.spam = true | ||
382 | + assert t.spam? | ||
383 | + assert !t.ham? | ||
384 | + | ||
385 | + t.spam = false | ||
386 | + assert t.ham? | ||
387 | + assert !t.spam? | ||
388 | + | ||
389 | + t.spam = nil | ||
390 | + assert !t.spam? | ||
391 | + assert !t.ham? | ||
392 | + end | ||
393 | + | ||
394 | + should 'be able to select non-spam tasks' do | ||
395 | + t1 = fast_create(Task) | ||
396 | + t2 = fast_create(Task, :spam => false) | ||
397 | + t3 = fast_create(Task, :spam => true) | ||
398 | + | ||
399 | + assert_equivalent [t1,t2], Task.without_spam | ||
400 | + end | ||
401 | + | ||
402 | + should 'be able to select spam tasks' do | ||
403 | + t1 = fast_create(Task) | ||
404 | + t2 = fast_create(Task, :spam => false) | ||
405 | + t3 = fast_create(Task, :spam => true) | ||
406 | + | ||
407 | + assert_equivalent [t3], Task.spam | ||
408 | + end | ||
409 | + | ||
410 | + should 'be able to mark as spam' do | ||
411 | + t1 = fast_create(Task) | ||
412 | + t1.spam! | ||
413 | + t1.reload | ||
414 | + assert t1.spam? | ||
415 | + end | ||
416 | + | ||
417 | + should 'be able to mark as ham' do | ||
418 | + t1 = fast_create(Task) | ||
419 | + t1.ham! | ||
420 | + t1.reload | ||
421 | + assert t1.ham? | ||
422 | + end | ||
423 | + | ||
375 | protected | 424 | protected |
376 | 425 | ||
377 | def sample_user | 426 | def sample_user |
test/unit/uploaded_file_test.rb
@@ -7,13 +7,6 @@ class UploadedFileTest < ActiveSupport::TestCase | @@ -7,13 +7,6 @@ class UploadedFileTest < ActiveSupport::TestCase | ||
7 | end | 7 | end |
8 | attr_reader :profile | 8 | attr_reader :profile |
9 | 9 | ||
10 | - should 'return a thumbnail as icon for images ' do | ||
11 | - f = UploadedFile.new | ||
12 | - f.expects(:image?).returns(true) | ||
13 | - f.expects(:public_filename).with(:icon).returns('/path/to/file.xyz') | ||
14 | - assert_equal '/path/to/file.xyz', UploadedFile.icon_name(f) | ||
15 | - end | ||
16 | - | ||
17 | should 'return a default icon for uploaded files' do | 10 | should 'return a default icon for uploaded files' do |
18 | assert_equal 'upload-file', UploadedFile.icon_name | 11 | assert_equal 'upload-file', UploadedFile.icon_name |
19 | end | 12 | end |
@@ -113,8 +106,11 @@ class UploadedFileTest < ActiveSupport::TestCase | @@ -113,8 +106,11 @@ class UploadedFileTest < ActiveSupport::TestCase | ||
113 | p = create_user('test_user').person | 106 | p = create_user('test_user').person |
114 | file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :profile => p) | 107 | file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :profile => p) |
115 | 108 | ||
109 | + ENV.stubs('[]').with('RAILS_ENV').returns('other') | ||
110 | + Rails.logger.expects(:warn) # warn about deprecatede usage of UploadedFile#to_html | ||
111 | + stubs(:puts) | ||
116 | stubs(:content_tag).returns('link') | 112 | stubs(:content_tag).returns('link') |
117 | - expects(:link_to).with(file.name, file.url, :class => file.css_class_name) | 113 | + expects(:link_to).with(file.name, file.url) |
118 | 114 | ||
119 | instance_eval(&file.to_html) | 115 | instance_eval(&file.to_html) |
120 | end | 116 | end |
@@ -206,13 +202,6 @@ class UploadedFileTest < ActiveSupport::TestCase | @@ -206,13 +202,6 @@ class UploadedFileTest < ActiveSupport::TestCase | ||
206 | file.destroy | 202 | file.destroy |
207 | end | 203 | end |
208 | 204 | ||
209 | - should 'return the default thumbnail image as icon for images ' do | ||
210 | - f = UploadedFile.new | ||
211 | - f.expects(:image?).returns(true) | ||
212 | - f.expects(:public_filename).with(:icon).returns('/path/to/file.xyz') | ||
213 | - assert_equal '/path/to/file.xyz', UploadedFile.icon_name(f) | ||
214 | - end | ||
215 | - | ||
216 | should 'store width and height after processing' do | 205 | should 'store width and height after processing' do |
217 | file = UploadedFile.create!(:profile => @profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | 206 | file = UploadedFile.create!(:profile => @profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) |
218 | file.create_thumbnails | 207 | file.create_thumbnails |
@@ -287,12 +276,6 @@ class UploadedFileTest < ActiveSupport::TestCase | @@ -287,12 +276,6 @@ class UploadedFileTest < ActiveSupport::TestCase | ||
287 | assert_equal '', f.lead | 276 | assert_equal '', f.lead |
288 | end | 277 | end |
289 | 278 | ||
290 | - should 'survive when try to get icon_name from a file with mime_type nil' do | ||
291 | - f = UploadedFile.new | ||
292 | - f.expects(:mime_type).returns(nil) | ||
293 | - assert_equal 'upload-file', UploadedFile.icon_name(f) | ||
294 | - end | ||
295 | - | ||
296 | should 'upload to a folder with same name as the schema if database is postgresql' do | 279 | should 'upload to a folder with same name as the schema if database is postgresql' do |
297 | uses_postgresql 'image_schema_one' | 280 | uses_postgresql 'image_schema_one' |
298 | file1 = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => @profile) | 281 | file1 = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => @profile) |
@@ -352,4 +335,26 @@ class UploadedFileTest < ActiveSupport::TestCase | @@ -352,4 +335,26 @@ class UploadedFileTest < ActiveSupport::TestCase | ||
352 | assert_equal 1, ActionTracker::Record.find_all_by_verb('upload_image').count | 335 | assert_equal 1, ActionTracker::Record.find_all_by_verb('upload_image').count |
353 | end | 336 | end |
354 | 337 | ||
338 | + { | ||
339 | + nil => 5.megabytes, # default | ||
340 | + '1KB' => 1.kilobytes, | ||
341 | + '2MB' => 2.megabyte, | ||
342 | + '3GB' => 3.gigabytes, | ||
343 | + '4TB' => 4.terabytes, | ||
344 | + '6 MB' => 6.megabytes, # allow whitespace between number and unit | ||
345 | + '0.5 GB' => 512.megabytes, # allow floating point numbers | ||
346 | + '2' => 2.megabytes, # assume MB as unit by default | ||
347 | + 'INVALID' => 5.megabytes, # use default for invalid input | ||
348 | + '1ZYX' => 5.megabytes, # use default for invalid input | ||
349 | + }.each do |input,output| | ||
350 | + test 'maximum upload size: convert %s into %s' % [input, output] do | ||
351 | + NOOSFERO_CONF.expects(:[]).with('max_upload_size').returns(input) | ||
352 | + assert_equal output, UploadedFile.max_size | ||
353 | + end | ||
354 | + end | ||
355 | + test 'max_size should always return an integer' do | ||
356 | + NOOSFERO_CONF.expects(:[]).with('max_upload_size').returns("0.5 GB") | ||
357 | + assert_instance_of Fixnum, UploadedFile.max_size | ||
358 | + end | ||
359 | + | ||
355 | end | 360 | end |
vendor/plugins/action_tracker_has_comments/init.rb
1 | # monkey patch to add comments on action_tracker | 1 | # monkey patch to add comments on action_tracker |
2 | 2 | ||
3 | -ActionTracker::Record.module_eval do | 3 | +Rails.configuration.to_prepare do |
4 | + ActionTracker::Record.module_eval do | ||
4 | 5 | ||
5 | - has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :finder_sql => 'SELECT * FROM comments WHERE #{conditions_for_comments} ORDER BY created_at ASC', :counter_sql => 'SELECT * FROM comments WHERE #{conditions_for_comments}' | 6 | + has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, |
7 | + :finder_sql => 'SELECT * FROM comments WHERE #{conditions_for_comments} ORDER BY created_at ASC', | ||
8 | + :counter_sql => 'SELECT COUNT(*) FROM comments WHERE #{conditions_for_comments}' | ||
6 | 9 | ||
7 | - def conditions_for_comments | ||
8 | - type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id]) | ||
9 | - "source_type = '#{type}' AND source_id = '#{id}'" | ||
10 | - end | ||
11 | - | ||
12 | - def comments_as_thread | ||
13 | - result = {} | ||
14 | - root = [] | ||
15 | - self.comments.each do |c| | ||
16 | - c.replies = [] | ||
17 | - result[c.id] ||= c | ||
18 | - c.reply_of_id.nil? ? root << c : result[c.reply_of_id].replies << c | 10 | + def conditions_for_comments |
11 | + type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id]) | ||
12 | + "source_type = '#{type}' AND source_id = '#{id}' AND reply_of_id IS NULL" | ||
19 | end | 13 | end |
20 | - root | ||
21 | - end | ||
22 | 14 | ||
15 | + end | ||
23 | end | 16 | end |
vendor/plugins/monkey_patches/rescue_delayed_job_crashes/init.rb
1 | Delayed::Worker.module_eval do | 1 | Delayed::Worker.module_eval do |
2 | # based on https://groups.google.com/forum/#!topic/delayed_job/ZGMUFFppNgs | 2 | # based on https://groups.google.com/forum/#!topic/delayed_job/ZGMUFFppNgs |
3 | class Delayed::Worker::ExceptionNotification < ActionMailer::Base | 3 | class Delayed::Worker::ExceptionNotification < ActionMailer::Base |
4 | - def mail error | 4 | + def mail job, error |
5 | environment = Environment.default | 5 | environment = Environment.default |
6 | 6 | ||
7 | recipients NOOSFERO_CONF['exception_recipients'] | 7 | recipients NOOSFERO_CONF['exception_recipients'] |
8 | from environment.contact_email | 8 | from environment.contact_email |
9 | reply_to environment.contact_email | 9 | reply_to environment.contact_email |
10 | - subject "[#{environment.name}] DelayedJob: #{error.message}" | ||
11 | - body render(:text => error.backtrace.join("\n")) | 10 | + subject "[#{environment.name}] DelayedJob ##{job.id}: #{error.message}" |
11 | + body render(:text => " | ||
12 | +Job: | ||
13 | +#{job.inspect} | ||
14 | + | ||
15 | +Handler: | ||
16 | +#{job.handler} | ||
17 | + | ||
18 | +Backtrace: | ||
19 | +#{error.backtrace.join("\n")} | ||
20 | + ") | ||
12 | end | 21 | end |
13 | end | 22 | end |
14 | 23 | ||
15 | def handle_failed_job_with_notification(job, error) | 24 | def handle_failed_job_with_notification(job, error) |
16 | - Delayed::Worker::ExceptionNotification.deliver_mail error if NOOSFERO_CONF['exception_recipients'].present? | 25 | + Delayed::Worker::ExceptionNotification.deliver_mail job, error if NOOSFERO_CONF['exception_recipients'].present? |
17 | handle_failed_job_without_notification job, error | 26 | handle_failed_job_without_notification job, error |
18 | end | 27 | end |
19 | alias_method_chain :handle_failed_job, :notification | 28 | alias_method_chain :handle_failed_job, :notification |