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