Commit b3068b11263fab2924cd91501cec37b1feb76fb4
Committed by
Arthur Esposte
1 parent
46080e93
Exists in
master
and in
22 other branches
Add option to all community and users followers view a private article
Signed-off-by: André Bernardes <andrebsguedes@gmail.com> Signed-off-by: Arthur Del Esposte <arthurmde@gmail.com> Signed-off-by: David Carlos <ddavidcarlos1392@gmail.com> Signed-off-by: Fabio Teixeira <fabio1079@gmail.com> Signed-off-by: Filipe Ribeiro <firibeiro77@live.com> Signed-off-by: Gabriela Navarro <navarro1703@gmail.com> Signed-off-by: Luciano Prestes <lucianopcbr@gmail.com> Signed-off-by: Pedro de Lyra <pedrodelyra@gmail.com>
Showing
6 changed files
with
185 additions
and
39 deletions
Show diff stats
app/helpers/article_helper.rb
| ... | ... | @@ -77,12 +77,59 @@ module ArticleHelper |
| 77 | 77 | content_tag('div', |
| 78 | 78 | radio_button(:article, :published, false) + |
| 79 | 79 | content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") |
| 80 | - ) + | |
| 81 | - (article.profile.community? ? content_tag('div', | |
| 82 | - content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") + | |
| 83 | - token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'}, | |
| 84 | - {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) : | |
| 85 | - '')) | |
| 80 | + ) + | |
| 81 | + privacity_exceptions(article, tokenized_children) | |
| 82 | + ) | |
| 83 | + end | |
| 84 | + | |
| 85 | + def privacity_exceptions(article, tokenized_children) | |
| 86 | + content_tag('div', | |
| 87 | + content_tag('div', | |
| 88 | + ( | |
| 89 | + if article.profile | |
| 90 | + add_option_to_followers(article, tokenized_children) | |
| 91 | + else | |
| 92 | + '' | |
| 93 | + end | |
| 94 | + ) | |
| 95 | + ), | |
| 96 | + :style => "margin-left:10px" | |
| 97 | + ) | |
| 98 | + end | |
| 99 | + | |
| 100 | + def add_option_to_followers(article, tokenized_children) | |
| 101 | + label_message = article.profile.organization? ? _('For all community members') : _('For all your friends') | |
| 102 | + | |
| 103 | + check_box( | |
| 104 | + :article, | |
| 105 | + :show_to_followers, | |
| 106 | + {:class => "custom_privacy_option"} | |
| 107 | + ) + | |
| 108 | + content_tag( | |
| 109 | + 'label', | |
| 110 | + label_message, | |
| 111 | + :for => 'article_show_to_followers', | |
| 112 | + :id => 'label_show_to_followers' | |
| 113 | + ) + | |
| 114 | + (article.profile.community? ? | |
| 115 | + content_tag( | |
| 116 | + 'div', | |
| 117 | + content_tag( | |
| 118 | + 'label', | |
| 119 | + _('Fill in the search field to add the exception users to see this content'), | |
| 120 | + :id => "text-input-search-exception-users" | |
| 121 | + ) + | |
| 122 | + token_input_field_tag( | |
| 123 | + :q, | |
| 124 | + 'search-article-privacy-exceptions', | |
| 125 | + {:action => 'search_article_privacy_exceptions'}, | |
| 126 | + { | |
| 127 | + :focus => false, | |
| 128 | + :hint_text => _('Type in a search term for a user'), | |
| 129 | + :pre_populate => tokenized_children | |
| 130 | + } | |
| 131 | + ) | |
| 132 | + ) : '') | |
| 86 | 133 | end |
| 87 | 134 | |
| 88 | 135 | def prepare_to_token_input(array) | ... | ... |
app/models/article.rb
| ... | ... | @@ -2,7 +2,14 @@ require 'hpricot' |
| 2 | 2 | |
| 3 | 3 | class Article < ActiveRecord::Base |
| 4 | 4 | |
| 5 | - 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 | |
| 5 | + attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, | |
| 6 | + :allow_members_to_edit, :translation_of_id, :language, | |
| 7 | + :license_id, :parent_id, :display_posts_in_current_language, | |
| 8 | + :category_ids, :posts_per_page, :moderate_comments, | |
| 9 | + :accept_comments, :feed, :published, :source, | |
| 10 | + :highlighted, :notify_comments, :display_hits, :slug, | |
| 11 | + :external_feed_builder, :display_versions, :external_link, | |
| 12 | + :image_builder, :show_to_followers | |
| 6 | 13 | |
| 7 | 14 | acts_as_having_image |
| 8 | 15 | |
| ... | ... | @@ -333,7 +340,7 @@ class Article < ActiveRecord::Base |
| 333 | 340 | def belongs_to_blog? |
| 334 | 341 | self.parent and self.parent.blog? |
| 335 | 342 | end |
| 336 | - | |
| 343 | + | |
| 337 | 344 | def belongs_to_forum? |
| 338 | 345 | self.parent and self.parent.forum? |
| 339 | 346 | end |
| ... | ... | @@ -445,6 +452,7 @@ class Article < ActiveRecord::Base |
| 445 | 452 | if self.parent && !self.parent.published? |
| 446 | 453 | return false |
| 447 | 454 | end |
| 455 | + | |
| 448 | 456 | true |
| 449 | 457 | else |
| 450 | 458 | false |
| ... | ... | @@ -476,14 +484,17 @@ class Article < ActiveRecord::Base |
| 476 | 484 | {:conditions => [" articles.published = ? OR |
| 477 | 485 | articles.last_changed_by_id = ? OR |
| 478 | 486 | articles.profile_id = ? OR |
| 479 | - ?", | |
| 480 | - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] } | |
| 487 | + ? OR articles.show_to_followers = ? AND ?", | |
| 488 | + true, user.id, user.id, user.has_permission?(:view_private_content, profile), | |
| 489 | + true, user.follows?(profile)]} | |
| 481 | 490 | end |
| 482 | 491 | |
| 492 | + | |
| 483 | 493 | def display_unpublished_article_to?(user) |
| 484 | 494 | user == author || allow_view_private_content?(user) || user == profile || |
| 485 | 495 | user.is_admin?(profile.environment) || user.is_admin?(profile) || |
| 486 | - article_privacy_exceptions.include?(user) | |
| 496 | + article_privacy_exceptions.include?(user) || | |
| 497 | + (self.show_to_followers && user.follows?(profile)) | |
| 487 | 498 | end |
| 488 | 499 | |
| 489 | 500 | def display_to?(user = nil) | ... | ... |
db/migrate/20150113131617_add_show_to_followers_for_article.rb
0 → 100644
features/edit_article.feature
| ... | ... | @@ -47,6 +47,28 @@ Feature: edit article |
| 47 | 47 | Then I should see "Access denied" |
| 48 | 48 | |
| 49 | 49 | @selenium |
| 50 | + Scenario: Hide token field when show to members is activated | |
| 51 | + Given the following communities | |
| 52 | + | name | identifier | owner | | |
| 53 | + | Free Software | freesoftware | joaosilva | | |
| 54 | + And the following users | |
| 55 | + | login | name | | |
| 56 | + | mario | Mario Souto | | |
| 57 | + | maria | Maria Silva | | |
| 58 | + And "Mario Souto" is a member of "Free Software" | |
| 59 | + And "Maria Silva" is a member of "Free Software" | |
| 60 | + And I am on freesoftware's control panel | |
| 61 | + And I follow "Manage Content" | |
| 62 | + And I should see "New content" | |
| 63 | + And I follow "New content" | |
| 64 | + And I should see "Folder" | |
| 65 | + When I follow "Folder" | |
| 66 | + And I fill in "Title" with "My Folder" | |
| 67 | + And I choose "article_published_false" | |
| 68 | + And I check "article_show_to_followers" | |
| 69 | + Then I should not see "Fill in the search" | |
| 70 | + | |
| 71 | + @selenium | |
| 50 | 72 | Scenario: show exception users field when you choose the private option |
| 51 | 73 | Given the following communities |
| 52 | 74 | | name | identifier | owner | | ... | ... |
public/javascripts/article.js
| ... | ... | @@ -136,7 +136,7 @@ jQuery(function($) { |
| 136 | 136 | if (data.length && data.length > 0) { |
| 137 | 137 | $('#media-search-results').slideDown(); |
| 138 | 138 | } |
| 139 | - $('#media-search-box .header').toggleClass('icon-loading'); | |
| 139 | + $('#media-search-box .header').toggleClass('icon-loading'); | |
| 140 | 140 | }); |
| 141 | 141 | return false; |
| 142 | 142 | }); |
| ... | ... | @@ -144,20 +144,20 @@ jQuery(function($) { |
| 144 | 144 | $('#media-upload-form form').ajaxForm({ |
| 145 | 145 | resetForm: true, |
| 146 | 146 | beforeSubmit: |
| 147 | - function() { | |
| 148 | - $('#media-upload-form').slideUp(); | |
| 149 | - $('#media-upload-box .header').toggleClass('icon-loading'); | |
| 150 | - }, | |
| 147 | + function() { | |
| 148 | + $('#media-upload-form').slideUp(); | |
| 149 | + $('#media-upload-box .header').toggleClass('icon-loading'); | |
| 150 | + }, | |
| 151 | 151 | success: |
| 152 | - function(text) { | |
| 153 | - text = text.replace('<pre>', '').replace('</pre>', ''); // old firefox | |
| 154 | - var data = $.parseJSON(text); | |
| 155 | - list_items(data, '#media-upload-results .items', true); | |
| 156 | - if (data.length && data.length > 0) { | |
| 157 | - $('#media-upload-results').slideDown(); | |
| 158 | - } | |
| 159 | - $('#media-upload-box .header').toggleClass('icon-loading'); | |
| 152 | + function(text) { | |
| 153 | + text = text.replace('<pre>', '').replace('</pre>', ''); // old firefox | |
| 154 | + var data = $.parseJSON(text); | |
| 155 | + list_items(data, '#media-upload-results .items', true); | |
| 156 | + if (data.length && data.length > 0) { | |
| 157 | + $('#media-upload-results').slideDown(); | |
| 160 | 158 | } |
| 159 | + $('#media-upload-box .header').toggleClass('icon-loading'); | |
| 160 | + } | |
| 161 | 161 | }); |
| 162 | 162 | |
| 163 | 163 | $('#media-upload-more-files').click(function() { |
| ... | ... | @@ -166,19 +166,45 @@ jQuery(function($) { |
| 166 | 166 | return false; |
| 167 | 167 | }); |
| 168 | 168 | |
| 169 | + function is_public_article() { | |
| 170 | + return $("#article_published_true").attr('checked'); | |
| 171 | + } | |
| 172 | + | |
| 173 | + function show_hide_privacy_options() { | |
| 174 | + var show_privacy_options = $("#article_published_false").attr('checked'); | |
| 175 | + var custom_privacy_option = $(".custom_privacy_option").parent("div"); | |
| 176 | + | |
| 177 | + if( show_privacy_options ) { | |
| 178 | + custom_privacy_option.show(); | |
| 179 | + } else { | |
| 180 | + custom_privacy_option.hide(); | |
| 181 | + } | |
| 182 | + show_hide_token_input(); | |
| 183 | + } | |
| 184 | + | |
| 169 | 185 | function show_hide_token_input() { |
| 170 | - if($("#article_published_false").attr('checked')) | |
| 171 | - $("#text-input-search-exception-users").parent("div").css('display', 'block'); | |
| 172 | - else | |
| 173 | - $("#text-input-search-exception-users").parent("div").css('display', 'none'); | |
| 186 | + var display_token = $(".custom_privacy_option:checked").length == 0; | |
| 187 | + var token_field = $("#text-input-search-exception-users").parent("div"); | |
| 188 | + | |
| 189 | + if( display_token && !is_public_article() ) { | |
| 190 | + token_field.css('display', 'block'); | |
| 191 | + } else { | |
| 192 | + token_field.css('display', 'none'); | |
| 193 | + } | |
| 174 | 194 | } |
| 175 | 195 | |
| 176 | 196 | if( $("#token-input-search-article-privacy-exceptions").length == 1 ) { |
| 197 | + show_hide_privacy_options(); | |
| 177 | 198 | show_hide_token_input(); |
| 178 | - | |
| 179 | - //Hide / Show the text area | |
| 180 | - $("#article_published_false").click(show_hide_token_input); | |
| 181 | - $("#article_published_true").click(show_hide_token_input); | |
| 182 | 199 | } |
| 183 | 200 | |
| 201 | + $(document).ready(function(){ | |
| 202 | + show_hide_privacy_options(); | |
| 203 | + }); | |
| 204 | + | |
| 205 | + //Hide / Show the text area | |
| 206 | + $("#article_published_false").click(show_hide_privacy_options); | |
| 207 | + $("#article_published_true").click(show_hide_privacy_options); | |
| 208 | + $(".custom_privacy_option").click(show_hide_token_input); | |
| 209 | + | |
| 184 | 210 | }); | ... | ... |
test/functional/content_viewer_controller_test.rb
| ... | ... | @@ -661,8 +661,8 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 661 | 661 | get :view_page, :profile => owner.identifier, :page => folder.path |
| 662 | 662 | assert_response :success |
| 663 | 663 | assert_select '.image-gallery-item', 0 |
| 664 | - end | |
| 665 | - | |
| 664 | + end | |
| 665 | + | |
| 666 | 666 | |
| 667 | 667 | should 'display default image in the slideshow if thumbnails were not processed' do |
| 668 | 668 | @controller.stubs(:per_page).returns(1) |
| ... | ... | @@ -1296,14 +1296,14 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 1296 | 1296 | def comment_form_extra_contents(args) |
| 1297 | 1297 | proc { |
| 1298 | 1298 | hidden_field_tag('comment[some_field_id]', 1) |
| 1299 | - } | |
| 1299 | + } | |
| 1300 | 1300 | end |
| 1301 | 1301 | end |
| 1302 | 1302 | class Plugin2 < Noosfero::Plugin |
| 1303 | 1303 | def comment_form_extra_contents(args) |
| 1304 | 1304 | proc { |
| 1305 | 1305 | hidden_field_tag('comment[another_field_id]', 1) |
| 1306 | - } | |
| 1306 | + } | |
| 1307 | 1307 | end |
| 1308 | 1308 | end |
| 1309 | 1309 | Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name]) |
| ... | ... | @@ -1373,20 +1373,20 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 1373 | 1373 | get :view_page, :profile => profile.identifier, :page => [blog.path] |
| 1374 | 1374 | assert_tag :tag => 'strong', :content => /bold/ |
| 1375 | 1375 | end |
| 1376 | - | |
| 1376 | + | |
| 1377 | 1377 | should 'add extra content on article header from plugins' do |
| 1378 | 1378 | class Plugin1 < Noosfero::Plugin |
| 1379 | 1379 | def article_header_extra_contents(args) |
| 1380 | 1380 | proc { |
| 1381 | 1381 | content_tag('div', '', :class => 'plugin1') |
| 1382 | - } | |
| 1382 | + } | |
| 1383 | 1383 | end |
| 1384 | 1384 | end |
| 1385 | 1385 | class Plugin2 < Noosfero::Plugin |
| 1386 | 1386 | def article_header_extra_contents(args) |
| 1387 | 1387 | proc { |
| 1388 | 1388 | content_tag('div', '', :class => 'plugin2') |
| 1389 | - } | |
| 1389 | + } | |
| 1390 | 1390 | end |
| 1391 | 1391 | end |
| 1392 | 1392 | Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name]) |
| ... | ... | @@ -1447,4 +1447,35 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 1447 | 1447 | assert_tag :tag => 'meta', :attributes => { :property => 'og:image', :content => /\/images\/x.png/ } |
| 1448 | 1448 | end |
| 1449 | 1449 | |
| 1450 | + should 'manage private article visualization' do | |
| 1451 | + community = Community.create(:name => 'test-community') | |
| 1452 | + community.add_member(@profile) | |
| 1453 | + community.save! | |
| 1454 | + | |
| 1455 | + blog = community.articles.find_by_name("Blog") | |
| 1456 | + | |
| 1457 | + article = TinyMceArticle.create(:name => 'Article to be shared with images', | |
| 1458 | + :body => 'This article should be shared with all social networks', | |
| 1459 | + :profile => @profile, | |
| 1460 | + :published => false, | |
| 1461 | + :show_to_followers => true) | |
| 1462 | + article.parent = blog | |
| 1463 | + article.save! | |
| 1464 | + | |
| 1465 | + otheruser = create_user('otheruser').person | |
| 1466 | + community.add_member(otheruser) | |
| 1467 | + login_as(otheruser.identifier) | |
| 1468 | + | |
| 1469 | + get :view_page, :profile => community.identifier, "page" => 'blog' | |
| 1470 | + | |
| 1471 | + assert_response :success | |
| 1472 | + assert_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name | |
| 1473 | + | |
| 1474 | + article.show_to_followers = false | |
| 1475 | + article.save! | |
| 1476 | + | |
| 1477 | + get :view_page, :profile => community.identifier, "page" => 'blog' | |
| 1478 | + | |
| 1479 | + assert_no_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name | |
| 1480 | + end | |
| 1450 | 1481 | end | ... | ... |