diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7c07b0e..adcc3d7 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1329,4 +1329,17 @@ module ApplicationHelper _("Are you sure that you want to remove the item \"#{article.name}\"?") end end + + def expirable_link_to(expired, content, url, options = {}) + if expired + options[:class] = (options[:class] || '') + ' disabled' + content_tag('a', ' '+content_tag('span', content), options) + else + link_to content, url, options + end + end + + def remove_content_button(action) + @plugins.dispatch("content_remove_#{action.to_s}", @page).include?(true) + end end diff --git a/app/helpers/cms_helper.rb b/app/helpers/cms_helper.rb index c281d06..7d84e6d 100644 --- a/app/helpers/cms_helper.rb +++ b/app/helpers/cms_helper.rb @@ -42,13 +42,25 @@ module CmsHelper def display_spread_button(profile, article) if profile.person? - button_without_text :spread, _('Spread this'), :action => 'publish', :id => article.id + expirable_button article, :spread, _('Spread this'), :action => 'publish', :id => article.id elsif profile.community? && environment.portal_community - button_without_text :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id + expirable_button article, :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id end end def display_delete_button(article) - button_without_text :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article) + expirable_button article, :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article) + end + + def expirable_button(content, action, title, url, options = {}) + reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first + if reason.present? + options[:class] = (options[:class] || '') + ' disabled' + options[:disabled] = 'disabled' + options.delete(:confirm) + options.delete(:method) + title = reason + end + button_without_text action.to_sym, title, url, options end end diff --git a/app/helpers/content_viewer_helper.rb b/app/helpers/content_viewer_helper.rb index 524aa53..c03aef2 100644 --- a/app/helpers/content_viewer_helper.rb +++ b/app/helpers/content_viewer_helper.rb @@ -68,4 +68,20 @@ module ContentViewerHelper end end + def expirable_content_reference(content, action, text, url, options = {}) + reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first + options[:title] = reason + expirable_link_to reason.present?, text, url, options + end + + def expirable_button(content, action, text, url, options = {}) + options[:class] = "button with-text icon-#{action.to_s}" + expirable_content_reference content, action, text, url, options + end + + def expirable_comment_link(content, action, text, url, options = {}) + options[:class] = "comment-footer comment-footer-link comment-footer-hide" + expirable_content_reference content, action, text, url, options + end + end diff --git a/app/models/comment.rb b/app/models/comment.rb index 50af142..a20c86e 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -25,6 +25,8 @@ class Comment < ActiveRecord::Base xss_terminate :only => [ :body, :title, :name ], :on => 'validation' + delegate :environment, :to => :source + def action_tracker_target self.article.profile end diff --git a/app/views/cms/view.rhtml b/app/views/cms/view.rhtml index 807ac94..b7de3e7 100644 --- a/app/views/cms/view.rhtml +++ b/app/views/cms/view.rhtml @@ -49,13 +49,13 @@ <%= article.class.short_description %> - <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => article.id %> + <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> <%= button_without_text :eyes, _('Public view'), article.view_url %> - <%= display_spread_button(profile, article) unless article.folder? %> - <% if !environment.enabled?('cant_change_homepage') %> - <%= button_without_text :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> + <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> + <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> + <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> <% end %> - <%= display_delete_button(article) %> + <%= display_delete_button(article) if !remove_content_button(:delete) %> <% end %> diff --git a/app/views/content_viewer/_article_toolbar.rhtml b/app/views/content_viewer/_article_toolbar.rhtml index 433f3ba..50708df 100644 --- a/app/views/content_viewer/_article_toolbar.rhtml +++ b/app/views/content_viewer/_article_toolbar.rhtml @@ -1,38 +1,39 @@ >
- <% if @page.allow_edit?(user) %> - <%= link_to content_tag( 'span', label_for_edit_article(@page) ), - profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }), - :class => 'button with-text icon-edit' %> + + <% if @page.allow_edit?(user) && !remove_content_button(:edit) %> + <% content = content_tag('span', label_for_edit_article(@page)) %> + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }) %> + <%= expirable_button @page, :edit, content, url %> <% end %> - <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) %> - <%= link_to content_tag( 'span', _('Delete') ), - profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page}), - :method => :post, - :class => 'button with-text icon-delete', - :confirm => delete_article_message(@page) %> + <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) && !remove_content_button(:delete)%> + <% content = content_tag( 'span', _('Delete') ) %> + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page}) %> + <% options = {:method => :post, :confirm => delete_article_message(@page)} %> + <%= expirable_button @page, :delete, content, url, options %> <% end %> - <% if !@page.folder? && @page.allow_spread?(user) %> + <% if !@page.folder? && @page.allow_spread?(user) && !remove_content_button(:spread) %> + <% content = content_tag( 'span', _('Spread this') ) %> + <% url = nil %> <% if profile.kind_of?(Person) %> - <%= link_to content_tag( 'span', _('Spread this') ), - profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page }), - :class => 'button with-text icon-spread' %> + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page }) %> <% elsif profile.kind_of?(Community) && environment.portal_community %> - <%= link_to content_tag( 'span', _('Spread this') ), - profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page }), - :class => 'button with-text icon-spread' %> + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page }) %> <% end %> + <%= expirable_button @page, :spread, content, url if url %> <% end %> <% if !@page.gallery? && @page.allow_create?(user) %> - <%= link_to _('Add translation'), - profile.admin_url.merge(:controller => 'cms', :action => 'new', - :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)), - :type => @page.type, :article => { :translation_of_id => @page.native_translation.id }), - :class => 'button with-text icon-locale' if @page.translatable? && !@page.native_translation.language.blank? %> + <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %> + <% content = _('Add translation') %> + <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %> + <% url = profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => parent_id, :type => @page.type, :article => { :translation_of_id => @page.native_translation.id })%> + <%= expirable_button @page, :locale, content, url %> + <% end %> + <%= lightbox_remote_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)))) %> <% end %> @@ -40,8 +41,11 @@ <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) %> <% end %> - <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) %> - <%= 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' %> + <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %> + <% content = content_tag( 'span', _('Suggest an article') ) %> + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %> + <% options = {:id => 'suggest-article-link'} %> + <%= expirable_button @page, :suggest, content, url, options %> <% end %> <%= report_abuse(profile, :link, @page) %> diff --git a/app/views/content_viewer/_comment.rhtml b/app/views/content_viewer/_comment.rhtml index 1a9d895..2352733 100644 --- a/app/views/content_viewer/_comment.rhtml +++ b/app/views/content_viewer/_comment.rhtml @@ -57,6 +57,10 @@ <% end %> <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> + <% if comment.author && comment.author == user %> + <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %> + <%= content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') %> + <% end %> <%= link_to_function _('Reply'), "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id, :class => 'comment-footer comment-footer-link comment-footer-hide', diff --git a/app/views/profile/_comment.rhtml b/app/views/profile/_comment.rhtml index 8b40ba5..009a4cf 100644 --- a/app/views/profile/_comment.rhtml +++ b/app/views/profile/_comment.rhtml @@ -46,6 +46,10 @@ <% end %> <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> + <% if comment.author && comment.author == user %> + <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %> + <%= content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') %> + <% end %> <%= link_to_function _('Reply'), "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id, :class => 'comment-footer comment-footer-link comment-footer-hide', diff --git a/lib/noosfero/plugin.rb b/lib/noosfero/plugin.rb index 81e07dc..55b8084 100644 --- a/lib/noosfero/plugin.rb +++ b/lib/noosfero/plugin.rb @@ -196,28 +196,6 @@ class Noosfero::Plugin nil end - # This is a generic hotspot for all controllers on Noosfero. - # If any plugin wants to define filters to run on any controller, the name of - # the hotspot must be in the following form: _filters. - # Example: for ProfileController the hotspot is profile_controller_filters - # - # -> Adds a filter to a controller - # returns = { :type => type, - # :method_name => method_name, - # :options => {:opt1 => opt1, :opt2 => opt2}, - # :block => Proc or lambda block} - # type = 'before_filter' or 'after_filter' - # method_name = The name of the filter - # option = Filter options, like :only or :except - # block = Block that the filter will call - def method_missing(method, *args, &block) - if method.to_s =~ /^(.+)_controller_filters$/ - [] - else - super - end - end - # This method will be called just before a comment is saved to the database. # # It can modify the comment in several ways. In special, a plugin can call @@ -256,4 +234,40 @@ class Noosfero::Plugin nil end + def method_missing(method, *args, &block) + # This is a generic hotspot for all controllers on Noosfero. + # If any plugin wants to define filters to run on any controller, the name of + # the hotspot must be in the following form: _filters. + # Example: for ProfileController the hotspot is profile_controller_filters + # + # -> Adds a filter to a controller + # returns = { :type => type, + # :method_name => method_name, + # :options => {:opt1 => opt1, :opt2 => opt2}, + # :block => Proc or lambda block} + # type = 'before_filter' or 'after_filter' + # method_name = The name of the filter + # option = Filter options, like :only or :except + # block = Block that the filter will call + if method.to_s =~ /^(.+)_controller_filters$/ + [] + # -> Removes the action button from the content + # returns = boolean + elsif method.to_s =~ /^content_remove_(#{content_actions.join('|')})$/ + nil + # -> Expire the action button from the content + # returns = string with reason of expiration + elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/ + nil + else + super + end + end + + private + + def content_actions + %w[edit delete spread locale suggest home] + end + end diff --git a/public/designs/icons/tango/ie6.css b/public/designs/icons/tango/ie6.css index a7ae730..8a6d6fa 100644 --- a/public/designs/icons/tango/ie6.css +++ b/public/designs/icons/tango/ie6.css @@ -1,6 +1,7 @@ .msie6 .icon-edit { background-image: url(ie6/Tango/16x16/apps/text-editor.gif) } .msie6 .icon-home { background-image: url(ie6/Tango/16x16/actions/go-home.gif) } -.msie6 .icon-new { background-image: url(ie6/Tango/16x16/actions/filenew.gif) } +.msie6 .icon-new, +.msie6 .icon-suggest { background-image: url(ie6/Tango/16x16/actions/filenew.gif) } .msie6 .icon-close { background-image: url(ie6/Tango/16x16/actions/gtk-cancel.gif) } .msie6 .icon-newfolder { background-image: url(ie6/Tango/16x16/actions/folder-new.gif) } .msie6 .icon-save { background-image: url(ie6/Tango/16x16/actions/filesave.gif) } diff --git a/public/designs/icons/tango/style.css b/public/designs/icons/tango/style.css index 678d581..1881f0c 100644 --- a/public/designs/icons/tango/style.css +++ b/public/designs/icons/tango/style.css @@ -3,7 +3,8 @@ /******************SMALL ICONS********************/ .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) } .icon-home { background-image: url(Tango/16x16/actions/go-home.png) } -.icon-new { background-image: url(Tango/16x16/actions/filenew.png) } +.icon-new, +.icon-suggest { background-image: url(Tango/16x16/actions/filenew.png) } .icon-close { background-image: url(Tango/16x16/actions/gtk-cancel.png) } .icon-newfolder { background-image: url(Tango/16x16/actions/folder-new.png) } .icon-folder { background-image: url(Tango/16x16/places/folder.png) } diff --git a/public/designs/themes/base/style.css b/public/designs/themes/base/style.css index 817eb90..659f0a8 100644 --- a/public/designs/themes/base/style.css +++ b/public/designs/themes/base/style.css @@ -908,6 +908,16 @@ hr.pre-posts, hr.sep-posts { #article-actions a.button:hover { color: #555753; } +#content a.disabled, +#content a.disabled:hover { + color: #888; + text-decoration: none; +} +#content a.button.disabled, +#content a.button.disabled:hover { + background-color: #CCC; + border-color: #CCC; +} #addThis { text-align: right; diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 4dd7fc7..c4a6895 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -1487,7 +1487,13 @@ a.button:hover, body.noosfero a.button:hover, input.button:hover, a.button.with- body.noosfero a.button.with-text.icon-none, body.noosfero input.button.with-text.icon-none { padding-left: 2px; } -a.button.disabled, input.disabled { +a.disabled{ + filter: url(filters.svg#grayscale); /* Firefox 3.5+ */ + filter: gray; /* IE6-9 */ + -webkit-filter: grayscale(1); /* Google Chrome & Safari 6+ */ + cursor: default; +} +input.disabled { opacity: 0.5; filter-opacity: 50%; } diff --git a/test/functional/content_viewer_controller_test.rb b/test/functional/content_viewer_controller_test.rb index c741ea0..25669fb 100644 --- a/test/functional/content_viewer_controller_test.rb +++ b/test/functional/content_viewer_controller_test.rb @@ -1414,4 +1414,36 @@ class ContentViewerControllerTest < ActionController::TestCase end + should 'not display article actions button if any plugins says so' do + class Plugin1 < Noosfero::Plugin + def content_viewer_remove_edit(content); true; end + end + class Plugin2 < Noosfero::Plugin + def content_viewer_remove_edit(content); false; end + end + + environment.enable_plugin(Plugin1.name) + environment.enable_plugin(Plugin2.name) + + login_as('testinguser') + xhr :get, :view_page, :profile => 'testinguser', :page => [], :toolbar => true + assert_no_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :href => "/myprofile/testinguser/cms/edit/#{profile.home_page.id}" } } + end + + should 'expire article actions button if any plugins says so' do + class Plugin1 < Noosfero::Plugin + def content_viewer_expire_edit(content); 'This button is expired.'; end + end + class Plugin2 < Noosfero::Plugin + def content_viewer_expire_edit(content); nil; end + end + + environment.enable_plugin(Plugin1.name) + environment.enable_plugin(Plugin2.name) + + login_as('testinguser') + xhr :get, :view_page, :profile => 'testinguser', :page => [], :toolbar => true + assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :href => "/myprofile/testinguser/cms/edit/#{profile.home_page.id}", :title => 'This button is expired.', :class => 'button with-text icon-edit disabled', :onclick => 'return false' } } + end + end diff --git a/test/unit/comment_test.rb b/test/unit/comment_test.rb index d0c1ef7..7edf675 100644 --- a/test/unit/comment_test.rb +++ b/test/unit/comment_test.rb @@ -378,4 +378,12 @@ class CommentTest < ActiveSupport::TestCase assert_not_nil article.activity end + should 'delegate environment to article' do + profile = fast_create(Profile, :environment_id => Environment.default) + article = fast_create(Article, :profile_id => profile.id) + comment = fast_create(Comment, :source_id => article.id, :source_type => 'Article') + + assert_equal Environment.default, comment.environment + end + end -- libgit2 0.21.2