diff --git a/app/helpers/article_helper.rb b/app/helpers/article_helper.rb index db3a768..8bca69a 100644 --- a/app/helpers/article_helper.rb +++ b/app/helpers/article_helper.rb @@ -77,12 +77,59 @@ module ArticleHelper content_tag('div', radio_button(:article, :published, false) + content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") - ) + - (article.profile.community? ? content_tag('div', - content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") + - token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'}, - {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) : - '')) + ) + + privacity_exceptions(article, tokenized_children) + ) + end + + def privacity_exceptions(article, tokenized_children) + content_tag('div', + content_tag('div', + ( + if article.profile + add_option_to_followers(article, tokenized_children) + else + '' + end + ) + ), + :style => "margin-left:10px" + ) + end + + def add_option_to_followers(article, tokenized_children) + label_message = article.profile.organization? ? _('For all community members') : _('For all your friends') + + check_box( + :article, + :show_to_followers, + {:class => "custom_privacy_option"} + ) + + content_tag( + 'label', + label_message, + :for => 'article_show_to_followers', + :id => 'label_show_to_followers' + ) + + (article.profile.community? ? + content_tag( + 'div', + content_tag( + 'label', + _('Fill in the search field to add the exception users to see this content'), + :id => "text-input-search-exception-users" + ) + + token_input_field_tag( + :q, + 'search-article-privacy-exceptions', + {:action => 'search_article_privacy_exceptions'}, + { + :focus => false, + :hint_text => _('Type in a search term for a user'), + :pre_populate => tokenized_children + } + ) + ) : '') end def prepare_to_token_input(array) diff --git a/app/models/article.rb b/app/models/article.rb index 6023bfb..b52bd5b 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -2,7 +2,14 @@ require 'hpricot' class Article < ActiveRecord::Base - attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, :allow_members_to_edit, :translation_of_id, :language, :license_id, :parent_id, :display_posts_in_current_language, :category_ids, :posts_per_page, :moderate_comments, :accept_comments, :feed, :published, :source, :highlighted, :notify_comments, :display_hits, :slug, :external_feed_builder, :display_versions, :external_link, :image_builder + attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, + :allow_members_to_edit, :translation_of_id, :language, + :license_id, :parent_id, :display_posts_in_current_language, + :category_ids, :posts_per_page, :moderate_comments, + :accept_comments, :feed, :published, :source, + :highlighted, :notify_comments, :display_hits, :slug, + :external_feed_builder, :display_versions, :external_link, + :image_builder, :show_to_followers acts_as_having_image @@ -333,7 +340,7 @@ class Article < ActiveRecord::Base def belongs_to_blog? self.parent and self.parent.blog? end - + def belongs_to_forum? self.parent and self.parent.forum? end @@ -445,6 +452,7 @@ class Article < ActiveRecord::Base if self.parent && !self.parent.published? return false end + true else false @@ -476,14 +484,17 @@ class Article < ActiveRecord::Base {:conditions => [" articles.published = ? OR articles.last_changed_by_id = ? OR articles.profile_id = ? OR - ?", - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] } + ? OR articles.show_to_followers = ? AND ?", + true, user.id, user.id, user.has_permission?(:view_private_content, profile), + true, user.follows?(profile)]} end + def display_unpublished_article_to?(user) user == author || allow_view_private_content?(user) || user == profile || user.is_admin?(profile.environment) || user.is_admin?(profile) || - article_privacy_exceptions.include?(user) + article_privacy_exceptions.include?(user) || + (self.show_to_followers && user.follows?(profile)) end def display_to?(user = nil) diff --git a/db/migrate/20150113131617_add_show_to_followers_for_article.rb b/db/migrate/20150113131617_add_show_to_followers_for_article.rb new file mode 100644 index 0000000..f4fa99b --- /dev/null +++ b/db/migrate/20150113131617_add_show_to_followers_for_article.rb @@ -0,0 +1,9 @@ +class AddShowToFollowersForArticle < ActiveRecord::Migration + def up + add_column :articles, :show_to_followers, :boolean, :default => false + end + + def down + remove_column :articles, :show_to_followers + end +end diff --git a/features/edit_article.feature b/features/edit_article.feature index 3ec91be..014941d 100644 --- a/features/edit_article.feature +++ b/features/edit_article.feature @@ -47,6 +47,28 @@ Feature: edit article Then I should see "Access denied" @selenium + Scenario: Hide token field when show to members is activated + Given the following communities + | name | identifier | owner | + | Free Software | freesoftware | joaosilva | + And the following users + | login | name | + | mario | Mario Souto | + | maria | Maria Silva | + And "Mario Souto" is a member of "Free Software" + And "Maria Silva" is a member of "Free Software" + And I am on freesoftware's control panel + And I follow "Manage Content" + And I should see "New content" + And I follow "New content" + And I should see "Folder" + When I follow "Folder" + And I fill in "Title" with "My Folder" + And I choose "article_published_false" + And I check "article_show_to_followers" + Then I should not see "Fill in the search" + + @selenium Scenario: show exception users field when you choose the private option Given the following communities | name | identifier | owner | diff --git a/public/javascripts/article.js b/public/javascripts/article.js index 06901ae..1391160 100644 --- a/public/javascripts/article.js +++ b/public/javascripts/article.js @@ -136,7 +136,7 @@ jQuery(function($) { if (data.length && data.length > 0) { $('#media-search-results').slideDown(); } - $('#media-search-box .header').toggleClass('icon-loading'); + $('#media-search-box .header').toggleClass('icon-loading'); }); return false; }); @@ -144,20 +144,20 @@ jQuery(function($) { $('#media-upload-form form').ajaxForm({ resetForm: true, beforeSubmit: - function() { - $('#media-upload-form').slideUp(); - $('#media-upload-box .header').toggleClass('icon-loading'); - }, + function() { + $('#media-upload-form').slideUp(); + $('#media-upload-box .header').toggleClass('icon-loading'); + }, success: - function(text) { - text = text.replace('
', '').replace('', ''); // old firefox
- var data = $.parseJSON(text);
- list_items(data, '#media-upload-results .items', true);
- if (data.length && data.length > 0) {
- $('#media-upload-results').slideDown();
- }
- $('#media-upload-box .header').toggleClass('icon-loading');
+ function(text) {
+ text = text.replace('', '').replace('', ''); // old firefox
+ var data = $.parseJSON(text);
+ list_items(data, '#media-upload-results .items', true);
+ if (data.length && data.length > 0) {
+ $('#media-upload-results').slideDown();
}
+ $('#media-upload-box .header').toggleClass('icon-loading');
+ }
});
$('#media-upload-more-files').click(function() {
@@ -166,19 +166,45 @@ jQuery(function($) {
return false;
});
+ function is_public_article() {
+ return $("#article_published_true").attr('checked');
+ }
+
+ function show_hide_privacy_options() {
+ var show_privacy_options = $("#article_published_false").attr('checked');
+ var custom_privacy_option = $(".custom_privacy_option").parent("div");
+
+ if( show_privacy_options ) {
+ custom_privacy_option.show();
+ } else {
+ custom_privacy_option.hide();
+ }
+ show_hide_token_input();
+ }
+
function show_hide_token_input() {
- if($("#article_published_false").attr('checked'))
- $("#text-input-search-exception-users").parent("div").css('display', 'block');
- else
- $("#text-input-search-exception-users").parent("div").css('display', 'none');
+ var display_token = $(".custom_privacy_option:checked").length == 0;
+ var token_field = $("#text-input-search-exception-users").parent("div");
+
+ if( display_token && !is_public_article() ) {
+ token_field.css('display', 'block');
+ } else {
+ token_field.css('display', 'none');
+ }
}
if( $("#token-input-search-article-privacy-exceptions").length == 1 ) {
+ show_hide_privacy_options();
show_hide_token_input();
-
- //Hide / Show the text area
- $("#article_published_false").click(show_hide_token_input);
- $("#article_published_true").click(show_hide_token_input);
}
+ $(document).ready(function(){
+ show_hide_privacy_options();
+ });
+
+ //Hide / Show the text area
+ $("#article_published_false").click(show_hide_privacy_options);
+ $("#article_published_true").click(show_hide_privacy_options);
+ $(".custom_privacy_option").click(show_hide_token_input);
+
});
diff --git a/test/functional/content_viewer_controller_test.rb b/test/functional/content_viewer_controller_test.rb
index 03ef14c..9517922 100644
--- a/test/functional/content_viewer_controller_test.rb
+++ b/test/functional/content_viewer_controller_test.rb
@@ -661,8 +661,8 @@ class ContentViewerControllerTest < ActionController::TestCase
get :view_page, :profile => owner.identifier, :page => folder.path
assert_response :success
assert_select '.image-gallery-item', 0
- end
-
+ end
+
should 'display default image in the slideshow if thumbnails were not processed' do
@controller.stubs(:per_page).returns(1)
@@ -1296,14 +1296,14 @@ class ContentViewerControllerTest < ActionController::TestCase
def comment_form_extra_contents(args)
proc {
hidden_field_tag('comment[some_field_id]', 1)
- }
+ }
end
end
class Plugin2 < Noosfero::Plugin
def comment_form_extra_contents(args)
proc {
hidden_field_tag('comment[another_field_id]', 1)
- }
+ }
end
end
Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
@@ -1373,20 +1373,20 @@ class ContentViewerControllerTest < ActionController::TestCase
get :view_page, :profile => profile.identifier, :page => [blog.path]
assert_tag :tag => 'strong', :content => /bold/
end
-
+
should 'add extra content on article header from plugins' do
class Plugin1 < Noosfero::Plugin
def article_header_extra_contents(args)
proc {
content_tag('div', '', :class => 'plugin1')
- }
+ }
end
end
class Plugin2 < Noosfero::Plugin
def article_header_extra_contents(args)
proc {
content_tag('div', '', :class => 'plugin2')
- }
+ }
end
end
Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
@@ -1447,4 +1447,35 @@ class ContentViewerControllerTest < ActionController::TestCase
assert_tag :tag => 'meta', :attributes => { :property => 'og:image', :content => /\/images\/x.png/ }
end
+ should 'manage private article visualization' do
+ community = Community.create(:name => 'test-community')
+ community.add_member(@profile)
+ community.save!
+
+ blog = community.articles.find_by_name("Blog")
+
+ article = TinyMceArticle.create(:name => 'Article to be shared with images',
+ :body => 'This article should be shared with all social networks',
+ :profile => @profile,
+ :published => false,
+ :show_to_followers => true)
+ article.parent = blog
+ article.save!
+
+ otheruser = create_user('otheruser').person
+ community.add_member(otheruser)
+ login_as(otheruser.identifier)
+
+ get :view_page, :profile => community.identifier, "page" => 'blog'
+
+ assert_response :success
+ assert_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name
+
+ article.show_to_followers = false
+ article.save!
+
+ get :view_page, :profile => community.identifier, "page" => 'blog'
+
+ assert_no_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name
+ end
end
--
libgit2 0.21.2