Commit d1609c731d1a14066b2864a25196f5bbeb69b4a9

Authored by Daniela Feitosa
2 parents 527a4b0d 9f616e0b

Merge remote branch 'unb-gama/AI2852-article_access_level' into AI2852

Conflicts:
	app/models/person.rb
	db/schema.rb
app/controllers/my_profile/cms_controller.rb
@@ -2,6 +2,8 @@ class CmsController < MyProfileController @@ -2,6 +2,8 @@ class CmsController < MyProfileController
2 2
3 protect 'edit_profile', :profile, :only => [:set_home_page] 3 protect 'edit_profile', :profile, :only => [:set_home_page]
4 4
  5 + include ArticleHelper
  6 +
5 def self.protect_if(*args) 7 def self.protect_if(*args)
6 before_filter(*args) do |c| 8 before_filter(*args) do |c|
7 user, profile = c.send(:user), c.send(:profile) 9 user, profile = c.send(:user), c.send(:profile)
@@ -70,6 +72,14 @@ class CmsController < MyProfileController @@ -70,6 +72,14 @@ class CmsController < MyProfileController
70 translations if @article.translatable? 72 translations if @article.translatable?
71 continue = params[:continue] 73 continue = params[:continue]
72 74
  75 + @article.article_privacy_exceptions = params[:q].split(/,/).map{|n| environment.people.find n.to_i} unless params[:q].nil?
  76 +
  77 + @tokenized_children = prepare_to_token_input(
  78 + profile.members.map{|m|
  79 + m if @article.article_privacy_exceptions.include?(m)
  80 + }.compact
  81 + )
  82 +
73 refuse_blocks 83 refuse_blocks
74 record_coming 84 record_coming
75 if request.post? 85 if request.post?
@@ -130,6 +140,8 @@ class CmsController < MyProfileController @@ -130,6 +140,8 @@ class CmsController < MyProfileController
130 140
131 continue = params[:continue] 141 continue = params[:continue]
132 if request.post? 142 if request.post?
  143 + @article.article_privacy_exceptions = params[:q].split(/,/).map{|n| environment.people.find n.to_i} unless params[:q].nil?
  144 +
133 if @article.save 145 if @article.save
134 if continue 146 if continue
135 redirect_to :action => 'edit', :id => @article 147 redirect_to :action => 'edit', :id => @article
@@ -290,6 +302,12 @@ class CmsController < MyProfileController @@ -290,6 +302,12 @@ class CmsController < MyProfileController
290 render :text => article_list_to_json(results), :content_type => 'application/json' 302 render :text => article_list_to_json(results), :content_type => 'application/json'
291 end 303 end
292 304
  305 + def search_article_privacy_exceptions
  306 + arg = params[:q].downcase
  307 + result = profile.members.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"])
  308 + render :text => prepare_to_token_input(result).to_json
  309 + end
  310 +
293 def media_upload 311 def media_upload
294 files_uploaded = [] 312 files_uploaded = []
295 parent = check_parent(params[:parent_id]) 313 parent = check_parent(params[:parent_id])
app/helpers/application_helper.rb
@@ -40,6 +40,8 @@ module ApplicationHelper @@ -40,6 +40,8 @@ module ApplicationHelper
40 40
41 include Noosfero::Gravatar 41 include Noosfero::Gravatar
42 42
  43 + include TokenHelper
  44 +
43 def locale 45 def locale
44 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale 46 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale
45 end 47 end
@@ -1300,10 +1302,6 @@ module ApplicationHelper @@ -1300,10 +1302,6 @@ module ApplicationHelper
1300 content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs') 1302 content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs')
1301 end 1303 end
1302 1304
1303 - def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...'))  
1304 - "hintText: '#{hintText}', noResultsText: '#{noResultsText}', searchingText: '#{searchingText}'"  
1305 - end  
1306 -  
1307 def delete_article_message(article) 1305 def delete_article_message(article)
1308 if article.folder? 1306 if article.folder?
1309 _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!") 1307 _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!")
@@ -1344,50 +1342,6 @@ module ApplicationHelper @@ -1344,50 +1342,6 @@ module ApplicationHelper
1344 ) 1342 )
1345 end 1343 end
1346 1344
1347 - def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {})  
1348 - options[:min_chars] ||= 3  
1349 - options[:hint_text] ||= _("Type in a search term")  
1350 - options[:no_results_text] ||= _("No results")  
1351 - options[:searching_text] ||= _("Searching...")  
1352 - options[:search_delay] ||= 1000  
1353 - options[:prevent_duplicates] ||= true  
1354 - options[:backspace_delete_item] ||= false  
1355 - options[:focus] ||= false  
1356 - options[:avoid_enter] ||= true  
1357 - options[:on_result] ||= 'null'  
1358 - options[:on_add] ||= 'null'  
1359 - options[:on_delete] ||= 'null'  
1360 - options[:on_ready] ||= 'null'  
1361 -  
1362 - result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id})))  
1363 - result += javascript_tag("jQuery('##{element_id}')  
1364 - .tokenInput('#{url_for(search_action)}', {  
1365 - minChars: #{options[:min_chars].to_json},  
1366 - prePopulate: #{options[:pre_populate].to_json},  
1367 - hintText: #{options[:hint_text].to_json},  
1368 - noResultsText: #{options[:no_results_text].to_json},  
1369 - searchingText: #{options[:searching_text].to_json},  
1370 - searchDelay: #{options[:serach_delay].to_json},  
1371 - preventDuplicates: #{options[:prevent_duplicates].to_json},  
1372 - backspaceDeleteItem: #{options[:backspace_delete_item].to_json},  
1373 - queryParam: #{name.to_json},  
1374 - tokenLimit: #{options[:token_limit].to_json},  
1375 - onResult: #{options[:on_result]},  
1376 - onAdd: #{options[:on_add]},  
1377 - onDelete: #{options[:on_delete]},  
1378 - onReady: #{options[:on_ready]},  
1379 - });  
1380 - ")  
1381 - result += javascript_tag("jQuery('##{element_id}').focus();") if options[:focus]  
1382 - if options[:avoid_enter]  
1383 - result += javascript_tag("jQuery('#token-input-#{element_id}')  
1384 - .live('keydown', function(event){  
1385 - if(event.keyCode == '13') return false;  
1386 - });")  
1387 - end  
1388 - result  
1389 - end  
1390 -  
1391 def expirable_content_reference(content, action, text, url, options = {}) 1345 def expirable_content_reference(content, action, text, url, options = {})
1392 reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first 1346 reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first
1393 options[:title] = reason 1347 options[:title] = reason
app/helpers/article_helper.rb
1 module ArticleHelper 1 module ArticleHelper
2 2
3 - def custom_options_for_article(article) 3 + include TokenHelper
  4 +
  5 + def custom_options_for_article(article, tokenized_children)
4 @article = article 6 @article = article
5 - content_tag('h4', _('Visibility')) +  
6 - content_tag('div',  
7 - content_tag('div',  
8 - radio_button(:article, :published, true) +  
9 - content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true')  
10 - ) +  
11 - content_tag('div',  
12 - radio_button(:article, :published, false) +  
13 - content_tag('label', _('Private'), :for => 'article_published_false')  
14 - )  
15 - ) + 7 +
  8 + visibility_options(@article, tokenized_children) +
16 content_tag('h4', _('Options')) + 9 content_tag('h4', _('Options')) +
17 content_tag('div', 10 content_tag('div',
18 (article.profile.has_members? ? 11 (article.profile.has_members? ?
@@ -53,6 +46,28 @@ module ArticleHelper @@ -53,6 +46,28 @@ module ArticleHelper
53 ) 46 )
54 end 47 end
55 48
  49 + def visibility_options(article, tokenized_children)
  50 + content_tag('h4', _('Visibility')) +
  51 + content_tag('div',
  52 + content_tag('div',
  53 + radio_button(:article, :published, true) +
  54 + content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true')
  55 + ) +
  56 + content_tag('div',
  57 + radio_button(:article, :published, false) +
  58 + content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private")
  59 + ) +
  60 + (article.profile.class == Community ? content_tag('div',
  61 + content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") +
  62 + token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'},
  63 + {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) :
  64 + ''))
  65 + end
  66 +
  67 + def prepare_to_token_input(array)
  68 + array.map { |object| {:id => object.id, :name => object.name} }
  69 + end
  70 +
56 def cms_label_for_new_children 71 def cms_label_for_new_children
57 _('New article') 72 _('New article')
58 end 73 end
app/helpers/blog_helper.rb
1 module BlogHelper 1 module BlogHelper
2 2
3 - def custom_options_for_article(article) 3 + include ArticleHelper
  4 +
  5 + def custom_options_for_article(article,tokenized_children)
4 @article = article 6 @article = article
5 hidden_field_tag('article[published]', 1) + 7 hidden_field_tag('article[published]', 1) +
6 - hidden_field_tag('article[accept_comments]', 0) 8 + hidden_field_tag('article[accept_comments]', 0) +
  9 + visibility_options(article,tokenized_children)
7 end 10 end
8 11
9 def cms_label_for_new_children 12 def cms_label_for_new_children
app/helpers/cms_helper.rb
@@ -22,9 +22,9 @@ module CmsHelper @@ -22,9 +22,9 @@ module CmsHelper
22 22
23 attr_reader :environment 23 attr_reader :environment
24 24
25 - def options_for_article(article) 25 + def options_for_article(article, tokenized_children=nil)
26 article_helper = helper_for_article(article) 26 article_helper = helper_for_article(article)
27 - article_helper.custom_options_for_article(article) 27 + article_helper.custom_options_for_article(article, tokenized_children)
28 end 28 end
29 29
30 def link_to_article(article) 30 def link_to_article(article)
app/helpers/folder_helper.rb
1 module FolderHelper 1 module FolderHelper
2 2
3 include ShortFilename 3 include ShortFilename
  4 + include ArticleHelper
4 5
5 def list_articles(articles, recursive = false) 6 def list_articles(articles, recursive = false)
6 if !articles.blank? 7 if !articles.blank?
@@ -60,19 +61,10 @@ module FolderHelper @@ -60,19 +61,10 @@ module FolderHelper
60 "icon-new icon-new%s" % klass.icon_name 61 "icon-new icon-new%s" % klass.icon_name
61 end 62 end
62 63
63 - def custom_options_for_article(article) 64 + def custom_options_for_article(article,tokenized_children)
64 @article = article 65 @article = article
65 - content_tag('h4', _('Visibility')) +  
66 - content_tag('div',  
67 - content_tag('div',  
68 - radio_button(:article, :published, true) +  
69 - content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true')  
70 - ) +  
71 - content_tag('div',  
72 - radio_button(:article, :published, false) +  
73 - content_tag('label', _('Private'), :for => 'article_published_false')  
74 - )  
75 - ) + 66 +
  67 + visibility_options(article,tokenized_children) +
76 content_tag('div', 68 content_tag('div',
77 hidden_field_tag('article[accept_comments]', 0) 69 hidden_field_tag('article[accept_comments]', 0)
78 ) 70 )
app/helpers/token_helper.rb 0 → 100644
@@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
  1 +module TokenHelper
  2 +
  3 + def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...'))
  4 + "hintText: '#{hintText}', noResultsText: '#{noResultsText}', searchingText: '#{searchingText}'"
  5 + end
  6 +
  7 + def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {})
  8 + options[:min_chars] ||= 3
  9 + options[:hint_text] ||= _("Type in a search term")
  10 + options[:no_results_text] ||= _("No results")
  11 + options[:searching_text] ||= _("Searching...")
  12 + options[:search_delay] ||= 1000
  13 + options[:prevent_duplicates] ||= true
  14 + options[:backspace_delete_item] ||= false
  15 + options[:focus] ||= false
  16 + options[:avoid_enter] ||= true
  17 + options[:on_result] ||= 'null'
  18 + options[:on_add] ||= 'null'
  19 + options[:on_delete] ||= 'null'
  20 + options[:on_ready] ||= 'null'
  21 +
  22 + result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id})))
  23 + result += javascript_tag("jQuery('##{element_id}')
  24 + .tokenInput('#{url_for(search_action)}', {
  25 + minChars: #{options[:min_chars].to_json},
  26 + prePopulate: #{options[:pre_populate].to_json},
  27 + hintText: #{options[:hint_text].to_json},
  28 + noResultsText: #{options[:no_results_text].to_json},
  29 + searchingText: #{options[:searching_text].to_json},
  30 + searchDelay: #{options[:serach_delay].to_json},
  31 + preventDuplicates: #{options[:prevent_duplicates].to_json},
  32 + backspaceDeleteItem: #{options[:backspace_delete_item].to_json},
  33 + queryParam: #{name.to_json},
  34 + tokenLimit: #{options[:token_limit].to_json},
  35 + onResult: #{options[:on_result]},
  36 + onAdd: #{options[:on_add]},
  37 + onDelete: #{options[:on_delete]},
  38 + onReady: #{options[:on_ready]},
  39 + });
  40 + ")
  41 + result += javascript_tag("jQuery('##{element_id}').focus();") if options[:focus]
  42 + if options[:avoid_enter]
  43 + result += javascript_tag("jQuery('#token-input-#{element_id}')
  44 + .live('keydown', function(event){
  45 + if(event.keyCode == '13') return false;
  46 + });")
  47 + end
  48 + result
  49 + end
  50 +
  51 +end
0 \ No newline at end of file 52 \ No newline at end of file
app/models/article.rb
@@ -69,6 +69,7 @@ class Article < ActiveRecord::Base @@ -69,6 +69,7 @@ class Article < ActiveRecord::Base
69 settings_items :allow_members_to_edit, :type => :boolean, :default => false 69 settings_items :allow_members_to_edit, :type => :boolean, :default => false
70 settings_items :moderate_comments, :type => :boolean, :default => false 70 settings_items :moderate_comments, :type => :boolean, :default => false
71 settings_items :followers, :type => Array, :default => [] 71 settings_items :followers, :type => Array, :default => []
  72 + has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions'
72 73
73 belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' 74 belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id'
74 75
@@ -470,7 +471,8 @@ class Article < ActiveRecord::Base @@ -470,7 +471,8 @@ class Article < ActiveRecord::Base
470 471
471 def display_unpublished_article_to?(user) 472 def display_unpublished_article_to?(user)
472 user == author || allow_view_private_content?(user) || user == profile || 473 user == author || allow_view_private_content?(user) || user == profile ||
473 - user.is_admin?(profile.environment) || user.is_admin?(profile) 474 + user.is_admin?(profile.environment) || user.is_admin?(profile) ||
  475 + article_privacy_exceptions.include?(user)
474 end 476 end
475 477
476 def display_to?(user = nil) 478 def display_to?(user = nil)
app/models/person.rb
@@ -64,6 +64,7 @@ class Person < Profile @@ -64,6 +64,7 @@ class Person < Profile
64 has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy 64 has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy
65 65
66 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' 66 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people'
  67 + has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions'
67 68
68 named_scope :more_popular, 69 named_scope :more_popular,
69 :select => "#{Profile.qualified_column_names}, count(friend_id) as total", 70 :select => "#{Profile.qualified_column_names}, count(friend_id) as total",
app/views/cms/edit.rhtml
1 <%= error_messages_for 'article' %> 1 <%= error_messages_for 'article' %>
  2 +<%= javascript_include_tag "article.js" %>
2 3
3 <div class='<%= (environment.enabled?('media_panel') ? 'with_media_panel' : 'no_media_panel') %>'> 4 <div class='<%= (environment.enabled?('media_panel') ? 'with_media_panel' : 'no_media_panel') %>'>
4 <% labelled_form_for 'article', @article, :html => { :multipart => true, :class => @type } do |f| %> 5 <% labelled_form_for 'article', @article, :html => { :multipart => true, :class => @type } do |f| %>
@@ -33,7 +34,7 @@ @@ -33,7 +34,7 @@
33 <%= content_tag( 'small', _('Separate tags with commas') ) %> 34 <%= content_tag( 'small', _('Separate tags with commas') ) %>
34 35
35 <div id='edit-article-options'> 36 <div id='edit-article-options'>
36 - <%= options_for_article(@article) %> 37 + <%= options_for_article(@article, @tokenized_children) %>
37 </div> 38 </div>
38 39
39 <% button_bar do %> 40 <% button_bar do %>
db/migrate/20140108132730_article_privacy_exceptions.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class ArticlePrivacyExceptions < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :article_privacy_exceptions, :id => false do |t|
  4 + t.integer :article_id
  5 + t.integer :person_id
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + drop_table :article_privacy_exceptions
  11 + end
  12 +end
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 # 9 #
10 # It's strongly recommended to check this file into your version control system. 10 # It's strongly recommended to check this file into your version control system.
11 11
12 -ActiveRecord::Schema.define(:version => 20131128161159) do 12 +ActiveRecord::Schema.define(:version => 20140108132730) do
13 13
14 create_table "abuse_reports", :force => true do |t| 14 create_table "abuse_reports", :force => true do |t|
15 t.integer "reporter_id" 15 t.integer "reporter_id"
@@ -46,6 +46,11 @@ ActiveRecord::Schema.define(:version =&gt; 20131128161159) do @@ -46,6 +46,11 @@ ActiveRecord::Schema.define(:version =&gt; 20131128161159) do
46 add_index "action_tracker_notifications", ["profile_id", "action_tracker_id"], :name => "index_action_tracker_notif_on_prof_id_act_tracker_id", :unique => true 46 add_index "action_tracker_notifications", ["profile_id", "action_tracker_id"], :name => "index_action_tracker_notif_on_prof_id_act_tracker_id", :unique => true
47 add_index "action_tracker_notifications", ["profile_id"], :name => "index_action_tracker_notifications_on_profile_id" 47 add_index "action_tracker_notifications", ["profile_id"], :name => "index_action_tracker_notifications_on_profile_id"
48 48
  49 + create_table "article_privacy_exceptions", :id => false, :force => true do |t|
  50 + t.integer "article_id"
  51 + t.integer "person_id"
  52 + end
  53 +
49 create_table "article_versions", :force => true do |t| 54 create_table "article_versions", :force => true do |t|
50 t.integer "article_id" 55 t.integer "article_id"
51 t.integer "version" 56 t.integer "version"
@@ -460,6 +465,7 @@ ActiveRecord::Schema.define(:version =&gt; 20131128161159) do @@ -460,6 +465,7 @@ ActiveRecord::Schema.define(:version =&gt; 20131128161159) do
460 t.boolean "is_template", :default => false 465 t.boolean "is_template", :default => false
461 t.integer "template_id" 466 t.integer "template_id"
462 t.string "redirection_after_login" 467 t.string "redirection_after_login"
  468 + t.text "settings"
463 end 469 end
464 470
465 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" 471 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id"
features/edit_article.feature
@@ -22,6 +22,70 @@ Feature: edit article @@ -22,6 +22,70 @@ Feature: edit article
22 And I go to joaosilva's control panel 22 And I go to joaosilva's control panel
23 Then I should see "My Folder" 23 Then I should see "My Folder"
24 24
  25 + @selenium
  26 + Scenario: denied access folder for a not logged user
  27 + Given the following communities
  28 + | name | identifier | owner |
  29 + | Free Software | freesoftware | joaosilva |
  30 + And the following users
  31 + | login | name |
  32 + | mario | Mario Souto |
  33 + | maria | Maria Silva |
  34 + And "Mario Souto" is a member of "Free Software"
  35 + And "Maria Silva" is a member of "Free Software"
  36 + And I am on freesoftware's control panel
  37 + And I follow "Manage Content"
  38 + And I follow "New content"
  39 + When I follow "Folder"
  40 + And I fill in "Title" with "My Folder"
  41 + And I choose "article_published_false"
  42 + And I press "Save"
  43 + And I log off
  44 + And I go to /freesoftware/my-folder
  45 + Then I should see "Access denied"
  46 +
  47 + @selenium
  48 + Scenario: show exception users field when you choose the private option
  49 + Given the following communities
  50 + | name | identifier | owner |
  51 + | Free Software | freesoftware | joaosilva |
  52 + And the following users
  53 + | login | name |
  54 + | mario | Mario Souto |
  55 + | maria | Maria Silva |
  56 + And "Mario Souto" is a member of "Free Software"
  57 + And "Maria Silva" is a member of "Free Software"
  58 + And I am on freesoftware's control panel
  59 + And I follow "Manage Content"
  60 + And I follow "New content"
  61 + When I follow "Folder"
  62 + And I fill in "Title" with "My Folder"
  63 + And I choose "article_published_false"
  64 + Then I should see "Fill in the search field to add the exception users to see this content"
  65 +
  66 + @selenium
  67 + Scenario: allowed user should see the content of a folder
  68 + Given the following communities
  69 + | name | identifier | owner |
  70 + | Free Software | freesoftware | joaosilva |
  71 + And the following users
  72 + | login | name |
  73 + | mario | Mario Souto |
  74 + | maria | Maria Silva |
  75 + And the following articles
  76 + | owner | name | body |
  77 + | freesoftware | My Folder | ... |
  78 + And "Mario Souto" is a member of "Free Software"
  79 + And "Maria Silva" is a member of "Free Software"
  80 + And I go to /freesoftware/my-folder
  81 + When I follow "Edit"
  82 + And I choose "article_published_false"
  83 + And I press "Save"
  84 + And I add to "My Folder" the following exception "Maria Silva"
  85 + And I am logged in as "maria"
  86 + And I go to /freesoftware/my-folder
  87 + Then I should see "My Folder"
  88 +
25 Scenario: redirect to the created folder 89 Scenario: redirect to the created folder
26 Given I am on joaosilva's control panel 90 Given I am on joaosilva's control panel
27 And I follow "Manage Content" 91 And I follow "Manage Content"
@@ -40,6 +104,7 @@ Feature: edit article @@ -40,6 +104,7 @@ Feature: edit article
40 When I follow "Cancel" within ".main-block" 104 When I follow "Cancel" within ".main-block"
41 Then I should be on joaosilva's cms 105 Then I should be on joaosilva's cms
42 106
  107 + @selenium
43 Scenario: display tag list field when creating event 108 Scenario: display tag list field when creating event
44 Given I am on joaosilva's control panel 109 Given I am on joaosilva's control panel
45 And I follow "Manage Content" 110 And I follow "Manage Content"
features/step_definitions/content_steps.rb
@@ -8,3 +8,15 @@ When /^I create a content of type &quot;([^\&quot;]*)&quot; with the following data$/ do |conte @@ -8,3 +8,15 @@ When /^I create a content of type &quot;([^\&quot;]*)&quot; with the following data$/ do |conte
8 8
9 click_button "Save" 9 click_button "Save"
10 end 10 end
  11 +
  12 +And /^I add to "([^\"]*)" the following exception "([^\"]*)"$/ do |article_name, user_exception|
  13 + article = Article.find_by_name(article_name)
  14 + community = article.profile
  15 + raise "The article profile is not a community." unless community.class == Community
  16 +
  17 + my_user = community.members.find_by_name(user_exception)
  18 + raise "Could not find #{user_exception} in #{community.name} community." if my_user.nil?
  19 +
  20 + article.article_privacy_exceptions << my_user
  21 + article.save
  22 +end
11 \ No newline at end of file 23 \ No newline at end of file
public/javascripts/article.js
@@ -172,4 +172,19 @@ jQuery(function($) { @@ -172,4 +172,19 @@ jQuery(function($) {
172 return false; 172 return false;
173 }); 173 });
174 174
  175 + function show_hide_token_input() {
  176 + if($("#article_published_false").attr('checked'))
  177 + $("#text-input-search-exception-users").parent("div").css('display', 'block');
  178 + else
  179 + $("#text-input-search-exception-users").parent("div").css('display', 'none');
  180 + }
  181 +
  182 + if( $("#token-input-search-article-privacy-exceptions").length == 1 ) {
  183 + show_hide_token_input();
  184 +
  185 + //Hide / Show the text area
  186 + $("#article_published_false").click(show_hide_token_input);
  187 + $("#article_published_true").click(show_hide_token_input);
  188 + }
  189 +
175 }); 190 });