Commit fc8557c3c6c62a489bab035ea63f3ee7a10c5db0

Authored by Daniela Feitosa
2 parents 5fb09b51 85b0bd4d

Merge commit 'refs/merge-requests/213' of git://gitorious.org/noosfero/noosfero …

…into merge-requests/213

Conflicts:
	app/controllers/application_controller.rb
	app/helpers/application_helper.rb
	app/views/content_viewer/_comment.rhtml
	app/views/content_viewer/view_page.rhtml
	lib/noosfero/plugin.rb
	test/functional/content_viewer_controller_test.rb
	test/unit/comment_test.rb
Showing 38 changed files with 650 additions and 68 deletions   Show diff stats
app/controllers/application_controller.rb
... ... @@ -114,7 +114,9 @@ class ApplicationController < ActionController::Base
114 114 # plugin to the current controller being initialized.
115 115 def init_noosfero_plugins_controller_filters
116 116 plugins.each do |plugin|
117   - plugin.send(self.class.name.underscore + '_filters').each do |plugin_filter|
  117 + filters = plugin.send(self.class.name.underscore + '_filters')
  118 + filters = [filters] if !filters.kind_of?(Array)
  119 + filters.each do |plugin_filter|
118 120 self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {}))
119 121 self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block])
120 122 end
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -2,6 +2,8 @@ class ContentViewerController < ApplicationController
2 2  
3 3 needs_profile
4 4  
  5 + before_filter :comment_author, :only => :edit_comment
  6 +
5 7 helper ProfileHelper
6 8 helper TagsHelper
7 9  
... ... @@ -121,6 +123,22 @@ class ContentViewerController < ApplicationController
121 123 end
122 124 end
123 125  
  126 + def edit_comment
  127 + path = params[:page].join('/')
  128 + @page = profile.articles.find_by_path(path)
  129 + @form_div = 'opened'
  130 + @comment = Comment.find(params[:id])
  131 + if request.post?
  132 + begin
  133 + @comment.update_attributes(params[:comment])
  134 + session[:notice] = _('Comment updated.')
  135 + redirect_to :action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path
  136 + rescue
  137 + session[:notice] = _('Comment could not be updated.')
  138 + end
  139 + end
  140 + end
  141 +
124 142 protected
125 143  
126 144 def add_comment
... ... @@ -198,4 +216,9 @@ class ContentViewerController < ApplicationController
198 216 end
199 217 end
200 218  
  219 + def comment_author
  220 + comment = Comment.find(params[:id])
  221 + render_access_denied if comment.author.blank? || comment.author != user
  222 + end
  223 +
201 224 end
... ...
app/helpers/application_helper.rb
... ... @@ -1336,6 +1336,19 @@ module ApplicationHelper
1336 1336 end
1337 1337 end
1338 1338  
  1339 + def expirable_link_to(expired, content, url, options = {})
  1340 + if expired
  1341 + options[:class] = (options[:class] || '') + ' disabled'
  1342 + content_tag('a', ' '+content_tag('span', content), options)
  1343 + else
  1344 + link_to content, url, options
  1345 + end
  1346 + end
  1347 +
  1348 + def remove_content_button(action)
  1349 + @plugins.dispatch("content_remove_#{action.to_s}", @page).include?(true)
  1350 + end
  1351 +
1339 1352 def template_options(klass, field_name)
1340 1353 return '' if klass.templates.count == 0
1341 1354 return hidden_field_tag("#{field_name}[template_id]", klass.templates.first.id) if klass.templates.count == 1
... ... @@ -1401,4 +1414,19 @@ module ApplicationHelper
1401 1414 result
1402 1415 end
1403 1416  
  1417 + def expirable_content_reference(content, action, text, url, options = {})
  1418 + reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first
  1419 + options[:title] = reason
  1420 + expirable_link_to reason.present?, text, url, options
  1421 + end
  1422 +
  1423 + def expirable_button(content, action, text, url, options = {})
  1424 + options[:class] = "button with-text icon-#{action.to_s}"
  1425 + expirable_content_reference content, action, text, url, options
  1426 + end
  1427 +
  1428 + def expirable_comment_link(content, action, text, url, options = {})
  1429 + options[:class] = "comment-footer comment-footer-link comment-footer-hide"
  1430 + expirable_content_reference content, action, text, url, options
  1431 + end
1404 1432 end
... ...
app/helpers/cms_helper.rb
... ... @@ -42,13 +42,25 @@ module CmsHelper
42 42  
43 43 def display_spread_button(profile, article)
44 44 if profile.person?
45   - button_without_text :spread, _('Spread this'), :action => 'publish', :id => article.id
  45 + expirable_button article, :spread, _('Spread this'), :action => 'publish', :id => article.id
46 46 elsif profile.community? && environment.portal_community
47   - button_without_text :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id
  47 + expirable_button article, :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id
48 48 end
49 49 end
50 50  
51 51 def display_delete_button(article)
52   - button_without_text :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article)
  52 + expirable_button article, :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article)
  53 + end
  54 +
  55 + def expirable_button(content, action, title, url, options = {})
  56 + reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first
  57 + if reason.present?
  58 + options[:class] = (options[:class] || '') + ' disabled'
  59 + options[:disabled] = 'disabled'
  60 + options.delete(:confirm)
  61 + options.delete(:method)
  62 + title = reason
  63 + end
  64 + button_without_text action.to_sym, title, url, options
53 65 end
54 66 end
... ...
app/models/comment.rb
... ... @@ -28,6 +28,8 @@ class Comment < ActiveRecord::Base
28 28  
29 29 xss_terminate :only => [ :body, :title, :name ], :on => 'validation'
30 30  
  31 + delegate :environment, :to => :source
  32 +
31 33 def action_tracker_target
32 34 self.article.profile
33 35 end
... ...
app/views/cms/view.rhtml
... ... @@ -49,13 +49,13 @@
49 49 <%= article.class.short_description %>
50 50 </td>
51 51 <td class="article-controls">
52   - <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => article.id %>
  52 + <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %>
53 53 <%= button_without_text :eyes, _('Public view'), article.view_url %>
54   - <%= display_spread_button(profile, article) unless article.folder? %>
55   - <% if !environment.enabled?('cant_change_homepage') %>
56   - <%= button_without_text :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>
  54 + <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%>
  55 + <% 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 %>
57 57 <% end %>
58   - <%= display_delete_button(article) %>
  58 + <%= display_delete_button(article) if !remove_content_button(:delete) %>
59 59 </td>
60 60 </tr>
61 61 <% end %>
... ...
app/views/content_viewer/_article_toolbar.rhtml
1 1 <div<%= user && " class='logged-in'" %>>
2 2 <div id="article-actions">
3 3  
4   - <% if @page.allow_edit?(user) %>
5   - <%= link_to content_tag( 'span', label_for_edit_article(@page) ),
6   - profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }),
7   - :class => 'button with-text icon-edit' %>
  4 +
  5 + <% if @page.allow_edit?(user) && !remove_content_button(:edit) %>
  6 + <% content = content_tag('span', label_for_edit_article(@page)) %>
  7 + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }) %>
  8 + <%= expirable_button @page, :edit, content, url %>
8 9 <% end %>
9 10  
10   - <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) %>
11   - <%= link_to content_tag( 'span', _('Delete') ),
12   - profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page}),
13   - :method => :post,
14   - :class => 'button with-text icon-delete',
15   - :confirm => delete_article_message(@page) %>
  11 + <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) && !remove_content_button(:delete)%>
  12 + <% content = content_tag( 'span', _('Delete') ) %>
  13 + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page}) %>
  14 + <% options = {:method => :post, :confirm => delete_article_message(@page)} %>
  15 + <%= expirable_button @page, :delete, content, url, options %>
16 16 <% end %>
17 17  
18   - <% if !@page.folder? && @page.allow_spread?(user) %>
  18 + <% if !@page.folder? && @page.allow_spread?(user) && !remove_content_button(:spread) %>
  19 + <% content = content_tag( 'span', _('Spread this') ) %>
  20 + <% url = nil %>
19 21 <% if profile.kind_of?(Person) %>
20   - <%= link_to content_tag( 'span', _('Spread this') ),
21   - profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page }),
22   - :class => 'button with-text icon-spread' %>
  22 + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page }) %>
23 23 <% elsif profile.kind_of?(Community) && environment.portal_community %>
24   - <%= link_to content_tag( 'span', _('Spread this') ),
25   - profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page }),
26   - :class => 'button with-text icon-spread' %>
  24 + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page }) %>
27 25 <% end %>
  26 + <%= expirable_button @page, :spread, content, url if url %>
28 27 <% end %>
29 28  
30 29 <% if !@page.gallery? && @page.allow_create?(user) %>
31   - <%= link_to _('Add translation'),
32   - profile.admin_url.merge(:controller => 'cms', :action => 'new',
33   - :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)),
34   - :type => @page.type, :article => { :translation_of_id => @page.native_translation.id }),
35   - :class => 'button with-text icon-locale' if @page.translatable? && !@page.native_translation.language.blank? %>
  30 + <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %>
  31 + <% content = _('Add translation') %>
  32 + <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %>
  33 + <% url = profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => parent_id, :type => @page.type, :article => { :translation_of_id => @page.native_translation.id })%>
  34 + <%= expirable_button @page, :locale, content, url %>
  35 + <% end %>
  36 +
36 37 <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %>
37 38 <% end %>
38 39  
... ... @@ -40,8 +41,11 @@
40 41 <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) %>
41 42 <% end %>
42 43  
43   - <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) %>
44   - <%= link_to content_tag( 'span', _('Suggest an article') ), profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}), :id => 'suggest-article-link', :class => 'button with-text icon-new' %>
  44 + <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %>
  45 + <% content = content_tag( 'span', _('Suggest an article') ) %>
  46 + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %>
  47 + <% options = {:id => 'suggest-article-link'} %>
  48 + <%= expirable_button @page, :suggest, content, url, options %>
45 49 <% end %>
46 50  
47 51 <%= report_abuse(profile, :link, @page) %>
... ...
app/views/content_viewer/_comment.rhtml
... ... @@ -75,6 +75,10 @@
75 75 :class => 'comment-footer comment-footer-link comment-footer-hide',
76 76 :id => 'comment-reply-to-' + comment.id.to_s
77 77 %>
  78 + <% if comment.author && comment.author == user %>
  79 + &nbsp;
  80 + <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %>
  81 + <% end %>
78 82 <% end %>
79 83 </div>
80 84  
... ...
app/views/content_viewer/_comment_form.rhtml
... ... @@ -39,7 +39,7 @@ function submit_comment_form(button) {
39 39 d.find('input[name=comment[title]], textarea').val('');
40 40 d.find('.comment_form input[name=comment[<%= focus_on %>]]').focus();
41 41 }">
42   - <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %>
  42 + <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') if display_link %>
43 43 </h4>
44 44  
45 45 <% unless pass_without_comment_captcha? %>
... ... @@ -59,7 +59,7 @@ function submit_comment_form(button) {
59 59 </script>
60 60 <% end %>
61 61  
62   -<% form_tag( url_for(@page.view_url.merge({:only_path => true})), { :class => 'comment_form' } ) do %>
  62 +<% form_tag( url, { :class => 'comment_form' } ) do %>
63 63 <%= hidden_field_tag(:confirm, 'false') %>
64 64  
65 65 <%= required_fields_message %>
... ... @@ -84,7 +84,11 @@ function submit_comment_form(button) {
84 84  
85 85 <% button_bar do %>
86 86 <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %>
87   - <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %>
  87 + <% if cancel_triggers_hide %>
  88 + <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %>
  89 + <% else %>
  90 + <%= button('cancel', _('Cancel'), {:action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path})%>
  91 + <% end %>
88 92 <% end %>
89 93 <% end %>
90 94  
... ...
app/views/content_viewer/edit_comment.html.erb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<h1><%= _('Edit comment') %></h1>
  2 +
  3 +<%= render :partial => 'comment_form', :locals => {:url => {:action => 'edit_comment', :profile => profile.identifier}, :display_link => false, :cancel_triggers_hide => false} %>
... ...
app/views/content_viewer/view_page.rhtml
... ... @@ -98,7 +98,7 @@
98 98 </ul>
99 99  
100 100 <% if @page.accept_comments? %>
101   - <div id="page-comment-form"><%= render :partial => 'comment_form' %></div>
  101 + <div id="page-comment-form"><%= render :partial => 'comment_form', :locals => {:url => url_for(@page.view_url.merge({:only_path => true})), :display_link => true, :cancel_triggers_hide => true}%></div>
102 102 <% end %>
103 103 </div><!-- end class="comments" -->
104 104  
... ...
app/views/profile/_comment.rhtml
... ... @@ -62,6 +62,10 @@
62 62 </script>
63 63 <% end %>
64 64 <%= report_abuse(comment.author, :comment_link, comment) if comment.author %>
  65 + <% if comment.author && comment.author == user %>
  66 + <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %>
  67 + <%= content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') %>
  68 + <% end %>
65 69 <%= link_to_function _('Reply'),
66 70 "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id,
67 71 :class => 'comment-footer comment-footer-link comment-footer-hide',
... ...
config/routes.rb
... ... @@ -121,9 +121,12 @@ ActionController::Routing::Routes.draw do |map|
121 121 # cache stuff - hack
122 122 map.cache 'public/:action/:id', :controller => 'public'
123 123  
  124 + map.connect ':profile/edit_comment/:id/*page', :controller => 'content_viewer', :action => 'edit_comment', :profile => /#{Noosfero.identifier_format}/
  125 +
124 126 # match requests for profiles that don't have a custom domain
125 127 map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } }
126 128  
  129 +
127 130 # match requests for content in domains hosted for profiles
128 131 map.connect '*page', :controller => 'content_viewer', :action => 'view_page'
129 132  
... ...
lib/noosfero/plugin.rb
... ... @@ -211,28 +211,6 @@ class Noosfero::Plugin
211 211 nil
212 212 end
213 213  
214   - # This is a generic hotspot for all controllers on Noosfero.
215   - # If any plugin wants to define filters to run on any controller, the name of
216   - # the hotspot must be in the following form: <underscored_controller_name>_filters.
217   - # Example: for ProfileController the hotspot is profile_controller_filters
218   - #
219   - # -> Adds a filter to a controller
220   - # returns = { :type => type,
221   - # :method_name => method_name,
222   - # :options => {:opt1 => opt1, :opt2 => opt2},
223   - # :block => Proc or lambda block}
224   - # type = 'before_filter' or 'after_filter'
225   - # method_name = The name of the filter
226   - # option = Filter options, like :only or :except
227   - # block = Block that the filter will call
228   - def method_missing(method, *args, &block)
229   - if method.to_s =~ /^(.+)_controller_filters$/
230   - []
231   - else
232   - super
233   - end
234   - end
235   -
236 214 # This method will be called just before a comment is saved to the database.
237 215 #
238 216 # It can modify the comment in several ways. In special, a plugin can call
... ... @@ -333,4 +311,40 @@ class Noosfero::Plugin
333 311 nil
334 312 end
335 313  
  314 + def method_missing(method, *args, &block)
  315 + # This is a generic hotspot for all controllers on Noosfero.
  316 + # If any plugin wants to define filters to run on any controller, the name of
  317 + # the hotspot must be in the following form: <underscored_controller_name>_filters.
  318 + # Example: for ProfileController the hotspot is profile_controller_filters
  319 + #
  320 + # -> Adds a filter to a controller
  321 + # returns = { :type => type,
  322 + # :method_name => method_name,
  323 + # :options => {:opt1 => opt1, :opt2 => opt2},
  324 + # :block => Proc or lambda block}
  325 + # type = 'before_filter' or 'after_filter'
  326 + # method_name = The name of the filter
  327 + # option = Filter options, like :only or :except
  328 + # block = Block that the filter will call
  329 + if method.to_s =~ /^(.+)_controller_filters$/
  330 + []
  331 + # -> Removes the action button from the content
  332 + # returns = boolean
  333 + elsif method.to_s =~ /^content_remove_(#{content_actions.join('|')})$/
  334 + nil
  335 + # -> Expire the action button from the content
  336 + # returns = string with reason of expiration
  337 + elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/
  338 + nil
  339 + else
  340 + super
  341 + end
  342 + end
  343 +
  344 + private
  345 +
  346 + def content_actions
  347 + %w[edit delete spread locale suggest home]
  348 + end
  349 +
336 350 end
... ...
plugins/tolerance_time/controllers/tolerance_time_plugin_myprofile_controller.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +class ToleranceTimePluginMyprofileController < MyProfileController
  2 + def index
  3 + @tolerance = ToleranceTimePlugin::Tolerance.find_by_profile_id(profile.id) || ToleranceTimePlugin::Tolerance.create!(:profile => profile)
  4 + convert_values
  5 + if request.post?
  6 + begin
  7 + convert_params
  8 + @tolerance.update_attributes!(params[:tolerance])
  9 + convert_values
  10 + session[:notice] = _('Tolerance updated')
  11 + rescue
  12 + session[:notice] = _('Tolerance could not be updated')
  13 + end
  14 + end
  15 + end
  16 +
  17 + private
  18 +
  19 + def convert_params
  20 + params[:tolerance][:content_tolerance] = params[:tolerance][:content_tolerance].to_i * params[:content_tolerance_unit].to_i if !params[:tolerance][:content_tolerance].blank?
  21 + params[:tolerance][:comment_tolerance] = params[:tolerance][:comment_tolerance].to_i * params[:comment_tolerance_unit].to_i if !params[:tolerance][:comment_tolerance].blank?
  22 + end
  23 +
  24 + def convert_values
  25 + @content_default_unit = select_unit(@tolerance.content_tolerance)
  26 + @comment_default_unit = select_unit(@tolerance.comment_tolerance)
  27 + @tolerance.content_tolerance /= @content_default_unit if !@tolerance.content_tolerance.nil?
  28 + @tolerance.comment_tolerance /= @comment_default_unit if !@tolerance.comment_tolerance.nil?
  29 + end
  30 +
  31 + def select_unit(value)
  32 + return 1 if value.nil? || value == 0
  33 + return 3600 if value % 3600 == 0
  34 + return 60 if value % 60 == 0
  35 + return 1
  36 + end
  37 +end
... ...
plugins/tolerance_time/db/migrate/20120719090320_create_tolerance_time_plugin_tolerances.rb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +class CreateToleranceTimePluginTolerances < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :tolerance_time_plugin_tolerances do |t|
  4 + t.references :profile
  5 + t.integer :content_tolerance
  6 + t.integer :comment_tolerance
  7 + end
  8 + end
  9 +
  10 + def self.down
  11 + drop_table :tolerance_time_plugin_tolerances
  12 + end
  13 +end
... ...
plugins/tolerance_time/db/migrate/20120719095004_create_tolerance_time_plugin_publications.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +class CreateToleranceTimePluginPublications < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :tolerance_time_plugin_publications do |t|
  4 + t.references :target, :polymorphic => true
  5 + t.timestamps
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + drop_table :tolerance_time_plugin_publications
  11 + end
  12 +end
... ...
plugins/tolerance_time/lib/ext/article.rb 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +require_dependency 'article'
  2 +
  3 +class Article
  4 + after_create do |article|
  5 + ToleranceTimePlugin::Publication.create!(:target => article) if article.published
  6 + end
  7 +
  8 + before_save do |article|
  9 + if article.published_changed?
  10 + if article.published
  11 + ToleranceTimePlugin::Publication.create!(:target => article)
  12 + else
  13 + publication = ToleranceTimePlugin::Publication.find_by_target(article)
  14 + publication.destroy if publication.present?
  15 + end
  16 + end
  17 + end
  18 +
  19 + before_destroy do |article|
  20 + publication = ToleranceTimePlugin::Publication.find_by_target(article)
  21 + publication.destroy if publication.present?
  22 + end
  23 +end
... ...
plugins/tolerance_time/lib/ext/comment.rb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +require_dependency 'comment'
  2 +
  3 +class Comment
  4 + after_create do |comment|
  5 + ToleranceTimePlugin::Publication.create!(:target => comment)
  6 + end
  7 +
  8 + before_destroy do |comment|
  9 + publication = ToleranceTimePlugin::Publication.find_by_target(comment)
  10 + publication.destroy if publication.present?
  11 + end
  12 +end
  13 +
... ...
plugins/tolerance_time/lib/tolerance_time_plugin.rb 0 → 100644
... ... @@ -0,0 +1,71 @@
  1 +require_dependency 'ext/article'
  2 +require_dependency 'ext/comment'
  3 +
  4 +class ToleranceTimePlugin < Noosfero::Plugin
  5 +
  6 + def self.plugin_name
  7 + "Tolerance Time"
  8 + end
  9 +
  10 + def self.plugin_description
  11 + _("Adds a tolerance time for editing content after its publication")
  12 + end
  13 +
  14 + def self.expired?(content)
  15 + return false if content.kind_of?(Comment) && !content.article.kind_of?(Article)
  16 +
  17 + expirable = content.kind_of?(Comment) || (!content.folder? && content.published?)
  18 + publication = ToleranceTimePlugin::Publication.find_by_target(content)
  19 + publication = ToleranceTimePlugin::Publication.create!(:target => content) if expirable && publication.nil?
  20 + person_article = content.kind_of?(Article) && content.profile.kind_of?(Person)
  21 +
  22 + !person_article && expirable && publication.expired?
  23 + end
  24 +
  25 + def control_panel_buttons
  26 + {:title => _('Tolerance Adjustements'), :url => {:controller => 'tolerance_time_plugin_myprofile', :profile => context.profile.identifier}, :icon => 'tolerance-time' }
  27 + end
  28 +
  29 + def stylesheet?
  30 + true
  31 + end
  32 +
  33 + def cms_controller_filters
  34 + return if !context.environment.plugin_enabled?(ToleranceTimePlugin)
  35 + block = lambda do
  36 + content = Article.find(params[:id])
  37 + if ToleranceTimePlugin.expired?(content)
  38 + session[:notice] = _('This content can\'t be edited anymore because it expired the tolerance time')
  39 + redirect_to content.url
  40 + end
  41 + end
  42 +
  43 + { :type => 'before_filter',
  44 + :method_name => 'expired_content',
  45 + :options => {:only => 'edit'},
  46 + :block => block }
  47 + end
  48 +
  49 + def content_viewer_controller_filters
  50 + return if !context.environment.plugin_enabled?(ToleranceTimePlugin)
  51 + block = lambda do
  52 + content = Comment.find(params[:id])
  53 + if ToleranceTimePlugin.expired?(content)
  54 + session[:notice] = _('This content can\'t be edited anymore because it expired the tolerance time')
  55 + redirect_to content.article.url
  56 + end
  57 + end
  58 +
  59 + { :type => 'before_filter',
  60 + :method_name => 'expired_content',
  61 + :options => {:only => 'edit_comment'},
  62 + :block => block }
  63 + end
  64 +
  65 + def content_expire_edit(content)
  66 + if ToleranceTimePlugin.expired?(content)
  67 + _('The tolerance time for editing this content is over.')
  68 + end
  69 + end
  70 +
  71 +end
... ...
plugins/tolerance_time/lib/tolerance_time_plugin/publication.rb 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +class ToleranceTimePlugin::Publication < Noosfero::Plugin::ActiveRecord
  2 + belongs_to :target, :polymorphic => true
  3 + validates_presence_of :target_id, :target_type
  4 + validates_uniqueness_of :target_id, :scope => :target_type
  5 +
  6 + class << self
  7 + def find_by_target(target)
  8 + kind = target.kind_of?(Article) ? 'Article' : 'Comment'
  9 + find_by_target_id_and_target_type(target.id, kind)
  10 + end
  11 + end
  12 +
  13 + def expired?
  14 + profile = (target.kind_of?(Article) ? target.profile : target.article.profile)
  15 + profile_tolerance = ToleranceTimePlugin::Tolerance.find_by_profile_id(profile.id)
  16 + content_tolerance = profile_tolerance ? profile_tolerance.content_tolerance : nil
  17 + comment_tolerance = profile_tolerance ? profile_tolerance.comment_tolerance : nil
  18 + if target.kind_of?(Article)
  19 + tolerance_time = content_tolerance || 1.0/0
  20 + elsif target.kind_of?(Comment)
  21 + tolerance_time = comment_tolerance || 1.0/0
  22 + else
  23 + tolerance_time = 1.0/0
  24 + end
  25 + created_at.to_i+tolerance_time < Time.now.to_i
  26 + end
  27 +end
... ...
plugins/tolerance_time/lib/tolerance_time_plugin/tolerance.rb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +class ToleranceTimePlugin::Tolerance < Noosfero::Plugin::ActiveRecord
  2 + belongs_to :profile
  3 + validates_presence_of :profile_id
  4 + validates_uniqueness_of :profile_id
  5 + validates_numericality_of :content_tolerance, :only_integer => true, :allow_nil => true
  6 + validates_numericality_of :comment_tolerance, :only_integer => true, :allow_nil => true
  7 +end
... ...
plugins/tolerance_time/public/icons/tolerance-time.png 0 → 100644

4.71 KB

plugins/tolerance_time/public/style.css 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +.controller-profile_editor a.control-panel-tolerance-time,
  2 +.controller-profile_editor .msie6 a.control-panel-tolerance-time {
  3 + background-image: url(/plugins/tolerance_time/icons/tolerance-time.png)
  4 +}
... ...
plugins/tolerance_time/test/unit/article_test.rb 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +
  3 +class ArticleTest < ActiveSupport::TestCase
  4 + should 'create a publication after publishing the article' do
  5 + article = fast_create(Article, :published => false, :profile_id => fast_create(Profile).id)
  6 + assert_nil ToleranceTimePlugin::Publication.find_by_target(article)
  7 +
  8 + article.published = true
  9 + article.save!
  10 + assert_not_nil ToleranceTimePlugin::Publication.find_by_target(article)
  11 + end
  12 +
  13 + should 'destroy publication if the article is destroyed' do
  14 + profile = fast_create(Profile)
  15 + article = fast_create(Article, :profile_id => profile.id)
  16 + article_publication = ToleranceTimePlugin::Publication.create!(:target => article)
  17 + article.destroy
  18 + assert_raise ActiveRecord::RecordNotFound do
  19 + article_publication.reload
  20 + end
  21 + end
  22 +
  23 + should 'destroy publication if the article is changed to not published' do
  24 + profile = fast_create(Profile)
  25 + article = fast_create(Article, :profile_id => profile.id)
  26 + article_publication = ToleranceTimePlugin::Publication.create!(:target => article)
  27 + article.published = false
  28 + article.save!
  29 + assert_raise ActiveRecord::RecordNotFound do
  30 + article_publication.reload
  31 + end
  32 + end
  33 +end
... ...
plugins/tolerance_time/test/unit/comment_test.rb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +
  3 +class CommentTest < ActiveSupport::TestCase
  4 + should 'create a publication after posting a comment' do
  5 + article = fast_create(Article, :profile_id => fast_create(Person).id)
  6 + comment = Comment.new(:author_id => fast_create(Person).id, :body => 'Hello There!', :source_id => article.id)
  7 + assert_difference ToleranceTimePlugin::Publication, :count do
  8 + comment.save!
  9 + end
  10 + assert_not_nil ToleranceTimePlugin::Publication.find_by_target(comment)
  11 + end
  12 +
  13 + should 'destroy publication if the comment is destroyed' do
  14 + profile = fast_create(Profile)
  15 + article = fast_create(Article, :profile_id => profile.id)
  16 + comment = fast_create(Comment, :source_id => article.id)
  17 + comment_publication = ToleranceTimePlugin::Publication.create!(:target => comment)
  18 + comment.destroy
  19 + assert_raise ActiveRecord::RecordNotFound do
  20 + comment_publication.reload
  21 + end
  22 + end
  23 +end
  24 +
... ...
plugins/tolerance_time/test/unit/tolerance_time_plugin/publication_test.rb 0 → 100644
... ... @@ -0,0 +1,78 @@
  1 +require File.dirname(__FILE__) + '/../../../../../test/test_helper'
  2 +
  3 +class ToleranceTimePlugin::PublicationTest < ActiveSupport::TestCase
  4 + should 'validate presence of target' do
  5 + publication = ToleranceTimePlugin::Publication.new
  6 + publication.valid?
  7 + assert publication.errors.invalid?(:target_id)
  8 + assert publication.errors.invalid?(:target_type)
  9 +
  10 + publication.target = fast_create(Article)
  11 + publication.valid?
  12 + assert !publication.errors.invalid?(:target_id)
  13 + assert !publication.errors.invalid?(:target_type)
  14 + end
  15 +
  16 + should 'validate uniqueness of target' do
  17 + target = fast_create(Article)
  18 + p1 = ToleranceTimePlugin::Publication.create!(:target => target)
  19 + p2 = ToleranceTimePlugin::Publication.new(:target => target)
  20 + p2.valid?
  21 +
  22 + assert p2.errors.invalid?(:target_id)
  23 + end
  24 +
  25 + should 'be able to find publication by target' do
  26 + article = fast_create(Article)
  27 + publication = ToleranceTimePlugin::Publication.create!(:target => article)
  28 + assert_equal publication, ToleranceTimePlugin::Publication.find_by_target(article)
  29 + end
  30 +
  31 + should 'avaliate if the publication is expired' do
  32 + profile = fast_create(Profile)
  33 + author = fast_create(Person)
  34 + a1 = fast_create(Article, :profile_id => profile.id)
  35 + a2 = fast_create(Article, :profile_id => profile.id)
  36 + c1 = fast_create(Comment, :source_id => a1.id)
  37 + c2 = fast_create(Comment, :source_id => a2.id)
  38 + ToleranceTimePlugin::Tolerance.create!(:profile => profile, :content_tolerance => 10.minutes, :comment_tolerance => 5.minutes)
  39 + expired_article = ToleranceTimePlugin::Publication.create!(:target => a1)
  40 + expired_article.created_at = 15.minutes.ago
  41 + expired_article.save!
  42 + on_time_article = ToleranceTimePlugin::Publication.create!(:target => a2)
  43 + on_time_article.created_at = 5.minutes.ago
  44 + on_time_article.save!
  45 + expired_comment = ToleranceTimePlugin::Publication.create!(:target => c1)
  46 + expired_comment.created_at = 8.minutes.ago
  47 + expired_comment.save!
  48 + on_time_comment = ToleranceTimePlugin::Publication.create!(:target => c2)
  49 + on_time_comment.created_at = 2.minutes.ago
  50 + on_time_comment.save!
  51 +
  52 + assert expired_article.expired?
  53 + assert !on_time_article.expired?
  54 + assert expired_comment.expired?
  55 + assert !on_time_comment.expired?
  56 + end
  57 +
  58 + should 'consider tolerance infinity if not defined' do
  59 + profile = fast_create(Profile)
  60 + article = fast_create(Article, :profile_id => profile.id)
  61 + article_publication = ToleranceTimePlugin::Publication.create!(:target => article)
  62 + article_publication.created_at = 1000.years.ago
  63 + article_publication.save!
  64 + ToleranceTimePlugin::Tolerance.create!(:profile => profile)
  65 +
  66 + assert !article_publication.expired?
  67 + end
  68 +
  69 + should 'not crash if profile has no tolerance yet defined' do
  70 + profile = fast_create(Profile)
  71 + article = fast_create(Article, :profile_id => profile.id)
  72 + article_publication = ToleranceTimePlugin::Publication.create!(:target => article)
  73 + article_publication.created_at = 1000.years.ago
  74 + article_publication.save!
  75 +
  76 + assert !article_publication.expired?
  77 + end
  78 +end
... ...
plugins/tolerance_time/test/unit/tolerance_time_plugin/tolerance_test.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +require File.dirname(__FILE__) + '/../../../../../test/test_helper'
  2 +
  3 +class ToleranceTimePlugin::ToleranceTest < ActiveSupport::TestCase
  4 + should 'validate presence of profile' do
  5 + tolerance = ToleranceTimePlugin::Tolerance.new
  6 + tolerance.valid?
  7 + assert tolerance.errors.invalid?(:profile_id)
  8 +
  9 + tolerance.profile = fast_create(Profile)
  10 + tolerance.valid?
  11 + assert !tolerance.errors.invalid?(:profile_id)
  12 + end
  13 +
  14 + should 'validate uniqueness of profile' do
  15 + profile = fast_create(Profile)
  16 + t1 = ToleranceTimePlugin::Tolerance.create!(:profile => profile)
  17 + t2 = ToleranceTimePlugin::Tolerance.new(:profile => profile)
  18 + t2.valid?
  19 +
  20 + assert t2.errors.invalid?(:profile_id)
  21 + end
  22 +
  23 + should 'validate integer format for comment and content tolerance' do
  24 + tolerance = ToleranceTimePlugin::Tolerance.new(:profile => fast_create(Profile))
  25 + assert tolerance.valid?
  26 +
  27 + tolerance.comment_tolerance = 'sdfa'
  28 + tolerance.content_tolerance = 4.5
  29 + tolerance.valid?
  30 + assert tolerance.errors.invalid?(:comment_tolerance)
  31 + assert tolerance.errors.invalid?(:content_tolerance)
  32 +
  33 + tolerance.comment_tolerance = 3
  34 + tolerance.content_tolerance = 6
  35 + assert tolerance.valid?
  36 + end
  37 +end
... ...
plugins/tolerance_time/views/tolerance_time_plugin_myprofile/index.html.erb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +<h1><%= _('Tolerance Adjustments') %></h1>
  2 +
  3 +<%= error_messages_for :tolerance %>
  4 +
  5 +<% form_for :tolerance, @tolerance do |f| %>
  6 +
  7 + <% time_units = [[_('Seconds'), 1], [_('Minutes'), 60], [_('Hours'), 3600]]%>
  8 +
  9 + <% if profile.organization? %>
  10 + <%= labelled_form_field(_('Content edition tolerance time'),
  11 + f.text_field(:content_tolerance, :size => 2, :style => 'font-size: 14px; text-align: right') +
  12 + select_tag(:content_tolerance_unit, options_for_select(time_units, @content_default_unit) )) %>
  13 + <% end %>
  14 + <%= labelled_form_field(_('Comment edition tolerance time'),
  15 + f.text_field(:comment_tolerance, :size => 2, :style => 'font-size: 14px; text-align: right') +
  16 + select_tag(:comment_tolerance_unit, options_for_select(time_units, @comment_default_unit) )) %>
  17 +
  18 + <%= content_tag( 'small', _('Empty means unlimited and zero means right away.') ) %>
  19 +
  20 + <% button_bar do %>
  21 + <%= submit_button('save', _('Save'))%>
  22 + <%= button('back', _('Back'), {:controller => 'profile_editor'})%>
  23 + <% end %>
  24 +<% end %>
... ...
public/designs/icons/tango/ie6.css
1 1 .msie6 .icon-edit { background-image: url(ie6/Tango/16x16/apps/text-editor.gif) }
2 2 .msie6 .icon-home { background-image: url(ie6/Tango/16x16/actions/go-home.gif) }
3   -.msie6 .icon-new { background-image: url(ie6/Tango/16x16/actions/filenew.gif) }
  3 +.msie6 .icon-new,
  4 +.msie6 .icon-suggest { background-image: url(ie6/Tango/16x16/actions/filenew.gif) }
4 5 .msie6 .icon-close { background-image: url(ie6/Tango/16x16/actions/gtk-cancel.gif) }
5 6 .msie6 .icon-newfolder { background-image: url(ie6/Tango/16x16/actions/folder-new.gif) }
6 7 .msie6 .icon-save { background-image: url(ie6/Tango/16x16/actions/filesave.gif) }
... ...
public/designs/icons/tango/style.css
... ... @@ -3,7 +3,8 @@
3 3 /******************SMALL ICONS********************/
4 4 .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) }
5 5 .icon-home { background-image: url(Tango/16x16/actions/go-home.png) }
6   -.icon-new { background-image: url(Tango/16x16/actions/filenew.png) }
  6 +.icon-new,
  7 +.icon-suggest { background-image: url(Tango/16x16/actions/filenew.png) }
7 8 .icon-close { background-image: url(Tango/16x16/actions/gtk-cancel.png) }
8 9 .icon-newfolder { background-image: url(Tango/16x16/actions/folder-new.png) }
9 10 .icon-folder { background-image: url(Tango/16x16/places/folder.png) }
... ...
public/designs/themes/base/style.css
... ... @@ -908,6 +908,16 @@ hr.pre-posts, hr.sep-posts {
908 908 #article-actions a.button:hover {
909 909 color: #555753;
910 910 }
  911 +#content a.disabled,
  912 +#content a.disabled:hover {
  913 + color: #888;
  914 + text-decoration: none;
  915 +}
  916 +#content a.button.disabled,
  917 +#content a.button.disabled:hover {
  918 + background-color: #CCC;
  919 + border-color: #CCC;
  920 +}
911 921  
912 922 #addThis {
913 923 text-align: right;
... ...
public/filters.svg 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +<svg xmlns="http://www.w3.org/2000/svg">
  2 + <filter id="grayscale">
  3 + <feColorMatrix type="matrix" values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"/>
  4 + </filter>
  5 +</svg>
... ...
public/stylesheets/application.css
... ... @@ -1503,7 +1503,13 @@ a.button:hover, body.noosfero a.button:hover, input.button:hover, a.button.with-
1503 1503 body.noosfero a.button.with-text.icon-none, body.noosfero input.button.with-text.icon-none {
1504 1504 padding-left: 2px;
1505 1505 }
1506   -a.button.disabled, input.disabled {
  1506 +a.disabled{
  1507 + filter: url(filters.svg#grayscale); /* Firefox 3.5+ */
  1508 + filter: gray; /* IE6-9 */
  1509 + -webkit-filter: grayscale(1); /* Google Chrome & Safari 6+ */
  1510 + cursor: default;
  1511 +}
  1512 +input.disabled {
1507 1513 opacity: 0.5;
1508 1514 filter-opacity: 50%;
1509 1515 }
... ...
test/factories.rb
... ... @@ -442,7 +442,7 @@ module Noosfero::Factory
442 442  
443 443 def defaults_for_comment(params = {})
444 444 name = "comment_#{rand(1000)}"
445   - { :title => name, :body => "my own comment", :source_id => 1 }.merge(params)
  445 + { :title => name, :body => "my own comment", :source_id => 1, :source_type => 'Article' }.merge(params)
446 446 end
447 447  
448 448 ###############################################
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -1400,6 +1400,38 @@ end
1400 1400 end
1401 1401 end
1402 1402  
  1403 + should 'not display article actions button if any plugins says so' do
  1404 + class Plugin1 < Noosfero::Plugin
  1405 + def content_remove_edit(content); true; end
  1406 + end
  1407 + class Plugin2 < Noosfero::Plugin
  1408 + def content_remove_edit(content); false; end
  1409 + end
  1410 +
  1411 + environment.enable_plugin(Plugin1.name)
  1412 + environment.enable_plugin(Plugin2.name)
  1413 +
  1414 + login_as('testinguser')
  1415 + xhr :get, :view_page, :profile => 'testinguser', :page => [], :toolbar => true
  1416 + assert_no_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :href => "/myprofile/testinguser/cms/edit/#{profile.home_page.id}" } }
  1417 + end
  1418 +
  1419 + should 'expire article actions button if any plugins says so' do
  1420 + class Plugin1 < Noosfero::Plugin
  1421 + def content_expire_edit(content); 'This button is expired.'; end
  1422 + end
  1423 + class Plugin2 < Noosfero::Plugin
  1424 + def content_expire_edit(content); nil; end
  1425 + end
  1426 +
  1427 + environment.enable_plugin(Plugin1.name)
  1428 + environment.enable_plugin(Plugin2.name)
  1429 +
  1430 + login_as('testinguser')
  1431 + xhr :get, :view_page, :profile => 'testinguser', :page => [], :toolbar => true
  1432 + assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :title => 'This button is expired.', :class => 'button with-text icon-edit disabled' } }
  1433 + end
  1434 +
1403 1435 should 'remove email from article followers when unfollow' do
1404 1436 profile = create_user('testuser').person
1405 1437 follower_email = 'john@doe.br'
... ...
test/unit/cms_helper_test.rb
... ... @@ -5,6 +5,7 @@ class CmsHelperTest &lt; ActiveSupport::TestCase
5 5 include CmsHelper
6 6 include BlogHelper
7 7 include ApplicationHelper
  8 + include ActionView::Helpers::UrlHelper
8 9  
9 10 should 'show default options for article' do
10 11 CmsHelperTest.any_instance.stubs(:controller).returns(ActionController::Base.new)
... ... @@ -47,14 +48,18 @@ class CmsHelperTest &lt; ActiveSupport::TestCase
47 48 end
48 49  
49 50 should 'display spread button when profile is a person' do
  51 + @controller = ApplicationController.new
  52 + @plugins.stubs(:dispatch).returns([])
50 53 profile = fast_create(Person)
51 54 article = fast_create(TinyMceArticle, :name => 'My article', :profile_id => profile.id)
52   - expects(:button_without_text).with(:spread, 'Spread this', :action => 'publish', :id => article.id)
  55 + expects(:link_to).with('Spread this', {:action => 'publish', :id => article.id}, :class => 'button with-text icon-spread', :title => nil)
53 56  
54 57 result = display_spread_button(profile, article)
55 58 end
56 59  
57 60 should 'display spread button when profile is a community and env has portal_community' do
  61 + @controller = ApplicationController.new
  62 + @plugins.stubs(:dispatch).returns([])
58 63 env = fast_create(Environment)
59 64 env.expects(:portal_community).returns(true)
60 65 profile = fast_create(Community, :environment_id => env.id)
... ... @@ -62,12 +67,14 @@ class CmsHelperTest &lt; ActiveSupport::TestCase
62 67  
63 68 article = fast_create(TinyMceArticle, :name => 'My article', :profile_id => profile.id)
64 69  
65   - expects(:button_without_text).with(:spread, 'Spread this', :action => 'publish_on_portal_community', :id => article.id)
  70 + expects(:link_to).with('Spread this', {:action => 'publish_on_portal_community', :id => article.id}, :class => 'button with-text icon-spread', :title => nil)
66 71  
67 72 result = display_spread_button(profile, article)
68 73 end
69 74  
70 75 should 'not display spread button when profile is a community and env has not portal_community' do
  76 + @controller = ApplicationController.new
  77 + @plugins.stubs(:dispatch).returns([])
71 78 env = fast_create(Environment)
72 79 env.expects(:portal_community).returns(nil)
73 80 profile = fast_create(Community, :environment_id => env.id)
... ... @@ -75,31 +82,37 @@ class CmsHelperTest &lt; ActiveSupport::TestCase
75 82  
76 83 article = fast_create(TinyMceArticle, :name => 'My article', :profile_id => profile.id)
77 84  
78   - expects(:button_without_text).with(:spread, 'Spread this', :action => 'publish_on_portal_community', :id => article.id).never
  85 + expects(:link_to).with('Spread this', {:action => 'publish_on_portal_community', :id => article.id}, :class => 'button with-text icon-spread', :title => nil).never
79 86  
80 87 result = display_spread_button(profile, article)
81 88 end
82 89  
83 90 should 'display delete_button to folder' do
  91 + @controller = ApplicationController.new
  92 + @plugins.stubs(:dispatch).returns([])
84 93 profile = fast_create(Profile)
85 94 name = 'My folder'
86 95 folder = fast_create(Folder, :name => name, :profile_id => profile.id)
87 96 confirm_message = "Are you sure that you want to remove the folder \"#{name}\"? Note that all the items inside it will also be removed!"
88   - expects(:button_without_text).with(:delete, 'Delete', {:action => 'destroy', :id => folder.id}, :method => :post, :confirm => confirm_message)
  97 + expects(:link_to).with('Delete', {:action => 'destroy', :id => folder.id}, :method => :post, :confirm => confirm_message, :class => 'button with-text icon-delete', :title => nil)
89 98  
90 99 result = display_delete_button(folder)
91 100 end
92 101  
93 102 should 'display delete_button to article' do
  103 + @controller = ApplicationController.new
  104 + @plugins.stubs(:dispatch).returns([])
94 105 profile = fast_create(Profile)
95 106 name = 'My article'
96 107 article = fast_create(TinyMceArticle, :name => name, :profile_id => profile.id)
97 108 confirm_message = "Are you sure that you want to remove the item \"#{name}\"?"
98   - expects(:button_without_text).with(:delete, 'Delete', {:action => 'destroy', :id => article.id}, :method => :post, :confirm => confirm_message)
  109 + expects(:link_to).with('Delete', {:action => 'destroy', :id => article.id}, :method => :post, :confirm => confirm_message, :class => 'button with-text icon-delete', :title => nil)
99 110  
100 111 result = display_delete_button(article)
101 112 end
102 113  
  114 + def link_to(text, *args); puts text; puts args.inspect; text; end
  115 +
103 116 end
104 117  
105 118 module RssFeedHelper
... ...
test/unit/comment_test.rb
... ... @@ -555,6 +555,14 @@ class CommentTest &lt; ActiveSupport::TestCase
555 555 assert_equal 'bar', c.referrer
556 556 end
557 557  
  558 + should 'delegate environment to article' do
  559 + profile = fast_create(Profile, :environment_id => Environment.default)
  560 + article = fast_create(Article, :profile_id => profile.id)
  561 + comment = fast_create(Comment, :source_id => article.id, :source_type => 'Article')
  562 +
  563 + assert_equal Environment.default, comment.environment
  564 + end
  565 +
558 566 private
559 567  
560 568 def create_comment(args = {})
... ...