Commit a6151343194e4273a3828152d7a1664e304ccaba
Exists in
master
and in
29 other branches
Merge branch 'article_privacity_to_followers' into 'master'
Article privacity to followers https://gitlab.com/participa/noosfero/issues/324 Feitos para amigos de perfis de pessoas também! See merge request !422
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 | ... | ... |