Commit 5853fd51ddcd232938ada80c239451ee3dedffe0

Authored by Antonio Terceiro
1 parent f49dbb2e

UI to mark comments as ham

Additionally, I have made the "Mark as SPAM" and "Remove" links in the
page view comment listing work through AJAX, so that now it is much more
practical to remove comments or mark them as spam.

ActionItem2306
app/controllers/my_profile/spam_controller.rb 0 → 100644
... ... @@ -0,0 +1,40 @@
  1 +class SpamController < MyProfileController
  2 +
  3 + protect :moderate_comments, :profile
  4 +
  5 + def index
  6 + if request.post?
  7 + begin
  8 + # FIXME duplicated logic
  9 + #
  10 + # This logic more or less replicates what is already in
  11 + # ContentViewerController#view_page,
  12 + # ContentViewerController#remove_comment and
  13 + # ContentViewerController#mark_comment_as_spam
  14 + if params[:remove_comment]
  15 + profile.comments_received.find(params[:remove_comment]).destroy
  16 + end
  17 + if params[:mark_comment_as_ham]
  18 + profile.comments_received.find(params[:mark_comment_as_ham]).ham!
  19 + end
  20 + if request.xhr?
  21 + json_response(true)
  22 + else
  23 + redirect_to :action => :index
  24 + end
  25 + rescue
  26 + json_response(false)
  27 + end
  28 + return
  29 + end
  30 +
  31 + @spam = profile.comments_received.spam.paginate({:page => params[:page]})
  32 + end
  33 +
  34 + protected
  35 +
  36 + def json_response(status)
  37 + render :text => {'ok' => status }.to_json, :content_type => 'application/json'
  38 + end
  39 +
  40 +end
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -155,7 +155,7 @@ class ContentViewerController &lt; ApplicationController
155 155 @comment.destroy
156 156 session[:notice] = _('Comment succesfully deleted')
157 157 end
158   - redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view]
  158 + finish_comment_handling
159 159 end
160 160  
161 161 def mark_comment_as_spam
... ... @@ -164,7 +164,15 @@ class ContentViewerController &lt; ApplicationController
164 164 @comment.spam!
165 165 session[:notice] = _('Comment succesfully marked as SPAM')
166 166 end
167   - redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view]
  167 + finish_comment_handling
  168 + end
  169 +
  170 + def finish_comment_handling
  171 + if request.xhr?
  172 + render :text => {'ok' => true}.to_json, :content_type => 'application/json'
  173 + else
  174 + redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view]
  175 + end
168 176 end
169 177  
170 178 def per_page
... ...
app/models/profile.rb
... ... @@ -101,6 +101,8 @@ class Profile &lt; ActiveRecord::Base
101 101 has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC", :dependent => :destroy
102 102 belongs_to :template, :class_name => 'Profile', :foreign_key => 'template_id'
103 103  
  104 + has_many :comments_received, :class_name => 'Comment', :through => :articles, :source => :comments
  105 +
104 106 # FIXME ugly workaround
105 107 def self.human_attribute_name(attrib)
106 108 _(self.superclass.human_attribute_name(attrib))
... ...
app/views/content_viewer/_comment.rhtml
1 1 <li id="<%= comment.anchor %>" class="article-comment">
2 2 <div class="article-comment-inner">
3 3  
4   - <div class="comment-content comment-logged-<%= comment.author ? 'in' : 'out' %> <%= 'comment-from-owner' if ( comment.author && (@page.profile.name == comment.author.name) ) %>">
  4 + <div class="comment-content comment-logged-<%= comment.author ? 'in' : 'out' %> <%= 'comment-from-owner' if ( comment.author && (profile == comment.author) ) %>">
5 5  
6 6 <% if comment.author %>
7 7 <%= link_to image_tag(profile_icon(comment.author, :minor)) +
... ... @@ -53,21 +53,29 @@
53 53 <% end %>
54 54 <%= report_abuse(comment.author, :comment_link, comment) if comment.author %>
55 55  
56   - <% if (logged_in? && (user == @page.profile || user.has_permission?(:moderate_comments, @page.profile))) %>
57   - <%= link_to(_('Mark as SPAM'), { :mark_comment_as_spam => comment.id }, :method => :post, :confirm => _('Are you sure you want to mark this comment as SPAM?'), :class => 'comment-footer comment-footer-link comment-footer-hide') %>
  56 + <% if comment.spam? %>
58 57 &nbsp;
  58 + <%= 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') %>
  59 + <% else %>
  60 + <% if (logged_in? && (user == profile || user.has_permission?(:moderate_comments, profile))) %>
  61 + &nbsp;
  62 + <%= 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') %>
  63 + <% end %>
59 64 <% end %>
60 65  
61   - <% if logged_in? && (user == @page.profile || user == comment.author || user.has_permission?(:moderate_comments, @page.profile)) %>
62   - <%= link_to(_('Remove'), { :profile => params[:profile], :remove_comment => comment.id, :view => params[:view] }, :method => :post, :confirm => _('Are you sure you want to remove this comment and all its replies?'), :class => 'comment-footer comment-footer-link comment-footer-hide') %>
  66 + <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %>
63 67 &nbsp;
  68 + <%= 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') %>
64 69 <% end %>
65 70  
66   - <%= link_to_function _('Reply'),
  71 + <% unless comment.spam? %>
  72 + &nbsp;
  73 + <%= link_to_function _('Reply'),
67 74 "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id,
68 75 :class => 'comment-footer comment-footer-link comment-footer-hide',
69 76 :id => 'comment-reply-to-' + comment.id.to_s
70   - %>
  77 + %>
  78 + <% end %>
71 79 </div>
72 80  
73 81 <% end %>
... ...
app/views/profile_editor/index.rhtml
... ... @@ -66,6 +66,8 @@
66 66  
67 67 <%= control_panel_button(_('Manage my groups'), 'groups', :controller => 'memberships') if profile.person? %>
68 68  
  69 + <%= control_panel_button(_('Manage SPAM'), 'manage-spam', :controller => 'spam', :action => 'index') %>
  70 +
69 71 <% @plugins.dispatch(:control_panel_buttons).each do |button| %>
70 72 <%= control_panel_button(button[:title], button[:icon], button[:url]) %>
71 73 <% end %>
... ...
app/views/spam/index.rhtml 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +<h1><%= _('Manage SPAM') %></h1>
  2 +
  3 +<% button_bar do %>
  4 + <%= button :back, _('Back to control panel'), :controller => :profile_editor %>
  5 +<% end %>
  6 +
  7 +<%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %>
  8 +<div id='article'>
  9 + <div class="comments" id="comments_list">
  10 + <ul class="article-comments-list">
  11 + <%= render :partial => 'content_viewer/comment', :collection => @spam %>
  12 + </ul>
  13 + </div>
  14 +</div>
  15 +
  16 +<%= pagination_links @spam %>
  17 +
  18 +<% button_bar do %>
  19 + <%= button :back, _('Back to control panel'), :controller => :profile_editor %>
  20 +<% end %>
... ...
public/images/control-panel/mail-mark-junk.png 0 → 100644

3.94 KB

public/images/control-panel/mail-mark-junk.svg 0 → 100644
... ... @@ -0,0 +1,504 @@
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
  3 +<svg
  4 + xmlns:dc="http://purl.org/dc/elements/1.1/"
  5 + xmlns:cc="http://creativecommons.org/ns#"
  6 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  7 + xmlns:svg="http://www.w3.org/2000/svg"
  8 + xmlns="http://www.w3.org/2000/svg"
  9 + xmlns:xlink="http://www.w3.org/1999/xlink"
  10 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  11 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  12 + inkscape:export-ydpi="90.000000"
  13 + inkscape:export-xdpi="90.000000"
  14 + inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
  15 + width="48px"
  16 + height="48px"
  17 + id="svg11300"
  18 + sodipodi:version="0.32"
  19 + inkscape:version="0.46"
  20 + sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
  21 + sodipodi:docname="mail-mark-junk.svg"
  22 + inkscape:output_extension="org.inkscape.output.svg.inkscape">
  23 + <defs
  24 + id="defs3">
  25 + <inkscape:perspective
  26 + sodipodi:type="inkscape:persp3d"
  27 + inkscape:vp_x="0 : 24 : 1"
  28 + inkscape:vp_y="0 : 1000 : 0"
  29 + inkscape:vp_z="48 : 24 : 1"
  30 + inkscape:persp3d-origin="24 : 16 : 1"
  31 + id="perspective72" />
  32 + <linearGradient
  33 + inkscape:collect="always"
  34 + id="linearGradient5166">
  35 + <stop
  36 + style="stop-color:white;stop-opacity:1;"
  37 + offset="0"
  38 + id="stop5168" />
  39 + <stop
  40 + style="stop-color:white;stop-opacity:0;"
  41 + offset="1"
  42 + id="stop5170" />
  43 + </linearGradient>
  44 + <linearGradient
  45 + id="linearGradient5196">
  46 + <stop
  47 + style="stop-color:#dfe2dc;stop-opacity:1;"
  48 + offset="0"
  49 + id="stop5198" />
  50 + <stop
  51 + style="stop-color:#86917a;stop-opacity:1;"
  52 + offset="1"
  53 + id="stop5200" />
  54 + </linearGradient>
  55 + <linearGradient
  56 + id="linearGradient5188">
  57 + <stop
  58 + style="stop-color:white;stop-opacity:1;"
  59 + offset="0"
  60 + id="stop5190" />
  61 + <stop
  62 + style="stop-color:#aeaea3;stop-opacity:1;"
  63 + offset="1"
  64 + id="stop5192" />
  65 + </linearGradient>
  66 + <linearGradient
  67 + inkscape:collect="always"
  68 + id="linearGradient5176">
  69 + <stop
  70 + style="stop-color:black;stop-opacity:1;"
  71 + offset="0"
  72 + id="stop5178" />
  73 + <stop
  74 + style="stop-color:black;stop-opacity:0;"
  75 + offset="1"
  76 + id="stop5180" />
  77 + </linearGradient>
  78 + <linearGradient
  79 + id="linearGradient5162">
  80 + <stop
  81 + style="stop-color:#babdb6;stop-opacity:1;"
  82 + offset="0"
  83 + id="stop5164" />
  84 + <stop
  85 + style="stop-color:white;stop-opacity:1;"
  86 + offset="1"
  87 + id="stop5166" />
  88 + </linearGradient>
  89 + <linearGradient
  90 + inkscape:collect="always"
  91 + id="linearGradient5150">
  92 + <stop
  93 + style="stop-color:black;stop-opacity:1;"
  94 + offset="0"
  95 + id="stop5152" />
  96 + <stop
  97 + style="stop-color:black;stop-opacity:0;"
  98 + offset="1"
  99 + id="stop5154" />
  100 + </linearGradient>
  101 + <linearGradient
  102 + id="linearGradient11520">
  103 + <stop
  104 + id="stop11522"
  105 + offset="0.0000000"
  106 + style="stop-color:#ffffff;stop-opacity:1.0000000;" />
  107 + <stop
  108 + id="stop11524"
  109 + offset="1.0000000"
  110 + style="stop-color:#dcdcdc;stop-opacity:1.0000000;" />
  111 + </linearGradient>
  112 + <linearGradient
  113 + id="linearGradient11508"
  114 + inkscape:collect="always">
  115 + <stop
  116 + id="stop11510"
  117 + offset="0"
  118 + style="stop-color:#000000;stop-opacity:1;" />
  119 + <stop
  120 + id="stop11512"
  121 + offset="1"
  122 + style="stop-color:#000000;stop-opacity:0;" />
  123 + </linearGradient>
  124 + <linearGradient
  125 + id="linearGradient11494"
  126 + inkscape:collect="always">
  127 + <stop
  128 + id="stop11496"
  129 + offset="0"
  130 + style="stop-color:#ef2929;stop-opacity:1;" />
  131 + <stop
  132 + id="stop11498"
  133 + offset="1"
  134 + style="stop-color:#ef2929;stop-opacity:0;" />
  135 + </linearGradient>
  136 + <linearGradient
  137 + id="linearGradient11415">
  138 + <stop
  139 + id="stop11417"
  140 + offset="0.0000000"
  141 + style="stop-color:#204a87;stop-opacity:0.0000000;" />
  142 + <stop
  143 + style="stop-color:#204a87;stop-opacity:1.0000000;"
  144 + offset="0.50000000"
  145 + id="stop11423" />
  146 + <stop
  147 + id="stop11419"
  148 + offset="1"
  149 + style="stop-color:#204a87;stop-opacity:0;" />
  150 + </linearGradient>
  151 + <linearGradient
  152 + id="linearGradient11399"
  153 + inkscape:collect="always">
  154 + <stop
  155 + id="stop11401"
  156 + offset="0"
  157 + style="stop-color:#000000;stop-opacity:1;" />
  158 + <stop
  159 + id="stop11403"
  160 + offset="1"
  161 + style="stop-color:#000000;stop-opacity:0;" />
  162 + </linearGradient>
  163 + <linearGradient
  164 + gradientTransform="translate(-60.28571,-0.285714)"
  165 + y2="34.462429"
  166 + x2="43.615788"
  167 + y1="3.7744560"
  168 + x1="15.828360"
  169 + gradientUnits="userSpaceOnUse"
  170 + id="linearGradient11425"
  171 + xlink:href="#linearGradient11415"
  172 + inkscape:collect="always" />
  173 + <linearGradient
  174 + gradientTransform="translate(-60.57143,0.000000)"
  175 + y2="39.033859"
  176 + x2="35.679932"
  177 + y1="9.3458843"
  178 + x1="9.6957054"
  179 + gradientUnits="userSpaceOnUse"
  180 + id="linearGradient11427"
  181 + xlink:href="#linearGradient11415"
  182 + inkscape:collect="always" />
  183 + <linearGradient
  184 + y2="33.462429"
  185 + x2="26.758644"
  186 + y1="19.774456"
  187 + x1="13.267134"
  188 + gradientTransform="translate(-60.85714,0.428571)"
  189 + gradientUnits="userSpaceOnUse"
  190 + id="linearGradient11439"
  191 + xlink:href="#linearGradient11415"
  192 + inkscape:collect="always" />
  193 + <radialGradient
  194 + r="8.5000000"
  195 + fy="39.142857"
  196 + fx="12.071428"
  197 + cy="39.142857"
  198 + cx="12.071428"
  199 + gradientTransform="matrix(1.000000,0.000000,0.000000,0.487395,0.000000,20.06483)"
  200 + gradientUnits="userSpaceOnUse"
  201 + id="radialGradient11441"
  202 + xlink:href="#linearGradient11399"
  203 + inkscape:collect="always" />
  204 + <radialGradient
  205 + gradientTransform="matrix(1.243453,2.106784e-16,-2.106784e-16,1.243453,-6.713754,-3.742847)"
  206 + gradientUnits="userSpaceOnUse"
  207 + r="3.8335034"
  208 + fy="15.048258"
  209 + fx="27.577173"
  210 + cy="15.048258"
  211 + cx="27.577173"
  212 + id="radialGradient11500"
  213 + xlink:href="#linearGradient11494"
  214 + inkscape:collect="always" />
  215 + <radialGradient
  216 + r="3.8335034"
  217 + fy="16.049133"
  218 + fx="27.577173"
  219 + cy="16.049133"
  220 + cx="27.577173"
  221 + gradientTransform="matrix(1.243453,2.106784e-16,-2.106784e-16,1.243453,-6.713754,-3.742847)"
  222 + gradientUnits="userSpaceOnUse"
  223 + id="radialGradient11504"
  224 + xlink:href="#linearGradient11494"
  225 + inkscape:collect="always" />
  226 + <radialGradient
  227 + gradientUnits="userSpaceOnUse"
  228 + gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,2.166583e-14,29.48178)"
  229 + r="6.5659914"
  230 + fy="44.565483"
  231 + fx="30.203562"
  232 + cy="44.565483"
  233 + cx="30.203562"
  234 + id="radialGradient11514"
  235 + xlink:href="#linearGradient11508"
  236 + inkscape:collect="always" />
  237 + <radialGradient
  238 + gradientTransform="matrix(1.995058,-1.651527e-32,0.000000,1.995058,-24.32488,-35.70087)"
  239 + gradientUnits="userSpaceOnUse"
  240 + r="20.530962"
  241 + fy="35.878170"
  242 + fx="24.445690"
  243 + cy="35.878170"
  244 + cx="24.445690"
  245 + id="radialGradient11526"
  246 + xlink:href="#linearGradient11520"
  247 + inkscape:collect="always" />
  248 + <radialGradient
  249 + r="6.5659914"
  250 + fy="44.565483"
  251 + fx="30.203562"
  252 + cy="44.565483"
  253 + cx="30.203562"
  254 + gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,3.185827e-15,29.48178)"
  255 + gradientUnits="userSpaceOnUse"
  256 + id="radialGradient11532"
  257 + xlink:href="#linearGradient11508"
  258 + inkscape:collect="always" />
  259 + <radialGradient
  260 + inkscape:collect="always"
  261 + xlink:href="#linearGradient11508"
  262 + id="radialGradient1348"
  263 + gradientUnits="userSpaceOnUse"
  264 + gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,-1.353344e-14,29.48178)"
  265 + cx="30.203562"
  266 + cy="44.565483"
  267 + fx="30.203562"
  268 + fy="44.565483"
  269 + r="6.5659914" />
  270 + <radialGradient
  271 + inkscape:collect="always"
  272 + xlink:href="#linearGradient11520"
  273 + id="radialGradient1350"
  274 + gradientUnits="userSpaceOnUse"
  275 + gradientTransform="matrix(1.995058,-1.651527e-32,0.000000,1.995058,-24.32488,-35.70087)"
  276 + cx="24.445690"
  277 + cy="35.878170"
  278 + fx="24.445690"
  279 + fy="35.878170"
  280 + r="20.530962" />
  281 + <radialGradient
  282 + inkscape:collect="always"
  283 + xlink:href="#linearGradient11494"
  284 + id="radialGradient1352"
  285 + gradientUnits="userSpaceOnUse"
  286 + gradientTransform="matrix(1.243453,2.106784e-16,-2.106784e-16,1.243453,-6.713754,-3.742847)"
  287 + cx="27.577173"
  288 + cy="16.049133"
  289 + fx="27.577173"
  290 + fy="16.049133"
  291 + r="3.8335034" />
  292 + <radialGradient
  293 + inkscape:collect="always"
  294 + xlink:href="#linearGradient11494"
  295 + id="radialGradient1354"
  296 + gradientUnits="userSpaceOnUse"
  297 + gradientTransform="matrix(1.243453,2.106784e-16,-2.106784e-16,1.243453,-6.713754,-3.742847)"
  298 + cx="27.577173"
  299 + cy="15.048258"
  300 + fx="27.577173"
  301 + fy="15.048258"
  302 + r="3.8335034" />
  303 + <radialGradient
  304 + inkscape:collect="always"
  305 + xlink:href="#linearGradient11508"
  306 + id="radialGradient1356"
  307 + gradientUnits="userSpaceOnUse"
  308 + gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,2.220359e-14,29.48178)"
  309 + cx="30.203562"
  310 + cy="44.565483"
  311 + fx="30.203562"
  312 + fy="44.565483"
  313 + r="6.5659914" />
  314 + <radialGradient
  315 + inkscape:collect="always"
  316 + xlink:href="#linearGradient11520"
  317 + id="radialGradient1366"
  318 + gradientUnits="userSpaceOnUse"
  319 + gradientTransform="matrix(2.049266,-1.696401e-32,0.000000,2.049266,-25.65002,-37.31089)"
  320 + cx="24.445690"
  321 + cy="35.878170"
  322 + fx="24.445690"
  323 + fy="35.878170"
  324 + r="20.530962" />
  325 + <radialGradient
  326 + inkscape:collect="always"
  327 + xlink:href="#linearGradient5150"
  328 + id="radialGradient5156"
  329 + cx="24.837126"
  330 + cy="40.663769"
  331 + fx="24.837126"
  332 + fy="40.663769"
  333 + r="21.478369"
  334 + gradientTransform="matrix(1,0,0,0.325103,2.211772e-16,27.44386)"
  335 + gradientUnits="userSpaceOnUse" />
  336 + <linearGradient
  337 + inkscape:collect="always"
  338 + xlink:href="#linearGradient5162"
  339 + id="linearGradient5168"
  340 + x1="24.365993"
  341 + y1="20.246058"
  342 + x2="32.600704"
  343 + y2="28.554564"
  344 + gradientUnits="userSpaceOnUse" />
  345 + <linearGradient
  346 + inkscape:collect="always"
  347 + xlink:href="#linearGradient5162"
  348 + id="linearGradient5170"
  349 + gradientUnits="userSpaceOnUse"
  350 + x1="22.008699"
  351 + y1="36.509514"
  352 + x2="23.585091"
  353 + y2="14.412428" />
  354 + <linearGradient
  355 + inkscape:collect="always"
  356 + xlink:href="#linearGradient5176"
  357 + id="linearGradient5182"
  358 + x1="25.632622"
  359 + y1="10.611729"
  360 + x2="38.714096"
  361 + y2="18.389904"
  362 + gradientUnits="userSpaceOnUse" />
  363 + <radialGradient
  364 + inkscape:collect="always"
  365 + xlink:href="#linearGradient5188"
  366 + id="radialGradient5361"
  367 + gradientUnits="userSpaceOnUse"
  368 + gradientTransform="matrix(2.135667,1.912751e-16,-1.890308e-16,2.110607,-26.90176,-15.66914)"
  369 + cx="23.688078"
  370 + cy="14.210698"
  371 + fx="23.688078"
  372 + fy="14.210698"
  373 + r="22.597087" />
  374 + <radialGradient
  375 + inkscape:collect="always"
  376 + xlink:href="#linearGradient5196"
  377 + id="radialGradient5363"
  378 + gradientUnits="userSpaceOnUse"
  379 + gradientTransform="matrix(1.790269,1.339577e-16,-1.323859e-16,1.769263,-15.81394,-11.94997)"
  380 + cx="20.089987"
  381 + cy="10.853651"
  382 + fx="20.089987"
  383 + fy="10.853651"
  384 + r="22.597087" />
  385 + <linearGradient
  386 + inkscape:collect="always"
  387 + xlink:href="#linearGradient5166"
  388 + id="linearGradient5172"
  389 + x1="19.450956"
  390 + y1="14.463861"
  391 + x2="23.71875"
  392 + y2="48.404987"
  393 + gradientUnits="userSpaceOnUse" />
  394 + </defs>
  395 + <sodipodi:namedview
  396 + stroke="#ef2929"
  397 + fill="#eeeeec"
  398 + id="base"
  399 + pagecolor="#ffffff"
  400 + bordercolor="#666666"
  401 + borderopacity="0.25490196"
  402 + inkscape:pageopacity="0.0"
  403 + inkscape:pageshadow="2"
  404 + inkscape:zoom="1"
  405 + inkscape:cx="-91.650069"
  406 + inkscape:cy="-6.8095951"
  407 + inkscape:current-layer="layer1"
  408 + showgrid="false"
  409 + inkscape:grid-bbox="true"
  410 + inkscape:document-units="px"
  411 + inkscape:showpageshadow="false"
  412 + inkscape:window-width="872"
  413 + inkscape:window-height="688"
  414 + inkscape:window-x="441"
  415 + inkscape:window-y="160" />
  416 + <metadata
  417 + id="metadata4">
  418 + <rdf:RDF>
  419 + <cc:Work
  420 + rdf:about="">
  421 + <dc:format>image/svg+xml</dc:format>
  422 + <dc:type
  423 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  424 + <dc:creator>
  425 + <cc:Agent>
  426 + <dc:title>Jakub Steiner</dc:title>
  427 + </cc:Agent>
  428 + </dc:creator>
  429 + <dc:source>http://jimmac.musichall.cz</dc:source>
  430 + <cc:license
  431 + rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
  432 + <dc:title>Mark mail as Junk</dc:title>
  433 + <dc:subject>
  434 + <rdf:Bag>
  435 + <rdf:li>mail</rdf:li>
  436 + <rdf:li>spam</rdf:li>
  437 + <rdf:li>junk</rdf:li>
  438 + </rdf:Bag>
  439 + </dc:subject>
  440 + </cc:Work>
  441 + <cc:License
  442 + rdf:about="http://creativecommons.org/licenses/publicdomain/">
  443 + <cc:permits
  444 + rdf:resource="http://creativecommons.org/ns#Reproduction" />
  445 + <cc:permits
  446 + rdf:resource="http://creativecommons.org/ns#Distribution" />
  447 + <cc:permits
  448 + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
  449 + </cc:License>
  450 + </rdf:RDF>
  451 + </metadata>
  452 + <g
  453 + id="layer1"
  454 + inkscape:label="Layer 1"
  455 + inkscape:groupmode="layer">
  456 + <path
  457 + sodipodi:type="arc"
  458 + style="opacity:0.3258427;color:black;fill:url(#radialGradient5156);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  459 + id="path4275"
  460 + sodipodi:cx="24.837126"
  461 + sodipodi:cy="40.663769"
  462 + sodipodi:rx="21.478369"
  463 + sodipodi:ry="6.9826794"
  464 + d="M 46.315495 40.663769 A 21.478369 6.9826794 0 1 1 3.358757,40.663769 A 21.478369 6.9826794 0 1 1 46.315495 40.663769 z"
  465 + transform="matrix(1.106996,0,0,1.106996,-3.364576,-5.411516)" />
  466 + <path
  467 + style="opacity:1;color:black;fill:url(#radialGradient5361);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient5363);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  468 + d="M 9.0156115,37.570175 L 7.2478445,40.398602 L 10.960155,41.989592 L 13.611806,39.868272 L 25.455844,40.752155 L 29.168155,45.701903 L 32.526912,40.221825 L 36.769553,42.519922 L 42.426407,41.812816 L 41.012193,38.807612 L 44.901281,34.918524 L 39.421203,28.73134 L 44.724504,29.438447 L 47.022601,27.317127 L 44.017397,27.847457 L 40.835417,22.367379 L 36.239223,21.306719 L 39.951533,20.069282 L 40.12831,16.887302 L 32.880465,10.523341 L 30.228815,2.0380592 L 18.208,5.5735931 L 15.202796,12.644661 L 14.142136,10.346564 L 11.136932,10.523341 L 11.136932,13.351768 L 7.6013979,9.2859037 L 2.8284271,14.412428 L 2.8284271,21.660272 L 11.136932,28.908117 L 5.833631,31.913321 L 6.0104076,34.918524 L 9.0156115,37.570175 z "
  469 + id="path4273" />
  470 + <path
  471 + style="opacity:0.76966292;color:black;fill:url(#linearGradient5170);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  472 + d="M 19.445437,22.720933 L 18.561553,29.26167 L 20.682873,32.620427 L 16.086679,34.034641 L 13.435029,39.337942 L 25.455844,40.221825 L 28.284271,44.287689 L 30.582368,38.100505 L 26.162951,35.272078 L 19.445437,37.216622 L 22.097087,33.681088 L 20.682873,27.493903 L 19.445437,22.720933 z "
  473 + id="path5158" />
  474 + <path
  475 + style="opacity:0.61797753;color:black;fill:url(#linearGradient5168);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  476 + d="M 20.506097,23.781593 L 24.925514,30.675884 L 32.173359,25.726136 L 36.592776,28.20101 L 40.12831,25.195806 L 43.31029,28.024233 L 40.305087,23.074486 L 33.410795,21.483496 L 24.748737,17.240855 C 24.748737,17.240855 12.374369,20.953166 13.081475,20.953166 C 13.788582,20.953166 23.334524,21.129942 23.334524,21.129942 L 24.925514,18.831845 L 29.168155,20.776389 L 20.506097,23.781593 z "
  477 + id="path5160" />
  478 + <path
  479 + style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  480 + d="M 29.521708,3.4522727 L 19.091883,6.9878066 L 17.67767,10.876894 L 23.688077,15.119535 L 29.344931,9.6394571 L 29.521708,3.4522727 z "
  481 + id="path5172" />
  482 + <path
  483 + style="opacity:0.13483146;color:black;fill:url(#linearGradient5182);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  484 + d="M 29.698485,3.8058261 L 31.996582,11.230447 L 36.239223,14.942758 L 27.577165,12.998214 C 27.577165,12.998214 25.102291,15.826641 26.162951,15.826641 C 27.223611,15.826641 38.714096,17.240855 38.714096,17.240855 L 38.53732,19.538952 L 22.273864,16.533748 L 29.344931,9.9930105 L 29.698485,3.8058261 z "
  485 + id="path5174" />
  486 + <path
  487 + style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  488 + d="M 7.4246212,14.235651 L 6.5407377,23.074486 L 8.4852814,17.064078 L 13.611806,18.655069 L 14.849242,16.003418 L 21.036427,16.887302 L 22.45064,15.649865 L 13.435029,15.296311 L 12.551145,17.771185 L 8.6620581,15.826641 L 7.4246212,14.235651 z "
  489 + id="path5184" />
  490 + <path
  491 + style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  492 + d="M 22.45064,27.317127 L 25.455844,30.852661 L 32.350135,26.256466 L 36.592776,28.554563 L 43.487067,35.095301 L 35.885669,29.26167 L 32.173359,28.20101 L 24.925514,33.150758 L 22.45064,27.317127 z "
  493 + id="path5186" />
  494 + <path
  495 + sodipodi:type="inkscape:offset"
  496 + inkscape:radius="-0.83777463"
  497 + inkscape:original="M 30.21875 2.03125 L 18.21875 5.5625 L 15.1875 12.65625 L 14.15625 10.34375 L 11.125 10.53125 L 11.125 13.34375 L 7.59375 9.28125 L 2.84375 14.40625 L 2.84375 21.65625 L 11.125 28.90625 L 5.84375 31.90625 L 6 34.90625 L 9 37.5625 L 7.25 40.40625 L 10.96875 42 L 13.625 39.875 L 25.46875 40.75 L 29.15625 45.6875 L 32.53125 40.21875 L 36.78125 42.53125 L 42.4375 41.8125 L 41 38.8125 L 44.90625 34.90625 L 39.40625 28.71875 L 44.71875 29.4375 L 47.03125 27.3125 L 44.03125 27.84375 L 40.84375 22.375 L 36.25 21.3125 L 39.9375 20.0625 L 40.125 16.875 L 32.875 10.53125 L 30.21875 2.03125 z "
  498 + xlink:href="#path4273"
  499 + style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5172);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
  500 + id="path5359"
  501 + inkscape:href="#path4273"
  502 + d="M 29.65625,3.09375 L 18.84375,6.25 L 15.96875,13 C 15.834262,13.30255 15.53422,13.497528 15.203125,13.497528 C 14.87203,13.497528 14.571988,13.30255 14.4375,13 L 13.65625,11.21875 L 11.96875,11.3125 L 11.96875,13.34375 C 11.973462,13.69495 11.758625,14.011813 11.430625,14.13743 C 11.102625,14.263047 10.731089,14.170753 10.5,13.90625 L 7.5625,10.53125 L 3.6875,14.71875 L 3.6875,21.28125 L 11.6875,28.28125 C 11.883657,28.462891 11.981357,28.727236 11.950479,28.992788 C 11.919601,29.25834 11.763852,29.493214 11.53125,29.625 L 6.71875,32.375 L 6.8125,34.5 L 9.5625,36.9375 C 9.8645501,37.207345 9.9303261,37.654622 9.71875,38 L 8.46875,40 L 10.84375,41.03125 L 13.09375,39.21875 C 13.260233,39.0823 13.472846,39.015159 13.6875,39.03125 L 25.53125,39.90625 C 25.769158,39.930835 25.985219,40.055923 26.125,40.25 L 29.09375,44.21875 L 31.8125,39.78125 C 32.041236,39.389926 32.539705,39.251463 32.9375,39.46875 L 36.96875,41.65625 L 41.1875,41.125 L 40.25,39.1875 C 40.087762,38.864671 40.150741,38.474201 40.40625,38.21875 L 43.75,34.875 L 38.78125,29.28125 C 38.529387,29.019826 38.474521,28.625949 38.645349,28.305645 C 38.816178,27.985341 39.17384,27.811478 39.53125,27.875 L 43.40625,28.40625 C 43.369413,28.35773 43.337977,28.305337 43.3125,28.25 L 40.3125,23.09375 L 36.0625,22.125 C 35.709163,22.034799 35.454745,21.726417 35.433331,21.362378 C 35.411917,20.998338 35.628425,20.662254 35.96875,20.53125 L 39.125,19.46875 L 39.25,17.21875 L 32.3125,11.15625 C 32.19648,11.05643 32.110019,10.926737 32.0625,10.78125 L 29.65625,3.09375 z " />
  503 + </g>
  504 +</svg>
... ...
public/javascripts/application.js
... ... @@ -674,6 +674,21 @@ function add_comment_reply_form(button, comment_id) {
674 674 return f;
675 675 }
676 676  
  677 +function remove_comment(button, url, msg) {
  678 + var $ = jQuery;
  679 + var $button = $(button);
  680 + if (msg && !confirm(msg)) {
  681 + $button.removeClass('comment-button-loading');
  682 + return;
  683 + }
  684 + $button.addClass('comment-button-loading');
  685 + $.post(url, function(data) {
  686 + if (data.ok) {
  687 + $button.closest('.article-comment').slideUp();
  688 + }
  689 + });
  690 +}
  691 +
677 692 function original_image_dimensions(src) {
678 693 var img = new Image();
679 694 img.src = src;
... ...
public/stylesheets/application.css
... ... @@ -1262,6 +1262,11 @@ a.comment-picture {
1262 1262 }
1263 1263 /* * * Comment Box * * */
1264 1264  
  1265 +.comment-button-loading {
  1266 + padding-left: 20px;
  1267 + background: transparent url(../images/loading-small.gif) no-repeat left center;
  1268 +}
  1269 +
1265 1270 .post_comment_box {
1266 1271 text-align: center;
1267 1272 padding: 0px 15px 5px 15px;
... ... @@ -3840,6 +3845,9 @@ h1#agenda-title {
3840 3845 .controller-profile_editor .msie6 a.control-panel-edit-location {
3841 3846 background-image: url(../images/control-panel/set-geolocation.gif)
3842 3847 }
  3848 +.controller-profile_editor a.control-panel-manage-spam {
  3849 + background-image: url(../images/control-panel/mail-mark-junk.png)
  3850 +}
3843 3851 /* ==> public/stylesheets/controller_profile_members.css <== */
3844 3852 .controller-profile_members .no-boxes {
3845 3853 margin: 30px
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -92,7 +92,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
92 92  
93 93 login_as 'testuser'
94 94 get :view_page, :profile => 'testuser', :page => [ 'test' ]
95   - assert_tag :tag => 'a', :attributes => { :href => '/testuser/test?remove_comment=' + comment.id.to_s }
  95 + assert_tag :tag => 'a', :attributes => { :onclick => %r(/testuser/test\?remove_comment=#{comment.id}.quot) }
96 96 end
97 97  
98 98 should 'display remove comment button with param view when image' do
... ... @@ -106,8 +106,9 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
106 106  
107 107 login_as 'testuser'
108 108 get :view_page, :profile => 'testuser', :page => [ image.filename ], :view => true
109   - assert_tag :tag => 'a', :attributes => { :href => "/testuser/#{image.filename}?remove_comment=" + comment.id.to_s + '&amp;view=true'}
110   - end
  109 + assert_tag :tag => 'a', :attributes => { :onclick => %r(/testuser/#{image.filename}\?remove_comment=#{comment.id}.*amp;view=true.quot) }
  110 +end
  111 +
111 112  
112 113 should 'not add unneeded params for remove comment button' do
113 114 profile = create_user('testuser').person
... ... @@ -117,8 +118,8 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
117 118 comment.save!
118 119  
119 120 login_as 'testuser'
120   - get :view_page, :profile => 'testuser', :page => [ 'test' ], :random_param => 'bli' # <<<<<<<<<<<<<<<
121   - assert_tag :tag => 'a', :attributes => { :href => '/testuser/test?remove_comment=' + comment.id.to_s }
  121 + get :view_page, :profile => 'testuser', :page => [ 'test' ], :random_param => 'bli'
  122 + assert_tag :tag => 'a', :attributes => { :onclick => %r(/testuser/test\?remove_comment=#{comment.id.to_s}.quot) }
122 123 end
123 124  
124 125 should 'be able to remove comment' do
... ...
test/functional/spam_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,35 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class SpamControllerTest < ActionController::TestCase
  4 +
  5 + def setup
  6 + @profile = create_user.person
  7 + @article = fast_create(TextileArticle, :profile_id => @profile.id)
  8 + @spam = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com')
  9 +
  10 + login_as @profile.identifier
  11 + end
  12 +
  13 + test "should only list spammy comments" do
  14 + ham = fast_create(Comment, :source_id => @article.id)
  15 +
  16 + get :index, :profile => @profile.identifier
  17 +
  18 + assert_equivalent [@spam], assigns(:spam)
  19 + end
  20 +
  21 + test "should mark comments as ham" do
  22 + post :index, :profile => @profile.identifier, :mark_comment_as_ham => @spam.id
  23 +
  24 + @spam.reload
  25 + assert @spam.ham?
  26 + end
  27 +
  28 + test "should remove comments" do
  29 + post :index, :profile => @profile.identifier, :remove_comment => @spam.id
  30 +
  31 + assert !Comment.exists?(@spam.id)
  32 + end
  33 +
  34 +
  35 +end
... ...