diff --git a/app/controllers/public/comment_controller.rb b/app/controllers/public/comment_controller.rb new file mode 100644 index 0000000..f8d27b6 --- /dev/null +++ b/app/controllers/public/comment_controller.rb @@ -0,0 +1,177 @@ +class CommentController < ApplicationController + + needs_profile + + def create + begin + @page = profile.articles.find(params[:id]) + rescue + @page = nil + end + + # page not found, give error + if @page.nil? + respond_to do |format| + format.js do + render :json => { :msg => _('Page not found.')} + end + end + return + end + + unless @page.accept_comments? + respond_to do |format| + format.js do + render :json => { :msg => _('Comment not allowed in this article')} + end + end + return + end + + @comment = Comment.new(params[:comment]) + @comment.author = user if logged_in? + @comment.article = @page + @comment.ip_address = request.remote_ip + @comment.user_agent = request.user_agent + @comment.referrer = request.referrer + plugins_filter_comment(@comment) + + if @comment.rejected? + respond_to do |format| + format.js do + render :json => { :msg => _('Comment was rejected')} + end + end + return + end + + if !@comment.valid? || (not pass_without_comment_captcha? and not verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) + respond_to do |format| + format.js do + render :json => { + :render_target => 'form', + :html => render_to_string(:partial => 'comment_form', :object => @comment, :locals => {:comment => @comment, :display_link => true, :show_form => true}) + } + end + end + return + end + + if @comment.article.moderate_comments? && !(@comment.author && @comment.author_id == @comment.article.author_id) + @comment.created_at = Time.now + ApproveComment.create!(:requestor => @comment.author, :target => profile, :comment_attributes => @comment.attributes.to_json) + + respond_to do |format| + format.js do + render :json => { :render_target => nil, :msg => _('Your comment is waiting for approval.') } + end + end + return + end + + @comment.save + + respond_to do |format| + format.js do + comment_to_render = @comment.comment_root + render :json => { + :render_target => comment_to_render.anchor, + :html => render_to_string(:partial => 'comment', :locals => {:comment => comment_to_render, :display_link => true}), + :msg => _('Comment successfully created.') + } + end + end + end + + def destroy + comment = profile.comments_received.find(params[:id]) + + could_remove = (user == comment.author || user == comment.profile || user.has_permission?(:moderate_comments, comment.profile)) + if comment && could_remove && comment.destroy + render :text => {'ok' => true}.to_json, :content_type => 'application/json' + else + session[:notice] = _("The comment was not removed.") + render :text => {'ok' => false}.to_json, :content_type => 'application/json' + end + end + + def mark_as_spam + comment = profile.comments_received.find(params[:id]) + could_mark_as_spam = (user == comment.profile || user.has_permission?(:moderate_comments, comment.profile)) + + if logged_in? && could_mark_as_spam + comment.spam! + render :text => {'ok' => true}.to_json, :content_type => 'application/json' + else + session[:notice] = _("You couldn't mark this comment as spam.") + render :text => {'ok' => false}.to_json, :content_type => 'application/json' + end + end + + def edit + begin + @comment = profile.comments_received.find(params[:id]) + rescue ActiveRecord::RecordNotFound + @comment = nil + end + + if @comment.nil? + render_not_found + return + end + + display_link = params[:reply_of_id].present? && !params[:reply_of_id].empty? + + render :partial => "comment_form", :locals => {:comment => @comment, :display_link => display_link, :edition_mode => true, :show_form => true} + end + + def update + begin + @comment = profile.comments_received.find(params[:id]) + rescue ActiveRecord::RecordNotFound + @comment = nil + end + + if @comment.nil? or user != @comment.author + render_not_found + return + end + + if @comment.update_attributes(params[:comment]) + respond_to do |format| + format.js do + comment_to_render = @comment.comment_root + render :json => { + :ok => true, + :render_target => comment_to_render.anchor, + :html => render_to_string(:partial => 'comment', :locals => {:comment => comment_to_render}) + } + end + end + else + respond_to do |format| + format.js do + render :json => { + :ok => false, + :render_target => 'form', + :html => render_to_string(:partial => 'comment_form', :object => @comment, :locals => {:comment => @comment, :display_link => false, :edition_mode => true}) + } + end + end + end + end + + protected + + def plugins_filter_comment(comment) + @plugins.each do |plugin| + plugin.filter_comment(comment) + end + end + + def pass_without_comment_captcha? + logged_in? && !environment.enabled?('captcha_for_logged_users') + end + helper_method :pass_without_comment_captcha? + +end diff --git a/app/controllers/public/content_viewer_controller.rb b/app/controllers/public/content_viewer_controller.rb index 602eea8..6a017fb 100644 --- a/app/controllers/public/content_viewer_controller.rb +++ b/app/controllers/public/content_viewer_controller.rb @@ -2,8 +2,6 @@ class ContentViewerController < ApplicationController needs_profile - before_filter :comment_author, :only => :edit_comment - helper ProfileHelper helper TagsHelper @@ -70,24 +68,8 @@ class ContentViewerController < ApplicationController @form_div = params[:form] - if params[:comment] && params[:confirm] == 'true' - @comment = Comment.new(params[:comment]) - if request.post? && @page.accept_comments? - add_comment - end - else - @comment = Comment.new - end - - if request.post? - if params[:remove_comment] - remove_comment - return - elsif params[:mark_comment_as_spam] - mark_comment_as_spam - return - end - end + #FIXME see a better way to do this. It's not need to pass this variable anymore + @comment = Comment.new if @page.has_posts? posts = if params[:year] and params[:month] @@ -125,81 +107,8 @@ class ContentViewerController < ApplicationController end end - def edit_comment - path = params[:page].join('/') - @page = profile.articles.find_by_path(path) - @form_div = 'opened' - @comment = @page.comments.find_by_id(params[:id]) - if @comment - if request.post? - begin - @comment.update_attributes(params[:comment]) - session[:notice] = _('Comment succesfully updated') - redirect_to :action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path - rescue - session[:notice] = _('Comment could not be updated') - end - end - else - redirect_to @page.view_url - session[:notice] = _('Could not find the comment in the article') - end - end - protected - def add_comment - @comment.author = user if logged_in? - @comment.article = @page - @comment.ip_address = request.remote_ip - @comment.user_agent = request.user_agent - @comment.referrer = request.referrer - plugins_filter_comment(@comment) - return if @comment.rejected? - if (pass_without_comment_captcha? || verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) && @comment.save - @page.touch - @comment = nil # clear the comment form - redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] - else - @form_div = 'opened' if params[:comment][:reply_of_id].blank? - end - end - - def plugins_filter_comment(comment) - @plugins.each do |plugin| - plugin.filter_comment(comment) - end - end - - def pass_without_comment_captcha? - logged_in? && !environment.enabled?('captcha_for_logged_users') - end - helper_method :pass_without_comment_captcha? - - def remove_comment - @comment = @page.comments.find(params[:remove_comment]) - if (user == @comment.author || user == @page.profile || user.has_permission?(:moderate_comments, @page.profile)) - @comment.destroy - end - finish_comment_handling - end - - def mark_comment_as_spam - @comment = @page.comments.find(params[:mark_comment_as_spam]) - if logged_in? && (user == @page.profile || user.has_permission?(:moderate_comments, @page.profile)) - @comment.spam! - end - finish_comment_handling - end - - def finish_comment_handling - if request.xhr? - render :text => {'ok' => true}.to_json, :content_type => 'application/json' - else - redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] - end - end - def per_page 12 end @@ -223,13 +132,9 @@ class ContentViewerController < ApplicationController end end - def comment_author - comment = Comment.find_by_id(params[:id]) - if comment - render_access_denied if comment.author.blank? || comment.author != user - else - render_not_found - end + def pass_without_comment_captcha? + logged_in? && !environment.enabled?('captcha_for_logged_users') end + helper_method :pass_without_comment_captcha? end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index db14797..2c3b35a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1403,12 +1403,14 @@ module ApplicationHelper end def expirable_button(content, action, text, url, options = {}) - options[:class] = "button with-text icon-#{action.to_s}" + #FIXME Leandro see if it's needed the options class parameter + options[:class] = "button with-text icon-#{action.to_s}" + (options[:class].nil? ? '' : " " + options[:class]) expirable_content_reference content, action, text, url, options end def expirable_comment_link(content, action, text, url, options = {}) - options[:class] = "comment-footer comment-footer-link comment-footer-hide" + #FIXME Leandro see if it's needed the options class parameter + options[:class] = "comment-footer comment-footer-link comment-footer-hide" + (options[:class].nil? ? '' : " " + options[:class]) expirable_content_reference content, action, text, url, options end diff --git a/app/helpers/article_helper.rb b/app/helpers/article_helper.rb index d286384..c532393 100644 --- a/app/helpers/article_helper.rb +++ b/app/helpers/article_helper.rb @@ -35,7 +35,13 @@ module ArticleHelper 'div', check_box(:article, :notify_comments) + content_tag('label', _('I want to receive a notification of each comment written by e-mail'), :for => 'article_notify_comments') + - observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked") + observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked;$('article_moderate_comments').disabled = ! $('article_accept_comments').checked") + ) + + + content_tag( + 'div', + check_box(:article, :moderate_comments) + + content_tag('label', _('I want to approve comments on this article'), :for => 'article_moderate_comments') ) + (article.can_display_hits? ? diff --git a/app/helpers/comment_helper.rb b/app/helpers/comment_helper.rb new file mode 100644 index 0000000..d3d1454 --- /dev/null +++ b/app/helpers/comment_helper.rb @@ -0,0 +1,25 @@ +module CommentHelper + + def article_title(article, args = {}) + title = article.display_title if article.kind_of?(UploadedFile) && article.image? + title = article.title if title.blank? + title = content_tag('h1', h(title), :class => 'title') + if article.belongs_to_blog? + unless args[:no_link] + title = content_tag('h1', link_to(article.name, article.url), :class => 'title') + end + comments = '' + unless args[:no_comments] || !article.accept_comments + comments = (" - %s") % link_to_comments(article) + end + title << content_tag('span', + content_tag('span', show_date(article.published_at), :class => 'date') + + content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') + + content_tag('span', comments, :class => 'comments'), + :class => 'created-at' + ) + end + title + end + +end diff --git a/app/helpers/content_viewer_helper.rb b/app/helpers/content_viewer_helper.rb index f6ba368..8de2b05 100644 --- a/app/helpers/content_viewer_helper.rb +++ b/app/helpers/content_viewer_helper.rb @@ -2,14 +2,17 @@ module ContentViewerHelper include BlogHelper include ForumHelper + + def display_number_of_comments(n) + base_str = "#{n}" + + amount_str = n == 0 ? _('no comments yet') : (n == 1 ? _('One comment') : _('%s comments') % n) + + base_str + "#{amount_str}" + end def number_of_comments(article) - n = article.comments.without_spam.count - if n == 0 - _('No comments yet') - else - n_('One comment', '%{comments} comments', n) % { :comments => n } - end + display_number_of_comments(article.comments.without_spam.count) end def article_title(article, args = {}) diff --git a/app/models/approve_comment.rb b/app/models/approve_comment.rb new file mode 100644 index 0000000..361de45 --- /dev/null +++ b/app/models/approve_comment.rb @@ -0,0 +1,101 @@ +class ApproveComment < Task + validates_presence_of :target_id + + settings_items :comment_attributes, :closing_statment + + validates_presence_of :comment_attributes + + def comment + @comment ||= Comment.new(JSON.parse(self.comment_attributes)) unless self.comment_attributes.nil? + @comment + end + + def requestor_name + requestor ? requestor.name : _('Anonymous') + end + + def article + Article.find_by_id comment.source_id unless self.comment.nil? + end + + def article_name + article ? article.name : _("Article removed.") + end + + + def perform + comment.save! + end + + def title + _("New comment to article") + end + + def icon + result = {:type => :defined_image, :src => '/images/icons-app/article-minor.png'} + result.merge({:url => article.url}) if article + return result + end + + def linked_subject + {:text => article_name, :url => article.url} if article + end + + def information + if article + {:message => _('%{requestor} commented on the the article: %{linked_subject}.') % {:requestor => requestor_name} } + else + {:message => _("The article was removed.")} + end + end + + def accept_details + true + end + + def reject_details + true + end + + def default_decision + if article + 'skip' + else + 'reject' + end + end + + def accept_disabled? + article.blank? + end + + def target_notification_description + if article + _('%{requestor} wants to comment the article: %{article}.') % {:requestor => requestor_name, :article => article.name} + else + _('%{requestor} wanted to comment the article but it was removed.') % {:requestor => requestor_name} + end + end + + def target_notification_message + target_notification_description + "\n\n" + + _('You need to login on %{system} in order to approve or reject this comment.') % { :system => target.environment.name } + end + + def task_finished_message + if !closing_statment.blank? + _("Your comment to the article \"%{article}\" was approved. Here is the comment left by the admin who approved your comment:\n\n%{comment} ") % {:article => article_name, :comment => closing_statment} + else + _('Your request for comment the article "%{article}" was approved.') % {:article => article_name} + end + end + + def task_cancelled_message + message = _('Your request for commenting the article "%{article}" was rejected.') % {:article => article_name} + if !reject_explanation.blank? + message += " " + _("Here is the reject explanation left by the administrator who rejected your comment: \n\n%{reject_explanation}") % {:reject_explanation => reject_explanation} + end + message + end + +end diff --git a/app/models/article.rb b/app/models/article.rb index 57d3781..ba9687b 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -2,6 +2,8 @@ require 'hpricot' class Article < ActiveRecord::Base +include ActionController::UrlWriter + # use for internationalizable human type names in search facets # reimplement on subclasses def self.type_name @@ -42,6 +44,7 @@ class Article < ActiveRecord::Base settings_items :display_hits, :type => :boolean, :default => true settings_items :author_name, :type => :string, :default => "" settings_items :allow_members_to_edit, :type => :boolean, :default => false + settings_items :moderate_comments, :type => :boolean, :default => false settings_items :followers, :type => Array, :default => [] belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' @@ -309,6 +312,14 @@ class Article < ActiveRecord::Base @view_url ||= image? ? url.merge(:view => true) : url end + def comment_url_structure(comment, action = :edit) + if comment.new_record? + profile.url.merge(:page => path.split("/"), :controller => :comment, :action => :create) + else + profile.url.merge(:page => path.split("/"), :controller => :comment, :action => action || :edit, :id => comment.id) + end + end + def allow_children? true end @@ -471,6 +482,10 @@ class Article < ActiveRecord::Base allow_post_content?(user) || user && allow_members_to_edit && user.is_member_of?(profile) end + def moderate_comments? + moderate_comments == true + end + def comments_updated solr_save end diff --git a/app/models/comment.rb b/app/models/comment.rb index ed99a97..0671597 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -28,7 +28,14 @@ class Comment < ActiveRecord::Base xss_terminate :only => [ :body, :title, :name ], :on => 'validation' - delegate :environment, :to => :source + #FIXME make this test + def comment_root + if(self.reply_of.present?) + self.reply_of.comment_root + else + self + end + end def action_tracker_target self.article.profile diff --git a/app/models/task.rb b/app/models/task.rb index 8a6acf1..b3656c5 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -74,7 +74,7 @@ class Task < ActiveRecord::Base end def self.all_types - %w[Invitation EnterpriseActivation AddMember Ticket SuggestArticle AddFriend CreateCommunity AbuseComplaint ApproveArticle CreateEnterprise ChangePassword EmailActivation InviteFriend InviteMember] + %w[Invitation EnterpriseActivation AddMember Ticket SuggestArticle AddFriend CreateCommunity AbuseComplaint ApproveComment ApproveArticle CreateEnterprise ChangePassword EmailActivation InviteFriend InviteMember] end # this method finished the task. It calls #perform, which must be overriden diff --git a/app/views/comment/_comment.rhtml b/app/views/comment/_comment.rhtml new file mode 100644 index 0000000..9a2d4c4 --- /dev/null +++ b/app/views/comment/_comment.rhtml @@ -0,0 +1,99 @@ +
  • +
    + +
    + + <% if comment.author %> + <%= link_to image_tag(profile_icon(comment.author, :minor)) + + content_tag('span', comment.author_name, :class => 'comment-info'), + comment.author.url, + :class => 'comment-picture', + :title => comment.author_name + %> + <% else %> + <% url_image, status_class = comment.author_id ? + [comment.removed_user_image, 'icon-user-removed'] : + [str_gravatar_url_for( comment.email, :size => 50, :d=>404 ), 'icon-user-unknown'] %> + + <%= link_to( + image_tag(url_image, :onerror=>'gravatarCommentFailback(this)', + 'data-gravatar'=>str_gravatar_url_for(comment.email, :size=>50)) + + content_tag('span', comment.author_name, :class => 'comment-info') + + content_tag('span', comment.message, + :class => 'comment-user-status ' + status_class), + gravatar_profile_url(comment.email), + :target => '_blank', + :class => 'comment-picture', + :title => '%s %s' % [comment.author_name, comment.message] + )%> + <% end %> + + <% comment_balloon do %> + +
    +
    + <%= show_time(comment.created_at) %> +
    +

    <%= comment.title.blank? && ' ' || comment.title %>

    +
    +

    + <%= txt2html comment.body %> +

    +
    + +
    + <% if @comment && @comment.errors.any? && @comment.reply_of_id.to_i == comment.id %> + <%= error_messages_for :comment %> + + <% end %> + <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> + + <% if comment.spam? %> +   + <%= link_to_function(_('Mark as NOT SPAM'), 'remove_comment(this, %s); return false;' % url_for(:mark_comment_as_ham => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide') %> + <% else %> + <% if (logged_in? && (user == profile || user.has_permission?(:moderate_comments, profile))) %> +   + <%= link_to_function(_('Mark as SPAM'), 'remove_comment(this, %s, %s); return false;' % [url_for(:profile => profile.identifier, :controller => 'comment', :action => :mark_as_spam, :id => comment.id).to_json, _('Are you sure you want to mark this comment as SPAM?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide') %> + <% end %> + <% end %> + + <% if comment.author && comment.author == user %> +   + <%= expirable_comment_link comment, :edit, _('Edit'), url_for(:controller => :comment, :action => :edit, :id => comment.id),:class => 'colorbox' %> + <% end %> + + <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %> +   + <%= link_to_function(_('Remove'), 'remove_comment(this, %s, %s); return false ;' % [url_for(:controller => 'comment', :action => :destroy, :id => comment.id).to_json, _('Are you sure you want to remove this comment and all its replies?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide remove-children') %> + <% end %> + + <% unless comment.spam? %> +   + <%= link_to_function _('Reply'), + "var f = add_comment_reply_form(this, %s); f.find('comment_title, textarea').val(''); return false" % comment.id, + :class => 'comment-footer comment-footer-link comment-footer-hide', + :id => 'comment-reply-to-' + comment.id.to_s + %> + <% end %> +
    + + <% end %> + +
    + + <% unless comment.replies.blank? || comment.spam? %> + + <% end %> + +
    +
  • diff --git a/app/views/comment/_comment_form.rhtml b/app/views/comment/_comment_form.rhtml new file mode 100644 index 0000000..a9a8982 --- /dev/null +++ b/app/views/comment/_comment_form.rhtml @@ -0,0 +1,100 @@ +
    + +<% focus_on = logged_in? ? 'title' : 'name' %> + +<% edition_mode = (defined? edition_mode) ? edition_mode : false %> +
    + +<% if display_link %> +

    + <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %> +

    +<% end %> + +<% if !edition_mode && !pass_without_comment_captcha? %> + + + +<% end %> + + + +<% remote_form_for(:comment, comment, :url => {:profile => profile.identifier, :controller => 'comment', :action => (edition_mode ? 'update' : 'create'), :id => (edition_mode ? comment.id : @page.id)}, :html => { :class => 'comment_form' } ) do |f| %> + + <% if comment && comment.errors.any? %> + <%= error_messages_for :comment %> + + <% end %> + + <%= hidden_field_tag(:confirm, 'false') %> + + <%= required_fields_message %> + + <% unless logged_in? %> + + <%= required labelled_form_field(_('Name'), f.text_field(:name)) %> + <%= required labelled_form_field(_('e-mail'), f.text_field(:email)) %> +

    + <%= _('If you are a registered user, you can login and be automatically recognized.') %> +

    + + <% end %> + + <% if !edition_mode && !pass_without_comment_captcha? %> + <%= hidden_field_tag(:recaptcha_response_field, nil, :id => nil) %> + <%= hidden_field_tag(:recaptcha_challenge_field, nil, :id => nil) %> + <% end %> + + <%= labelled_form_field(_('Title'), f.text_field(:title)) %> + <%= required labelled_form_field(_('Enter your comment'), f.text_area(:body, :rows => 5)) %> + <%= f.hidden_field(:reply_of_id) %> + + <% button_bar do %> + <%= submit_button('add', _('Post comment'), :onclick => "if(check_captcha(this)) { save_comment(this) } else { check_captcha(this, save_comment)};return false;") %> + <%= button_to_function :cancel, _('Cancel'), "jQuery.colorbox.close();f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %> + <% end %> +<% end %> + + +
    +
    diff --git a/app/views/comment/edit.rhtml b/app/views/comment/edit.rhtml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/views/comment/edit.rhtml diff --git a/app/views/content_viewer/_comment.rhtml b/app/views/content_viewer/_comment.rhtml deleted file mode 100644 index 403de25..0000000 --- a/app/views/content_viewer/_comment.rhtml +++ /dev/null @@ -1,99 +0,0 @@ -
  • -
    - -
    - - <% if comment.author %> - <%= link_to image_tag(profile_icon(comment.author, :minor)) + - content_tag('span', comment.author_name, :class => 'comment-info'), - comment.author.url, - :class => 'comment-picture', - :title => comment.author_name - %> - <% else %> - <% url_image, status_class = comment.author_id ? - [comment.removed_user_image, 'icon-user-removed'] : - [str_gravatar_url_for( comment.email, :size => 50, :d=>404 ), 'icon-user-unknown'] %> - - <%= link_to( - image_tag(url_image, :onerror=>'gravatarCommentFailback(this)', - 'data-gravatar'=>str_gravatar_url_for(comment.email, :size=>50)) + - content_tag('span', comment.author_name, :class => 'comment-info') + - content_tag('span', comment.message, - :class => 'comment-user-status ' + status_class), - gravatar_profile_url(comment.email), - :target => '_blank', - :class => 'comment-picture', - :title => '%s %s' % [comment.author_name, comment.message] - )%> - <% end %> - - <% comment_balloon do %> - -
    -
    - <%= show_time(comment.created_at) %> -
    -

    <%= comment.title.blank? && ' ' || comment.title %>

    -
    -

    - <%= txt2html comment.body %> -

    -
    - -
    - <% if @comment && @comment.errors.any? && @comment.reply_of_id.to_i == comment.id %> - <%= error_messages_for :comment %> - - <% end %> - <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> - - <% if comment.spam? %> -   - <%= link_to_function(_('Mark as NOT SPAM'), 'remove_comment(this, %s); return false;' % url_for(:mark_comment_as_ham => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide') %> - <% else %> - <% if (logged_in? && (user == profile || user.has_permission?(:moderate_comments, profile))) %> -   - <%= link_to_function(_('Mark as SPAM'), 'remove_comment(this, %s, %s); return false;' % [url_for(:mark_comment_as_spam => comment.id).to_json, _('Are you sure you want to mark this comment as SPAM?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide') %> - <% end %> - <% end %> - - <% if comment.author && comment.author == user %> -   - <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %> - <% end %> - - <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %> -   - <%= link_to_function(_('Remove'), 'remove_comment(this, %s, %s); return false ;' % [url_for(:profile => params[:profile], :remove_comment => comment.id, :view => params[:view]).to_json, _('Are you sure you want to remove this comment and all its replies?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide remove-children') %> - <% end %> - - <% unless comment.spam? %> -   - <%= link_to_function _('Reply'), - "var f = add_comment_reply_form(this, %s); f.find('comment_title, textarea').val(''); return false" % comment.id, - :class => 'comment-footer comment-footer-link comment-footer-hide', - :id => 'comment-reply-to-' + comment.id.to_s - %> - <% end %> -
    - - <% end %> - -
    - - <% unless comment.replies.blank? || comment.spam? %> - - <% end %> - -
    -
  • diff --git a/app/views/content_viewer/_comment_form.rhtml b/app/views/content_viewer/_comment_form.rhtml deleted file mode 100644 index c19a877..0000000 --- a/app/views/content_viewer/_comment_form.rhtml +++ /dev/null @@ -1,97 +0,0 @@ - - -<% focus_on = logged_in? ? 'title' : 'name' %> - -<% if @comment && @comment.errors.any? && @comment.reply_of_id.blank? %> - <%= error_messages_for :comment %> - -<% end %> - -<% @form_div ||= 'closed' %> - -
    - -<% if display_link %> -

    - <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %> -

    -<% end %> - -<% unless pass_without_comment_captcha? %> - - - -<% end %> - -<% form_tag( url, { :class => 'comment_form' } ) do %> - <%= hidden_field_tag(:confirm, 'false') %> - - <%= required_fields_message %> - - <% unless logged_in? %> - - <%= required labelled_form_field(_('Name'), text_field(:comment, :name)) %> - <%= required labelled_form_field(_('e-mail'), text_field(:comment, :email)) %> -

    - <%= _('If you are a registered user, you can login and be automatically recognized.') %> -

    - - <% end %> - - <% unless pass_without_comment_captcha? %> - <%= hidden_field_tag(:recaptcha_response_field, nil, :id => nil) %> - <%= hidden_field_tag(:recaptcha_challenge_field, nil, :id => nil) %> - <% end %> - - <%= labelled_form_field(_('Title'), text_field(:comment, :title)) %> - <%= required labelled_form_field(_('Enter your comment'), text_area(:comment, :body, :rows => 5)) %> - - <% button_bar do %> - <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %> - <% if cancel_triggers_hide %> - <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %> - <% else %> - <%= button('cancel', _('Cancel'), {:action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path})%> - <% end %> - <% end %> -<% end %> - -
    diff --git a/app/views/content_viewer/edit_comment.html.erb b/app/views/content_viewer/edit_comment.html.erb deleted file mode 100644 index 0dbed2d..0000000 --- a/app/views/content_viewer/edit_comment.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -

    <%= _('Edit comment') %>

    - -<%= render :partial => 'comment_form', :locals => {:url => {:action => 'edit_comment', :profile => profile.identifier}, :display_link => false, :cancel_triggers_hide => false} %> diff --git a/app/views/content_viewer/view_page.rhtml b/app/views/content_viewer/view_page.rhtml index 15023a4..651d840 100644 --- a/app/views/content_viewer/view_page.rhtml +++ b/app/views/content_viewer/view_page.rhtml @@ -8,6 +8,12 @@ <%= render :partial => 'confirm_unfollow' %> + +
    diff --git a/app/views/tasks/_approve_comment_accept_details.rhtml b/app/views/tasks/_approve_comment_accept_details.rhtml new file mode 100644 index 0000000..74c7b9c --- /dev/null +++ b/app/views/tasks/_approve_comment_accept_details.rhtml @@ -0,0 +1,7 @@ +

    + <%= _('Title: ') %> + <%= task.comment.title %> +

    +

    + <%= task.comment.body %> +

    diff --git a/config/routes.rb b/config/routes.rb index 57f172d..27ff0e4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -76,6 +76,9 @@ ActionController::Routing::Routes.draw do |map| # profile search map.profile_search 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format}/ + # comments + map.comment 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format}/ + # public profile information map.profile 'profile/:profile/:action/:id', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format}/ @@ -122,7 +125,6 @@ ActionController::Routing::Routes.draw do |map| # cache stuff - hack map.cache 'public/:action/:id', :controller => 'public' - map.connect ':profile/edit_comment/:id/*page', :controller => 'content_viewer', :action => 'edit_comment', :profile => /#{Noosfero.identifier_format}/ # match requests for profiles that don't have a custom domain map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } diff --git a/plugins/require_auth_to_comment/public/jquery.livequery.min.js b/plugins/require_auth_to_comment/public/jquery.livequery.min.js new file mode 100644 index 0000000..5be66e7 --- /dev/null +++ b/plugins/require_auth_to_comment/public/jquery.livequery.min.js @@ -0,0 +1,9 @@ +/* Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net) + * Dual licensed under the MIT (MIT_LICENSE.txt) + * and GPL Version 2 (GPL_LICENSE.txt) licenses. + * + * Version: 1.1.1 + * Requires jQuery 1.3+ + * Docs: http://docs.jquery.com/Plugins/livequery + */ +(function(a){a.extend(a.fn,{livequery:function(e,d,c){var b=this,f;if(a.isFunction(e)){c=d,d=e,e=undefined}a.each(a.livequery.queries,function(g,h){if(b.selector==h.selector&&b.context==h.context&&e==h.type&&(!d||d.$lqguid==h.fn.$lqguid)&&(!c||c.$lqguid==h.fn2.$lqguid)){return(f=h)&&false}});f=f||new a.livequery(this.selector,this.context,e,d,c);f.stopped=false;f.run();return this},expire:function(e,d,c){var b=this;if(a.isFunction(e)){c=d,d=e,e=undefined}a.each(a.livequery.queries,function(f,g){if(b.selector==g.selector&&b.context==g.context&&(!e||e==g.type)&&(!d||d.$lqguid==g.fn.$lqguid)&&(!c||c.$lqguid==g.fn2.$lqguid)&&!this.stopped){a.livequery.stop(g.id)}});return this}});a.livequery=function(b,d,f,e,c){this.selector=b;this.context=d;this.type=f;this.fn=e;this.fn2=c;this.elements=[];this.stopped=false;this.id=a.livequery.queries.push(this)-1;e.$lqguid=e.$lqguid||a.livequery.guid++;if(c){c.$lqguid=c.$lqguid||a.livequery.guid++}return this};a.livequery.prototype={stop:function(){var b=this;if(this.type){this.elements.unbind(this.type,this.fn)}else{if(this.fn2){this.elements.each(function(c,d){b.fn2.apply(d)})}}this.elements=[];this.stopped=true},run:function(){if(this.stopped){return}var d=this;var e=this.elements,c=a(this.selector,this.context),b=c.not(e);this.elements=c;if(this.type){b.bind(this.type,this.fn);if(e.length>0){a.each(e,function(f,g){if(a.inArray(g,c)<0){a.event.remove(g,d.type,d.fn)}})}}else{b.each(function(){d.fn.apply(this)});if(this.fn2&&e.length>0){a.each(e,function(f,g){if(a.inArray(g,c)<0){d.fn2.apply(g)}})}}}};a.extend(a.livequery,{guid:0,queries:[],queue:[],running:false,timeout:null,checkQueue:function(){if(a.livequery.running&&a.livequery.queue.length){var b=a.livequery.queue.length;while(b--){a.livequery.queries[a.livequery.queue.shift()].run()}}},pause:function(){a.livequery.running=false},play:function(){a.livequery.running=true;a.livequery.run()},registerPlugin:function(){a.each(arguments,function(c,d){if(!a.fn[d]){return}var b=a.fn[d];a.fn[d]=function(){var e=b.apply(this,arguments);a.livequery.run();return e}})},run:function(b){if(b!=undefined){if(a.inArray(b,a.livequery.queue)<0){a.livequery.queue.push(b)}}else{a.each(a.livequery.queries,function(c){if(a.inArray(c,a.livequery.queue)<0){a.livequery.queue.push(c)}})}if(a.livequery.timeout){clearTimeout(a.livequery.timeout)}a.livequery.timeout=setTimeout(a.livequery.checkQueue,20)},stop:function(b){if(b!=undefined){a.livequery.queries[b].stop()}else{a.each(a.livequery.queries,function(c){a.livequery.queries[c].stop()})}}});a.livequery.registerPlugin("append","prepend","after","before","wrap","attr","removeAttr","addClass","removeClass","toggleClass","empty","remove","html");a(function(){a.livequery.play()})})(jQuery); \ No newline at end of file diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 9c271ee..b8b4d75 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -60,6 +60,27 @@ function updateUrlField(name_field, id) { } } + + +jQuery.fn.centerInForm = function () { + var $ = jQuery; + var form = $(this).parent('form'); + this.css("position", "absolute"); + this.css("top", (form.height() - this.height())/ 2 + form.scrollTop() + "px"); + this.css("left", (form.width() - this.width()) / 2 + form.scrollLeft() + "px"); + this.css("width", form.width() + "px"); + this.css("height", form.height() + "px"); + return this; +} + +jQuery.fn.center = function () { + var $ = jQuery; + this.css("position", "absolute"); + this.css("top", ($(window).height() - this.height())/ 2 + $(window).scrollTop() + "px"); + this.css("left", ($(window).width() - this.width()) / 2 + $(window).scrollLeft() + "px"); + return this; +} + function show_warning(field, message) { new Effect.Highlight(field, {duration:3}); $(message).show(); @@ -127,8 +148,9 @@ function loading_done(element_id) { $(element_id).removeClassName('small-loading-dark'); } function open_loading(message) { - jQuery('body').append("