diff --git a/app/controllers/post_moderation_controller.rb b/app/controllers/post_moderation_controller.rb index 773b79efd..3754889bf 100644 --- a/app/controllers/post_moderation_controller.rb +++ b/app/controllers/post_moderation_controller.rb @@ -33,6 +33,16 @@ class PostModerationController < ApplicationController end end + def delete + @post = Post.find(params[:post_id]) + @post.delete! + end + + def undelete + @post = Post.find(params[:post_id]) + @post.undelete! + end + private def disapproval_error(e) respond_to do |format| diff --git a/app/logical/cache.rb b/app/logical/cache.rb index 5dfdb1068..d6d6107d3 100644 --- a/app/logical/cache.rb +++ b/app/logical/cache.rb @@ -5,6 +5,14 @@ class Cache ActiveRecord::Base.logger.debug('MemCache Incr %s' % [key]) end + def self.decr(key, expiry = 0) + val = Cache.get(key, expiry) + if val.to_i > 0 + Cache.put(key, val.to_i - 1) + end + ActiveRecord::Base.logger.debug('MemCache Decr %s' % [key]) + end + def self.get_multi(keys, prefix, expiry = 0) key_to_sanitized_key_hash = keys.inject({}) do |hash, x| hash[x] = "#{prefix}:#{Cache.sanitize(x)}" diff --git a/app/models/post.rb b/app/models/post.rb index b1660256c..7f47932e3 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -27,6 +27,7 @@ class Post < ActiveRecord::Base validate :validate_parent_does_not_have_a_parent attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at scope :pending, where(["is_pending = ?", true]) + scope :undeleted, where(["is_deleted = ?", false]) scope :visible, lambda {|user| Danbooru.config.can_user_see_post_conditions(user)} scope :commented_before, lambda {|date| where("last_commented_at < ?", date).order("last_commented_at DESC")} scope :available_for_moderation, lambda {where(["id NOT IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])} @@ -237,6 +238,10 @@ class Post < ActiveRecord::Base end module PresenterMethods + def presenter + @presenter ||= PostPresenter.new(self) + end + def pretty_rating case rating when "q" @@ -480,11 +485,7 @@ class Post < ActiveRecord::Base q = Tag.parse_query(q) end - if q[:status] == "deleted" - relation = RemovedPost.scoped - else - relation = Post.scoped - end + relation = Post.scoped relation = add_range_relation(q[:post_id], "posts.id", relation) relation = add_range_relation(q[:mpixels], "posts.width * posts.height / 1000000.0", relation) @@ -507,6 +508,8 @@ class Post < ActiveRecord::Base relation = relation.where("posts.is_pending = TRUE") elsif q[:status] == "flagged" relation = relation.where("posts.is_flagged = TRUE") + elsif q[:status] == "deleted" + relation = relation.where("posts.is_deleted = TRUE") end if q[:source].is_a?(String) @@ -641,13 +644,31 @@ class Post < ActiveRecord::Base end module CountMethods + def get_count_from_cache(tags) + Cache.get(count_cache_key(tags)) + end + + def set_count_in_cache(tags, count) + if count < 100 + expiry = 0 + else + expiry = (count * 4).minutes + end + + Cache.put(count_cache_key(tags), count, expiry) + end + + def count_cache_key(tags) + "pfc:#{Cache.sanitize(tags)}" + end + def fast_count(tags = "") tags = tags.to_s - count = Cache.get("pfc:#{Cache.sanitize(tags)}") + count = get_count_from_cache(tags) if count.nil? - count = Post.tag_match("#{tags}").count + count = Post.tag_match(tags).undeleted.count if count > Danbooru.config.posts_per_page * 10 - Cache.put("pfc:#{Cache.sanitize(tags)}", count, (count * 4).minutes) + set_count_in_cache(tags, count) end end count @@ -657,9 +678,9 @@ class Post < ActiveRecord::Base module CacheMethods def expire_cache(tag_name) if Post.fast_count("") < 1000 - Cache.delete("pfc:") + Cache.delete(Post.count_cache_key("")) end - Cache.delete("pfc:#{Cache.sanitize(tag_name)}") + Cache.delete(Post.count_cache_key(tag_name)) end end @@ -679,14 +700,14 @@ class Post < ActiveRecord::Base module ClassMethods def update_has_children_flag_for(post_id) - has_children = Post.exists?(["parent_id = ?", post_id]) + has_children = Post.exists?(["is_deleted = ? AND parent_id = ?", false, post_id]) execute_sql("UPDATE posts SET has_children = ? WHERE id = ?", has_children, post_id) end def recalculate_has_children_for_all_posts transaction do execute_sql("UPDATE posts SET has_children = false WHERE has_children = true") - execute_sql("UPDATE posts SET has_children = true WHERE id IN (SELECT p.parent_id FROM posts p WHERE p.parent_id IS NOT NULL)") + execute_sql("UPDATE posts SET has_children = true WHERE id IN (SELECT p.parent_id FROM posts p WHERE p.parent_id IS NOT NULL AND is_deleted = FALSE)") end end end @@ -746,22 +767,23 @@ class Post < ActiveRecord::Base end end - module RemovalMethods - def remove! + module DeletionMethods + def delete! Post.transaction do - execute_sql("INSERT INTO removed_posts (#{Post.column_names.join(', ')}) SELECT #{Post.column_names.join(', ')} FROM posts WHERE posts.id = #{id}") give_favorites_to_parent update_children_on_destroy delete_favorites decrement_tag_post_counts - execute_sql("DELETE FROM posts WHERE id = #{id}") + update_attribute(:is_deleted, true) update_parent_on_destroy tag_array.each {|x| expire_cache(x)} end end - def is_removed? - false + def undelete! + update_attribute(:is_deleted, false) + tag_array.each {|x| expire_cache(x)} + update_parent_on_save end end @@ -826,17 +848,13 @@ class Post < ActiveRecord::Base extend CountMethods include CacheMethods include ParentMethods - include RemovalMethods + include DeletionMethods include VersionMethods def reload(options = nil) super reset_tag_array_cache end - - def presenter - @presenter ||= PostPresenter.new(self) - end end Post.connection.extend(PostgresExtensions) diff --git a/app/models/removed_post.rb b/app/models/removed_post.rb deleted file mode 100644 index 740595334..000000000 --- a/app/models/removed_post.rb +++ /dev/null @@ -1,38 +0,0 @@ -class RemovedPost < ActiveRecord::Base - has_one :unapproval, :dependent => :destroy, :foreign_key => "post_id" - - module RemovalMethods - def unremove! - Post.transaction do - execute_sql("INSERT INTO posts (#{Post.column_names.join(', ')}) SELECT #{Post.column_names.join(', ')} FROM removed_posts WHERE id = #{id}") - execute_sql("DELETE FROM removed_posts WHERE id = #{id}") - end - end - end - - def fast_count(tags) - count = Cache.get("rpfc:#{Cache.sanitize(tags)}") - if count.nil? - count = RemovedPost.tag_match("#{tags}").count - if count > Danbooru.config.posts_per_page * 10 - Cache.put("rpfc:#{Cache.sanitize(tags)}", count, (count * 4).minutes) - end - end - count - end - - def is_removed? - true - end - - include Post::FileMethods - include Post::ImageMethods - include Post::TagMethods - include Post::SearchMethods - include Post::UploaderMethods - include Post::PoolMethods - include Post::CountMethods - include Post::CacheMethods - include RemovalMethods -end - diff --git a/app/models/unapproval.rb b/app/models/unapproval.rb index dd0385aee..0eae29127 100644 --- a/app/models/unapproval.rb +++ b/app/models/unapproval.rb @@ -9,7 +9,7 @@ class Unapproval < ActiveRecord::Base before_save :flag_post def validate_post_is_active - if post.is_pending? || post.is_flagged? || post.is_removed? + if post.is_pending? || post.is_flagged? || post.is_deleted? errors[:post] << "is inactive" false else diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index 44f5a0d76..2dae25442 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -3,7 +3,7 @@ class PostPresenter < Presenter flags = [] flags << "pending" if post.is_pending? flags << "flagged" if post.is_flagged? - flags << "removed" if post.is_removed? + flags << "deleted" if post.is_deleted? html = %{
} html << %{} @@ -22,7 +22,7 @@ class PostPresenter < Presenter end def image_html(template) - return template.content_tag("p", "This image was deleted.") if @post.is_removed? && !CurrentUser.user.is_janitor? + return template.content_tag("p", "This image was deleted.") if @post.is_deleted? && !CurrentUser.user.is_janitor? return template.content_tag("p", "You need a privileged account to see this image.") if !Danbooru.config.can_see_post?(@post, CurrentUser.user) if @post.is_flash? diff --git a/app/views/post_moderation/delete.js.erb b/app/views/post_moderation/delete.js.erb new file mode 100644 index 000000000..756d5e4ee --- /dev/null +++ b/app/views/post_moderation/delete.js.erb @@ -0,0 +1,3 @@ +$("a#delete").hide(); +$("a#undelete").show(); +$("img#delete-wait").hide(); diff --git a/app/views/post_moderation/undelete.js.erb b/app/views/post_moderation/undelete.js.erb new file mode 100644 index 000000000..0f7628fc9 --- /dev/null +++ b/app/views/post_moderation/undelete.js.erb @@ -0,0 +1,3 @@ +$("a#delete").show(); +$("a#undelete").hide(); +$("img#undelete-wait").hide(); diff --git a/app/views/posts/partials/show/_options.html.erb b/app/views/posts/partials/show/_options.html.erb index 6560adc6e..55cd9070d 100644 --- a/app/views/posts/partials/show/_options.html.erb +++ b/app/views/posts/partials/show/_options.html.erb @@ -9,11 +9,8 @@
  • <%= link_to "Disapprove", "#", :id => "disapprove" %> <%= wait_image("disapprove-wait") %>
  • <% end %> <% if CurrentUser.is_moderator? %> - <% if post.is_removed? %> -
  • <%= link_to "Undelete", "#" %>
  • - <% else %> -
  • <%= link_to "Delete", "#" %>
  • - <% end %> +
  • <%= link_to "Undelete", "#", :id => "undelete" %> <%= wait_image("undelete-wait") %>
  • +
  • <%= link_to "Delete", "#", :id => "delete" %> <%= wait_image("delete-wait") %>
  • <% end %>
  • <%= link_to "Pool", "#" %>
  • \ No newline at end of file diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index 134d721aa..91749966e 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -69,6 +69,7 @@ + <% end %> <%= render :partial => "posts/partials/common/secondary_links" %> diff --git a/config/routes.rb b/config/routes.rb index ad110e57e..fa0a64b3f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -72,6 +72,8 @@ Danbooru::Application.routes.draw do match '/post_moderation/moderate' => 'post_moderation#moderate' match '/post_moderation/disapprove' => 'post_moderation#disapprove', :via => :put match '/post_moderation/approve' => 'post_moderation#approve', :via => :put + match '/post_moderation/delete' => 'post_moderation#delete', :via => :post + match '/post_moderation/undelete' => 'post_moderation#undelete', :via => :post match '/dtext/preview' => 'dtext#preview', :via => :post match "/site_map" => "static#site_map", :as => "site_map" match "/terms_of_service" => "static#terms_of_service", :as => "terms_of_service" diff --git a/db/development_structure.sql b/db/development_structure.sql index 0f23676fb..651a1a1ed 100644 --- a/db/development_structure.sql +++ b/db/development_structure.sql @@ -1132,6 +1132,7 @@ CREATE TABLE posts ( is_rating_locked boolean DEFAULT false NOT NULL, is_pending boolean DEFAULT false NOT NULL, is_flagged boolean DEFAULT false NOT NULL, + is_deleted boolean DEFAULT false NOT NULL, uploader_string character varying(255) NOT NULL, uploader_ip_addr inet NOT NULL, approver_string character varying(255) DEFAULT ''::character varying NOT NULL, @@ -1174,65 +1175,6 @@ CREATE SEQUENCE posts_id_seq ALTER SEQUENCE posts_id_seq OWNED BY posts.id; --- --- Name: removed_posts; Type: TABLE; Schema: public; Owner: -; Tablespace: --- - -CREATE TABLE removed_posts ( - id integer NOT NULL, - created_at timestamp without time zone, - updated_at timestamp without time zone, - score integer DEFAULT 0 NOT NULL, - source character varying(255), - md5 character varying(255) NOT NULL, - rating character(1) DEFAULT 'q'::bpchar NOT NULL, - is_note_locked boolean DEFAULT false NOT NULL, - is_rating_locked boolean DEFAULT false NOT NULL, - is_pending boolean DEFAULT false NOT NULL, - is_flagged boolean DEFAULT false NOT NULL, - uploader_string character varying(255) NOT NULL, - uploader_ip_addr inet NOT NULL, - approver_string character varying(255) DEFAULT ''::character varying NOT NULL, - fav_string text DEFAULT ''::text NOT NULL, - pool_string text DEFAULT ''::text NOT NULL, - view_count integer DEFAULT 0 NOT NULL, - last_noted_at timestamp without time zone, - last_commented_at timestamp without time zone, - tag_string text DEFAULT ''::text NOT NULL, - tag_index tsvector, - tag_count integer DEFAULT 0 NOT NULL, - tag_count_general integer DEFAULT 0 NOT NULL, - tag_count_artist integer DEFAULT 0 NOT NULL, - tag_count_character integer DEFAULT 0 NOT NULL, - tag_count_copyright integer DEFAULT 0 NOT NULL, - file_ext character varying(255) NOT NULL, - file_size integer NOT NULL, - image_width integer NOT NULL, - image_height integer NOT NULL, - parent_id integer, - has_children boolean DEFAULT false NOT NULL -); - - --- --- Name: removed_posts_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE removed_posts_id_seq - START WITH 1 - INCREMENT BY 1 - NO MAXVALUE - NO MINVALUE - CACHE 1; - - --- --- Name: removed_posts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE removed_posts_id_seq OWNED BY removed_posts.id; - - -- -- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -; Tablespace: -- @@ -1354,7 +1296,6 @@ CREATE TABLE tags ( id integer NOT NULL, name character varying(255) NOT NULL, post_count integer DEFAULT 0 NOT NULL, - view_count integer DEFAULT 0 NOT NULL, category integer DEFAULT 0 NOT NULL, related_tags text, related_tags_updated_at timestamp without time zone, @@ -1837,13 +1778,6 @@ ALTER TABLE post_votes ALTER COLUMN id SET DEFAULT nextval('post_votes_id_seq':: ALTER TABLE posts ALTER COLUMN id SET DEFAULT nextval('posts_id_seq'::regclass); --- --- Name: id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE removed_posts ALTER COLUMN id SET DEFAULT nextval('removed_posts_id_seq'::regclass); - - -- -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- @@ -2170,14 +2104,6 @@ ALTER TABLE ONLY posts ADD CONSTRAINT posts_pkey PRIMARY KEY (id); --- --- Name: removed_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: --- - -ALTER TABLE ONLY removed_posts - ADD CONSTRAINT removed_posts_pkey PRIMARY KEY (id); - - -- -- Name: tag_aliases_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- @@ -2825,90 +2751,6 @@ CREATE INDEX index_posts_on_source ON posts USING btree (source); CREATE INDEX index_posts_on_tags_index ON posts USING gin (tag_index); --- --- Name: index_removed_posts_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_created_at ON removed_posts USING btree (created_at); - - --- --- Name: index_removed_posts_on_file_size; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_file_size ON removed_posts USING btree (file_size); - - --- --- Name: index_removed_posts_on_image_height; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_image_height ON removed_posts USING btree (image_height); - - --- --- Name: index_removed_posts_on_image_width; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_image_width ON removed_posts USING btree (image_width); - - --- --- Name: index_removed_posts_on_last_commented_at; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_last_commented_at ON removed_posts USING btree (last_commented_at); - - --- --- Name: index_removed_posts_on_last_noted_at; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_last_noted_at ON removed_posts USING btree (last_noted_at); - - --- --- Name: index_removed_posts_on_md5; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE UNIQUE INDEX index_removed_posts_on_md5 ON removed_posts USING btree (md5); - - --- --- Name: index_removed_posts_on_mpixels; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_mpixels ON posts USING btree (((((image_width * image_height))::numeric / 1000000.0))); - - --- --- Name: index_removed_posts_on_parent_id; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_parent_id ON removed_posts USING btree (parent_id); - - --- --- Name: index_removed_posts_on_source; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_source ON removed_posts USING btree (source); - - --- --- Name: index_removed_posts_on_tags_index; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_tags_index ON posts USING gin (tag_index); - - --- --- Name: index_removed_posts_on_view_count; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_removed_posts_on_view_count ON removed_posts USING btree (view_count); - - -- -- Name: index_tag_aliases_on_antecedent_name; Type: INDEX; Schema: public; Owner: -; Tablespace: -- @@ -2965,6 +2807,13 @@ CREATE UNIQUE INDEX index_tags_on_name ON tags USING btree (name); CREATE INDEX index_unapprovals_on_post_id ON unapprovals USING btree (post_id); +-- +-- Name: index_user_feedback_on_creator_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_user_feedback_on_creator_id ON user_feedback USING btree (creator_id); + + -- -- Name: index_user_feedback_on_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- @@ -3084,16 +2933,6 @@ CREATE TRIGGER trigger_posts_on_tag_index_update EXECUTE PROCEDURE tsvector_update_trigger('tag_index', 'public.danbooru', 'tag_string', 'fav_string', 'pool_string', 'uploader_string', 'approver_string'); --- --- Name: trigger_removed_posts_on_tag_index_update; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER trigger_removed_posts_on_tag_index_update - BEFORE INSERT OR UPDATE ON removed_posts - FOR EACH ROW - EXECUTE PROCEDURE tsvector_update_trigger('tag_index', 'public.danbooru', 'tag_string', 'fav_string', 'pool_string', 'uploader_string', 'approver_string'); - - -- -- Name: trigger_wiki_pages_on_update; Type: TRIGGER; Schema: public; Owner: - -- @@ -3170,6 +3009,4 @@ INSERT INTO schema_migrations (version) VALUES ('20100309211553'); INSERT INTO schema_migrations (version) VALUES ('20100318213503'); -INSERT INTO schema_migrations (version) VALUES ('20100818180317'); - INSERT INTO schema_migrations (version) VALUES ('20100826232512'); \ No newline at end of file diff --git a/db/migrate/20100204214746_create_posts.rb b/db/migrate/20100204214746_create_posts.rb index d9dfd0b27..bd409003d 100644 --- a/db/migrate/20100204214746_create_posts.rb +++ b/db/migrate/20100204214746_create_posts.rb @@ -13,6 +13,7 @@ class CreatePosts < ActiveRecord::Migration t.column :is_rating_locked, :boolean, :null => false, :default => false t.column :is_pending, :boolean, :null => false, :default => false t.column :is_flagged, :boolean, :null => false, :default => false + t.column :is_deleted, :boolean, :null => false, :default => false # Uploader t.column :uploader_string, :string, :null => false diff --git a/db/migrate/20100818180317_create_removed_posts.rb b/db/migrate/20100818180317_create_removed_posts.rb deleted file mode 100644 index 800f52519..000000000 --- a/db/migrate/20100818180317_create_removed_posts.rb +++ /dev/null @@ -1,75 +0,0 @@ -class CreateRemovedPosts < ActiveRecord::Migration - def self.up - create_table :removed_posts do |t| - t.timestamps - - t.column :score, :integer, :null => false, :default => 0 - t.column :source, :string - t.column :md5, :string, :null => false - t.column :rating, :character, :null => false, :default => 'q' - - # Statuses - t.column :is_note_locked, :boolean, :null => false, :default => false - t.column :is_rating_locked, :boolean, :null => false, :default => false - t.column :is_pending, :boolean, :null => false, :default => false - t.column :is_flagged, :boolean, :null => false, :default => false - - # Uploader - t.column :uploader_string, :string, :null => false - t.column :uploader_ip_addr, "inet", :null => false - - # Approver - t.column :approver_string, :string, :null => false, :default => "" - - # Favorites - t.column :fav_string, :text, :null => false, :default => "" - - # Pools - t.column :pool_string, :text, :null => false, :default => "" - - # Cached - t.column :view_count, :integer, :null => false, :default => 0 - t.column :last_noted_at, :datetime - t.column :last_commented_at, :datetime - - # Tags - t.column :tag_string, :text, :null => false, :default => "" - t.column :tag_index, "tsvector" - t.column :tag_count, :integer, :null => false, :default => 0 - t.column :tag_count_general, :integer, :null => false, :default => 0 - t.column :tag_count_artist, :integer, :null => false, :default => 0 - t.column :tag_count_character, :integer, :null => false, :default => 0 - t.column :tag_count_copyright, :integer, :null => false, :default => 0 - - # File - t.column :file_ext, :string, :null => false - t.column :file_size, :integer, :null => false - t.column :image_width, :integer, :null => false - t.column :image_height, :integer, :null => false - - # Parent - t.column :parent_id, :integer - t.column :has_children, :boolean, :null => false, :default => false - end - - add_index :removed_posts, :md5, :unique => true - add_index :removed_posts, :created_at - add_index :removed_posts, :last_commented_at - add_index :removed_posts, :last_noted_at - add_index :removed_posts, :file_size - add_index :removed_posts, :image_width - add_index :removed_posts, :image_height - add_index :removed_posts, :source - add_index :removed_posts, :view_count - add_index :removed_posts, :parent_id - - execute "CREATE INDEX index_removed_posts_on_mpixels ON posts (((image_width * image_height)::numeric / 1000000.0))" - - execute "CREATE INDEX index_removed_posts_on_tags_index ON posts USING gin (tag_index)" - execute "CREATE TRIGGER trigger_removed_posts_on_tag_index_update BEFORE INSERT OR UPDATE ON removed_posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('tag_index', 'public.danbooru', 'tag_string', 'fav_string', 'pool_string', 'uploader_string', 'approver_string')" - end - - def self.down - drop_table :removed_posts - end -end diff --git a/public/javascripts/compiled/default.js b/public/javascripts/compiled/default.js index 38e226f7f..cf867c730 100644 --- a/public/javascripts/compiled/default.js +++ b/public/javascripts/compiled/default.js @@ -1244,6 +1244,9 @@ $(document).ready(function() { this.initialize_approve_link(); this.initialize_disapprove_link(); this.hide_or_show_approve_and_disapprove_links(); + this.hide_or_show_delete_and_undelete_links(); + this.initialize_delete_link(); + this.initialize_undelete_link(); } Danbooru.PostModeration.hide_or_show_approve_and_disapprove_links = function() { @@ -1253,6 +1256,44 @@ $(document).ready(function() { } } + Danbooru.PostModeration.hide_or_show_delete_and_undelete_links = function() { + if ($("meta[name=post-is-deleted]").attr("content") == "true") { + $("a#delete").hide(); + } else { + $("a#undelete").hide(); + } + } + + Danbooru.PostModeration.initialize_delete_link = function() { + $("a#delete").click(function() { + $.ajax({ + url: "/post_moderation/delete.js", + type: "post", + data: { + post_id: $("meta[name=post-id]").attr("content") + }, + beforeSend: function() { + $("img#delete-wait").show(); + } + }); + }); + } + + Danbooru.PostModeration.initialize_undelete_link = function() { + $("a#undelete").click(function() { + $.ajax({ + url: "/post_moderation/undelete.js", + type: "post", + data: { + post_id: $("meta[name=post-id]").attr("content") + }, + beforeSend: function() { + $("img#undelete-wait").show(); + } + }); + }); + } + Danbooru.PostModeration.initialize_disapprove_link = function() { $("a#disapprove").click(function() { $.ajax({ diff --git a/public/javascripts/src/app/post_moderation.js b/public/javascripts/src/app/post_moderation.js index 2231f69d3..b1d20bba6 100644 --- a/public/javascripts/src/app/post_moderation.js +++ b/public/javascripts/src/app/post_moderation.js @@ -5,6 +5,9 @@ this.initialize_approve_link(); this.initialize_disapprove_link(); this.hide_or_show_approve_and_disapprove_links(); + this.hide_or_show_delete_and_undelete_links(); + this.initialize_delete_link(); + this.initialize_undelete_link(); } Danbooru.PostModeration.hide_or_show_approve_and_disapprove_links = function() { @@ -14,6 +17,44 @@ } } + Danbooru.PostModeration.hide_or_show_delete_and_undelete_links = function() { + if ($("meta[name=post-is-deleted]").attr("content") == "true") { + $("a#delete").hide(); + } else { + $("a#undelete").hide(); + } + } + + Danbooru.PostModeration.initialize_delete_link = function() { + $("a#delete").click(function() { + $.ajax({ + url: "/post_moderation/delete.js", + type: "post", + data: { + post_id: $("meta[name=post-id]").attr("content") + }, + beforeSend: function() { + $("img#delete-wait").show(); + } + }); + }); + } + + Danbooru.PostModeration.initialize_undelete_link = function() { + $("a#undelete").click(function() { + $.ajax({ + url: "/post_moderation/undelete.js", + type: "post", + data: { + post_id: $("meta[name=post-id]").attr("content") + }, + beforeSend: function() { + $("img#undelete-wait").show(); + } + }); + }); + } + Danbooru.PostModeration.initialize_disapprove_link = function() { $("a#disapprove").click(function() { $.ajax({ diff --git a/test/factories/removed_post.rb b/test/factories/removed_post.rb deleted file mode 100644 index 2b733ecf4..000000000 --- a/test/factories/removed_post.rb +++ /dev/null @@ -1,13 +0,0 @@ -Factory.define(:removed_post) do |f| - f.md5 {|x| Time.now.to_f.to_s} - f.uploader {|x| x.association(:user)} - f.uploader_ip_addr "127.0.0.1" - f.tag_string "tag1 tag2" - f.tag_count 2 - f.tag_count_general 2 - f.file_ext "jpg" - f.image_width 100 - f.image_height 200 - f.file_size 2000 - f.rating "q" -end diff --git a/test/functional/post_moderation_controller_test.rb b/test/functional/post_moderation_controller_test.rb index 94414e61d..f01b58425 100644 --- a/test/functional/post_moderation_controller_test.rb +++ b/test/functional/post_moderation_controller_test.rb @@ -12,6 +12,30 @@ class PostModerationControllerTest < ActionController::TestCase CurrentUser.user = nil CurrentUser.ip_addr = nil end + + context "delete action" do + setup do + @post = Factory.create(:post) + end + + should "delete a post" do + post :delete, {:post_id => @post.id, :format => "js"}, {:user_id => @mod.id} + @post.reload + assert_equal(true, @post.is_deleted?) + end + end + + context "undelete action" do + setup do + @post = Factory.create(:post, :is_deleted => true) + end + + should "undelete a post" do + post :undelete, {:post_id => @post.id, :format => "js"}, {:user_id => @mod.id} + @post.reload + assert_equal(false, @post.is_deleted?) + end + end context "moderate action" do setup do diff --git a/test/test_helper.rb b/test/test_helper.rb index 83f618b2f..66e7adb60 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -14,6 +14,7 @@ module UploadTestMethods FileUtils.copy_file(path, tempfile.path) (class << tempfile; self; end).class_eval do alias local_path path + define_method(:tempfile) {self} define_method(:original_filename) {filename} define_method(:content_type) {content_type} end diff --git a/test/unit/post_test.rb b/test/unit/post_test.rb index dee5ab65f..324e2696e 100644 --- a/test/unit/post_test.rb +++ b/test/unit/post_test.rb @@ -13,47 +13,30 @@ class PostTest < ActiveSupport::TestCase CurrentUser.ip_addr = nil end - context "Removal:" do - context "Removing a post" do + context "Deletion:" do + context "Deleting a post" do should "update the fast count" do post = Factory.create(:post, :tag_string => "aaa") assert_equal(1, Post.fast_count) assert_equal(1, Post.fast_count("aaa")) - post.remove! + post.delete! assert_equal(0, Post.fast_count) assert_equal(0, Post.fast_count("aaa")) end - should "duplicate the post in the archive table and remove it from the base table" do + should "toggle the is_deleted flag" do post = Factory.create(:post) - - assert_difference("RemovedPost.count", 1) do - assert_difference("Post.count", -1) do - post.remove! - end - end - - removed_post = RemovedPost.last - assert_equal(post.tag_string, removed_post.tag_string) + assert_equal(false, post.is_deleted?) + post.delete! + assert_equal(true, post.is_deleted?) end should "decrement the tag counts" do post = Factory.create(:post, :tag_string => "aaa") assert_equal(1, Tag.find_by_name("aaa").post_count) - post.remove! + post.delete! assert_equal(0, Tag.find_by_name("aaa").post_count) end - - should "preserve the id" do - post = Factory.create(:post, :tag_string => "aaa") - post_id = post.id - post.remove! - removed_post = RemovedPost.last - assert_equal(post_id, removed_post.id) - removed_post.unremove! - post = Post.last - assert_equal(post_id, post.id) - end end end @@ -100,7 +83,7 @@ class PostTest < ActiveSupport::TestCase c1 = Factory.create(:post, :parent_id => p1.id) user = Factory.create(:user) c1.add_favorite(user) - c1.remove! + c1.delete! p1.reload assert(!Favorite.exists?(:post_id => c1.id, :user_id => user.id)) assert(Favorite.exists?(:post_id => p1.id, :user_id => user.id)) @@ -109,7 +92,7 @@ class PostTest < ActiveSupport::TestCase should "update the parent's has_children flag" do p1 = Factory.create(:post) c1 = Factory.create(:post, :parent_id => p1.id) - c1.remove! + c1.delete! p1.reload assert(!p1.has_children?, "Parent should not have children") end @@ -120,7 +103,7 @@ class PostTest < ActiveSupport::TestCase should "remove the parent of that child" do p1 = Factory.create(:post) c1 = Factory.create(:post, :parent_id => p1.id) - p1.remove! + p1.delete! c1.reload assert_nil(c1.parent) end @@ -132,7 +115,7 @@ class PostTest < ActiveSupport::TestCase c1 = Factory.create(:post, :parent_id => p1.id) c2 = Factory.create(:post, :parent_id => p1.id) c3 = Factory.create(:post, :parent_id => p1.id) - p1.remove! + p1.delete! c1.reload c2.reload c3.reload @@ -147,10 +130,8 @@ class PostTest < ActiveSupport::TestCase should "not preserve the parent's has_children flag" do p1 = Factory.create(:post) c1 = Factory.create(:post, :parent_id => p1.id) - c1.remove! - c1 = RemovedPost.last - c1.unremove! - c1 = Post.last + c1.delete! + c1.undelete! p1.reload assert_nil(p1.parent_id) assert(!p1.has_children?, "Parent should not have children") @@ -182,15 +163,6 @@ class PostTest < ActiveSupport::TestCase assert_equal("approver:#{CurrentUser.name}", post.approver_string) end - should "preserve the unapproval association even when removed" do - post = Factory.create(:post) - post.unapprove!("bad") - post.remove! - removed_post = RemovedPost.last - assert_not_nil(removed_post.unapproval) - assert_equal("bad", removed_post.unapproval.reason) - end - context "that was previously approved by person X" do should "not allow person X to reapprove that post" do user = Factory.create(:janitor_user, :name => "xxx") diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index de284592a..1dde28f29 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -30,7 +30,7 @@ class UserTest < ActiveSupport::TestCase user.update_attribute(:is_contributor, false) 40.times do - Factory.create(:removed_post, :uploader => user) + Factory.create(:post, :uploader => user, :is_deleted => true) end assert(!user.can_upload?)