Commit fc8557c3c6c62a489bab035ea63f3ee7a10c5db0
Exists in
master
and in
23 other branches
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
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 | + | |
| 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/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 | ... | ... |
| ... | ... | @@ -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 | ... | ... |
| ... | ... | @@ -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 | + | ... | ... |
| ... | ... | @@ -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 | ... | ... |
4.71 KB
| ... | ... | @@ -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 | ... | ... |
| ... | ... | @@ -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/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 < 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 < 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 < 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 < 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 < 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 = {}) | ... | ... |