diff --git a/app/controllers/my_profile/cms_controller.rb b/app/controllers/my_profile/cms_controller.rb index a1e007e..81ee8de 100644 --- a/app/controllers/my_profile/cms_controller.rb +++ b/app/controllers/my_profile/cms_controller.rb @@ -2,6 +2,8 @@ class CmsController < MyProfileController protect 'edit_profile', :profile, :only => [:set_home_page] + include ArticleHelper + def self.protect_if(*args) before_filter(*args) do |c| user, profile = c.send(:user), c.send(:profile) @@ -70,6 +72,14 @@ class CmsController < MyProfileController translations if @article.translatable? continue = params[:continue] + @article.article_privacy_exceptions = params[:q].split(/,/).map{|n| environment.people.find n.to_i} unless params[:q].nil? + + @tokenized_children = prepare_to_token_input( + profile.members.map{|m| + m if @article.article_privacy_exceptions.include?(m) + }.compact + ) + refuse_blocks record_coming if request.post? @@ -130,6 +140,8 @@ class CmsController < MyProfileController continue = params[:continue] if request.post? + @article.article_privacy_exceptions = params[:q].split(/,/).map{|n| environment.people.find n.to_i} unless params[:q].nil? + if @article.save if continue redirect_to :action => 'edit', :id => @article @@ -290,6 +302,12 @@ class CmsController < MyProfileController render :text => article_list_to_json(results), :content_type => 'application/json' end + def search_article_privacy_exceptions + arg = params[:q].downcase + result = profile.members.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"]) + render :text => prepare_to_token_input(result).to_json + end + def media_upload files_uploaded = [] parent = check_parent(params[:parent_id]) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7068422..5a1a669 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -40,6 +40,8 @@ module ApplicationHelper include Noosfero::Gravatar + include TokenHelper + def locale (@page && !@page.language.blank?) ? @page.language : FastGettext.locale end @@ -1299,10 +1301,6 @@ module ApplicationHelper content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs') end - def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...')) - "hintText: '#{hintText}', noResultsText: '#{noResultsText}', searchingText: '#{searchingText}'" - end - def delete_article_message(article) if article.folder? _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!") @@ -1343,50 +1341,6 @@ module ApplicationHelper ) end - def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {}) - options[:min_chars] ||= 3 - options[:hint_text] ||= _("Type in a search term") - options[:no_results_text] ||= _("No results") - options[:searching_text] ||= _("Searching...") - options[:search_delay] ||= 1000 - options[:prevent_duplicates] ||= true - options[:backspace_delete_item] ||= false - options[:focus] ||= false - options[:avoid_enter] ||= true - options[:on_result] ||= 'null' - options[:on_add] ||= 'null' - options[:on_delete] ||= 'null' - options[:on_ready] ||= 'null' - - result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) - result += javascript_tag("jQuery('##{element_id}') - .tokenInput('#{url_for(search_action)}', { - minChars: #{options[:min_chars].to_json}, - prePopulate: #{options[:pre_populate].to_json}, - hintText: #{options[:hint_text].to_json}, - noResultsText: #{options[:no_results_text].to_json}, - searchingText: #{options[:searching_text].to_json}, - searchDelay: #{options[:serach_delay].to_json}, - preventDuplicates: #{options[:prevent_duplicates].to_json}, - backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, - queryParam: #{name.to_json}, - tokenLimit: #{options[:token_limit].to_json}, - onResult: #{options[:on_result]}, - onAdd: #{options[:on_add]}, - onDelete: #{options[:on_delete]}, - onReady: #{options[:on_ready]}, - }); - ") - result += javascript_tag("jQuery('##{element_id}').focus();") if options[:focus] - if options[:avoid_enter] - result += javascript_tag("jQuery('#token-input-#{element_id}') - .live('keydown', function(event){ - if(event.keyCode == '13') return false; - });") - end - result - end - def expirable_content_reference(content, action, text, url, options = {}) reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first options[:title] = reason diff --git a/app/helpers/article_helper.rb b/app/helpers/article_helper.rb index c532393..6588979 100644 --- a/app/helpers/article_helper.rb +++ b/app/helpers/article_helper.rb @@ -1,18 +1,11 @@ module ArticleHelper - def custom_options_for_article(article) + include TokenHelper + + def custom_options_for_article(article, tokenized_children) @article = article - content_tag('h4', _('Visibility')) + - content_tag('div', - content_tag('div', - radio_button(:article, :published, true) + - content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true') - ) + - content_tag('div', - radio_button(:article, :published, false) + - content_tag('label', _('Private'), :for => 'article_published_false') - ) - ) + + + visibility_options(@article, tokenized_children) + content_tag('h4', _('Options')) + content_tag('div', (article.profile.has_members? ? @@ -53,6 +46,28 @@ module ArticleHelper ) end + def visibility_options(article, tokenized_children) + content_tag('h4', _('Visibility')) + + content_tag('div', + content_tag('div', + radio_button(:article, :published, true) + + content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true') + ) + + content_tag('div', + radio_button(:article, :published, false) + + content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") + ) + + (article.profile.class == 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) + array.map { |object| {:id => object.id, :name => object.name} } + end + def cms_label_for_new_children _('New article') end diff --git a/app/helpers/blog_helper.rb b/app/helpers/blog_helper.rb index 4960e41..740b721 100644 --- a/app/helpers/blog_helper.rb +++ b/app/helpers/blog_helper.rb @@ -1,9 +1,12 @@ module BlogHelper - def custom_options_for_article(article) + include ArticleHelper + + def custom_options_for_article(article,tokenized_children) @article = article hidden_field_tag('article[published]', 1) + - hidden_field_tag('article[accept_comments]', 0) + hidden_field_tag('article[accept_comments]', 0) + + visibility_options(article,tokenized_children) end def cms_label_for_new_children diff --git a/app/helpers/cms_helper.rb b/app/helpers/cms_helper.rb index a858c32..6bd36ca 100644 --- a/app/helpers/cms_helper.rb +++ b/app/helpers/cms_helper.rb @@ -22,9 +22,9 @@ module CmsHelper attr_reader :environment - def options_for_article(article) + def options_for_article(article, tokenized_children=nil) article_helper = helper_for_article(article) - article_helper.custom_options_for_article(article) + article_helper.custom_options_for_article(article, tokenized_children) end def link_to_article(article) diff --git a/app/helpers/folder_helper.rb b/app/helpers/folder_helper.rb index 9df1226..c9d0a43 100644 --- a/app/helpers/folder_helper.rb +++ b/app/helpers/folder_helper.rb @@ -1,6 +1,7 @@ module FolderHelper include ShortFilename + include ArticleHelper def list_articles(articles, recursive = false) if !articles.blank? @@ -60,19 +61,10 @@ module FolderHelper "icon-new icon-new%s" % klass.icon_name end - def custom_options_for_article(article) + def custom_options_for_article(article,tokenized_children) @article = article - content_tag('h4', _('Visibility')) + - content_tag('div', - content_tag('div', - radio_button(:article, :published, true) + - content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true') - ) + - content_tag('div', - radio_button(:article, :published, false) + - content_tag('label', _('Private'), :for => 'article_published_false') - ) - ) + + + visibility_options(article,tokenized_children) + content_tag('div', hidden_field_tag('article[accept_comments]', 0) ) diff --git a/app/helpers/token_helper.rb b/app/helpers/token_helper.rb new file mode 100644 index 0000000..e33d77e --- /dev/null +++ b/app/helpers/token_helper.rb @@ -0,0 +1,51 @@ +module TokenHelper + + def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...')) + "hintText: '#{hintText}', noResultsText: '#{noResultsText}', searchingText: '#{searchingText}'" + end + + def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {}) + options[:min_chars] ||= 3 + options[:hint_text] ||= _("Type in a search term") + options[:no_results_text] ||= _("No results") + options[:searching_text] ||= _("Searching...") + options[:search_delay] ||= 1000 + options[:prevent_duplicates] ||= true + options[:backspace_delete_item] ||= false + options[:focus] ||= false + options[:avoid_enter] ||= true + options[:on_result] ||= 'null' + options[:on_add] ||= 'null' + options[:on_delete] ||= 'null' + options[:on_ready] ||= 'null' + + result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) + result += javascript_tag("jQuery('##{element_id}') + .tokenInput('#{url_for(search_action)}', { + minChars: #{options[:min_chars].to_json}, + prePopulate: #{options[:pre_populate].to_json}, + hintText: #{options[:hint_text].to_json}, + noResultsText: #{options[:no_results_text].to_json}, + searchingText: #{options[:searching_text].to_json}, + searchDelay: #{options[:serach_delay].to_json}, + preventDuplicates: #{options[:prevent_duplicates].to_json}, + backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, + queryParam: #{name.to_json}, + tokenLimit: #{options[:token_limit].to_json}, + onResult: #{options[:on_result]}, + onAdd: #{options[:on_add]}, + onDelete: #{options[:on_delete]}, + onReady: #{options[:on_ready]}, + }); + ") + result += javascript_tag("jQuery('##{element_id}').focus();") if options[:focus] + if options[:avoid_enter] + result += javascript_tag("jQuery('#token-input-#{element_id}') + .live('keydown', function(event){ + if(event.keyCode == '13') return false; + });") + end + result + end + +end \ No newline at end of file diff --git a/app/models/article.rb b/app/models/article.rb index 32b316a..f18ddb3 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -69,6 +69,7 @@ class Article < ActiveRecord::Base settings_items :allow_members_to_edit, :type => :boolean, :default => false settings_items :moderate_comments, :type => :boolean, :default => false settings_items :followers, :type => Array, :default => [] + has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions' belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' @@ -470,7 +471,8 @@ class Article < ActiveRecord::Base def display_unpublished_article_to?(user) user == author || allow_view_private_content?(user) || user == profile || - user.is_admin?(profile.environment) || user.is_admin?(profile) + user.is_admin?(profile.environment) || user.is_admin?(profile) || + article_privacy_exceptions.include?(user) end def display_to?(user = nil) diff --git a/app/models/person.rb b/app/models/person.rb index ba9d0f0..02e3be3 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -63,6 +63,8 @@ class Person < Profile has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy + has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' + named_scope :more_popular, :select => "#{Profile.qualified_column_names}, count(friend_id) as total", :group => Profile.qualified_column_names, diff --git a/app/views/cms/edit.rhtml b/app/views/cms/edit.rhtml index 566ae87..fcd7b1e 100644 --- a/app/views/cms/edit.rhtml +++ b/app/views/cms/edit.rhtml @@ -1,4 +1,5 @@ <%= error_messages_for 'article' %> +<%= javascript_include_tag "article.js" %>