comment deleting and undeleting

This commit is contained in:
joshua stein 2012-07-12 13:30:20 -05:00
parent 7dd4b99ac2
commit 3640e1e7a3
10 changed files with 197 additions and 41 deletions

View file

@ -233,6 +233,26 @@ $(document).ready(function() {
li.load("/comments/" + $(li).attr("data-shortid") + "/edit",
{ "edit": 1 });
});
$("a.comment_deletor").live("click", function() {
if (confirm("Are you sure you want to delete this comment?")) {
var li = $(this).parents("li.comment").first();
$.post("/comments/" + $(li).attr("data-shortid") + "/delete",
function(d) {
$(li).replaceWith(d);
});
}
});
$("a.comment_undeletor").live("click", function() {
if (confirm("Are you sure you want to undelete this comment?")) {
var li = $(this).parents("li.comment").first();
$.post("/comments/" + $(li).attr("data-shortid") + "/undelete",
function(d) {
$(li).replaceWith(d);
});
}
});
$("#story_tags_a").select2({
formatSelection: function(what) {

View file

@ -68,6 +68,11 @@ span.fakea {
color: gray;
}
span.na {
color: gray;
font-style: italic;
}
div.shorten_first_p p:first-child {
margin-top: 0.5em;
}

View file

@ -66,6 +66,32 @@ class CommentsController < ApplicationController
:comment => comment }
end
def delete
if !((comment = Comment.find_by_short_id(params[:comment_id])) &&
comment.is_editable_by_user?(@user))
return render :text => "can't find comment", :status => 400
end
comment.delete_for_user(@user)
render :partial => "comment", :layout => false,
:content_type => "text/html", :locals => { :story => comment.story,
:comment => comment }
end
def undelete
if !((comment = Comment.find_by_short_id(params[:comment_id])) &&
comment.is_undeletable_by_user?(@user))
return render :text => "can't find comment", :status => 400
end
comment.undelete_for_user(@user)
render :partial => "comment", :layout => false,
:content_type => "text/html", :locals => { :story => comment.story,
:comment => comment }
end
def update
if !((comment = Comment.find_by_short_id(params[:comment_id])) &&
comment.is_editable_by_user?(@user))

View file

@ -116,7 +116,7 @@ class StoriesController < ApplicationController
@short_url = @story.short_id_url
@comments = Comment.ordered_for_story_or_thread_for_user(@story.id, nil,
@user ? @user.id : nil)
@user ? @user : nil)
@comment = Comment.new
if @user
@ -147,7 +147,7 @@ class StoriesController < ApplicationController
end
@comments = Comment.ordered_for_story_or_thread_for_user(@story.id,
@showing_comment.thread_id, @user ? @user.id : nil)
@showing_comment.thread_id, @user ? @user : nil)
@comments.each do |c,x|
if c.id == @showing_comment.id

View file

@ -23,8 +23,11 @@ class Comment < ActiveRecord::Base
has "(upvotes - downvotes)", :as => :score, :type => :integer,
:sortable => true
has is_moderated, is_deleted
has created_at
where "is_moderated = 0 AND is_deleted = 0"
end
validate do
@ -42,11 +45,15 @@ class Comment < ActiveRecord::Base
end
def self.regenerate_markdown
Comment.record_timestamps = false
Comment.all.each do |c|
c.markeddown_comment = c.generated_markeddown_comment
Comment.record_timestamps = false
c.save(:validate => false)
end
Comment.record_timestamps = true
nil
end
@ -72,6 +79,10 @@ class Comment < ActiveRecord::Base
self.story.update_comment_count!
end
def is_gone?
is_deleted? || is_moderated?
end
def mark_submitter
Keystore.increment_value_for("user:#{self.user_id}:comments_posted")
@ -97,7 +108,30 @@ class Comment < ActiveRecord::Base
rescue
end
end
def delete_for_user(user)
Comment.record_timestamps = false
if user.is_admin? && user.id != self.user_id
self.is_moderated = true
else
self.is_deleted = true
end
self.save(:validate => false)
Comment.record_timestamps = true
end
def undelete_for_user(user)
Comment.record_timestamps = false
self.is_moderated = false
self.is_deleted = false
self.save(:validate => false)
Comment.record_timestamps = true
end
def give_upvote_or_downvote_and_recalculate_confidence!(upvote, downvote)
self.upvotes += upvote.to_i
self.downvotes += downvote.to_i
@ -157,7 +191,7 @@ class Comment < ActiveRecord::Base
self.updated_at && (self.updated_at - self.created_at > 1.minute)
end
def self.ordered_for_story_or_thread_for_user(story_id, thread_id, user_id)
def self.ordered_for_story_or_thread_for_user(story_id, thread_id, user)
parents = {}
if thread_id
@ -187,17 +221,51 @@ class Comment < ActiveRecord::Base
}
recursor.call(nil, 0)
# TODO: handle deleted comments, show for user_id
# for deleted comments, if they have no children, they can be removed from
# the tree. otherwise they have to stay and a "[deleted]" stub will be
# shown
new_ordered = []
ordered.each_with_index do |c,x|
if c.is_gone?
if ordered[x + 1] && (ordered[x + 1].indent_level > c.indent_level)
# we have child comments, so we must stay
elsif user && (user.is_admin? || c.user_id == user.id)
# admins and authors should be able to see their deleted comments
else
# drop this one
next
end
end
ordered
new_ordered.push c
end
new_ordered
end
def is_editable_by_user?(user)
if !user || user.id != self.user_id
if user && user.is_admin?
return true
elsif user && user.id == self.user_id
if self.is_moderated?
return false
else
return (Time.now.to_i - (self.updated_at ? self.updated_at.to_i :
self.created_at.to_i) < (60 * MAX_EDIT_MINS))
end
else
return false
end
end
def is_undeletable_by_user?(user)
if user && user.is_admin?
return true
elsif user && user.id == self.user_id && !self.is_moderated?
return true
else
return false
end
(Time.now.to_i - self.created_at.to_i < (60 * MAX_EDIT_MINS))
end
def url

View file

@ -39,6 +39,8 @@ class Story < ActiveRecord::Base
:title => 10,
:tags => 5,
}
where "is_moderated = 0 AND is_expired = 0"
end
validate do
@ -278,7 +280,9 @@ class Story < ActiveRecord::Base
end
def is_undeletable_by_user?(user)
if user && (user.is_admin? || user.id == self.user_id)
if user && user.is_admin?
return true
elsif user && user.id == self.user_id && !self.is_moderated?
return true
else
return false

View file

@ -6,13 +6,15 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
<%= comment.score <= -3 ? "negative_3" : "" %>
<%= comment.score <= -5 ? "negative_5" : "" %>
<%= comment.score <= -7 ? "negative_7" : "" %>">
<div class="voters">
<a class="upvoter"></a>
<div class="score">
<%= comment.score %>
</div>
<a class="downvoter"></a>
</div>
<% if !comment.is_gone? %>
<div class="voters">
<a class="upvoter"></a>
<div class="score">
<%= comment.score %>
</div>
<a class="downvoter"></a>
</div>
<% end %>
<div class="details">
<div class="byline">
<% if comment.previewing %>
@ -38,13 +40,22 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
<a href="<%= story.comments_url %>/comments/<%= comment.short_id
%>">link</a>
<% if !story.is_gone? %>
<% if comment.is_editable_by_user?(@user) %>
|
<% if comment.is_editable_by_user?(@user) %>
<a class="comment_editor">edit</a>
<% else %>
<a class="comment_editor">edit</a>
<% end %>
<% if comment.is_gone? && comment.is_undeletable_by_user?(@user) %>
|
<a class="comment_undeletor">undelete</a>
<% elsif !comment.is_gone? && comment.is_editable_by_user?(@user) %>
|
<a class="comment_deletor">delete</a>
<% end %>
<% if !story.is_gone? && !comment.is_gone? %>
|
<a class="comment_replier">reply</a>
<% end %>
<% end %>
<% if false && defined?(collapsable) && collapsable # XXX %>
@ -59,7 +70,16 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
<% end %>
</div>
<div class="comment_text">
<%= raw comment.markeddown_comment %>
<% if comment.is_gone? %>
<p>
<span class="na">
[Comment removed by <%= comment.is_deleted? ? "author" :
"moderator" %>]
</span>
</p>
<% else %>
<%= raw comment.markeddown_comment %>
<% end %>
</div>
<div class="comment_reply"></div>

View file

@ -45,6 +45,8 @@ Lobsters::Application.routes.draw do
post "edit"
post "preview"
post "update"
post "delete"
post "undelete"
end
post "/comments/post_to/:story_id" => "comments#create"
post "/comments/preview_to/:story_id" => "comments#preview_new"

View file

@ -0,0 +1,9 @@
class AddCommentDeleted < ActiveRecord::Migration
def up
add_column "comments", "is_deleted", :boolean, :default => false
add_column "comments", "is_moderated", :boolean, :default => false
end
def down
end
end

View file

@ -11,21 +11,23 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120706221602) do
ActiveRecord::Schema.define(:version => 20120712174445) do
create_table "comments", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at"
t.string "short_id", :limit => 10, :default => "", :null => false
t.integer "story_id", :null => false
t.integer "user_id", :null => false
t.string "short_id", :limit => 10, :default => "", :null => false
t.integer "story_id", :null => false
t.integer "user_id", :null => false
t.integer "parent_comment_id"
t.integer "thread_id"
t.text "comment", :null => false
t.integer "upvotes", :default => 0, :null => false
t.integer "downvotes", :default => 0, :null => false
t.decimal "confidence", :precision => 20, :scale => 17
t.text "comment", :null => false
t.integer "upvotes", :default => 0, :null => false
t.integer "downvotes", :default => 0, :null => false
t.decimal "confidence", :precision => 20, :scale => 19, :default => 0.0, :null => false
t.text "markeddown_comment"
t.boolean "is_deleted", :default => false
t.boolean "is_moderated", :default => false
end
add_index "comments", ["confidence"], :name => "confidence_idx"
@ -67,14 +69,14 @@ ActiveRecord::Schema.define(:version => 20120706221602) do
t.datetime "created_at"
t.integer "user_id"
t.string "url", :limit => 250, :default => ""
t.string "title", :limit => 150, :default => "", :null => false
t.string "title", :limit => 150, :default => "", :null => false
t.text "description"
t.string "short_id", :limit => 6, :default => "", :null => false
t.integer "is_expired", :limit => 1, :default => 0, :null => false
t.integer "upvotes", :default => 0, :null => false
t.integer "downvotes", :default => 0, :null => false
t.integer "is_moderated", :limit => 1, :default => 0, :null => false
t.decimal "hotness", :precision => 20, :scale => 10
t.string "short_id", :limit => 6, :default => "", :null => false
t.integer "is_expired", :limit => 1, :default => 0, :null => false
t.integer "upvotes", :default => 0, :null => false
t.integer "downvotes", :default => 0, :null => false
t.integer "is_moderated", :limit => 1, :default => 0, :null => false
t.decimal "hotness", :precision => 20, :scale => 10, :default => 0.0, :null => false
t.text "markeddown_description"
end