Fix #4178: add ability to mass undo tag edits.
Adds checkboxes to the /post_versions index allowing you to select and undo multiple versions at once.
This commit is contained in:
@@ -2,8 +2,10 @@ class PostVersionsController < ApplicationController
|
||||
before_action :member_only, except: [:index, :search]
|
||||
before_action :check_availabililty
|
||||
respond_to :html, :xml, :json
|
||||
respond_to :js, only: [:undo]
|
||||
|
||||
def index
|
||||
# XXX statement timeouts
|
||||
@post_versions = PostArchive.includes(:updater, post: [:versions]).search(search_params).paginate(params[:page], :limit => params[:limit], :search_count => params[:search])
|
||||
respond_with(@post_versions)
|
||||
end
|
||||
@@ -13,14 +15,9 @@ class PostVersionsController < ApplicationController
|
||||
|
||||
def undo
|
||||
@post_version = PostArchive.find(params[:id])
|
||||
@post_version.undo!
|
||||
|
||||
if @post_version.post.visible?
|
||||
@post_version.undo!
|
||||
end
|
||||
|
||||
respond_with(@post_version) do |format|
|
||||
format.js
|
||||
end
|
||||
respond_with(@post_version)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -36,6 +36,7 @@ export { default as Note } from '../src/javascripts/notes.js';
|
||||
export { default as Post } from '../src/javascripts/posts.js.erb';
|
||||
export { default as PostModeMenu } from '../src/javascripts/post_mode_menu.js';
|
||||
export { default as PostTooltip } from '../src/javascripts/post_tooltips.js';
|
||||
export { default as PostVersion } from '../src/javascripts/post_version.js';
|
||||
export { default as RelatedTag } from '../src/javascripts/related_tag.js';
|
||||
export { default as Shortcuts } from '../src/javascripts/shortcuts.js';
|
||||
export { default as Upload } from '../src/javascripts/uploads.js.erb';
|
||||
|
||||
45
app/javascript/src/javascripts/post_version.js
Normal file
45
app/javascript/src/javascripts/post_version.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import Utility from './utility';
|
||||
|
||||
let PostVersion = {};
|
||||
|
||||
PostVersion.initialize_all = function() {
|
||||
if ($("#c-post-versions #a-index").length) {
|
||||
PostVersion.initialize_undo();
|
||||
}
|
||||
};
|
||||
|
||||
PostVersion.initialize_undo = function() {
|
||||
/* Expand the clickable area of the checkbox to the entire table cell. */
|
||||
$(".post-version-select-column").on("click.danbooru", function(event) {
|
||||
$(event.target).find(".post-version-select-checkbox:not(:disabled)").prop("checked", (_, checked) => !checked).change();
|
||||
});
|
||||
|
||||
$("#post-version-select-all-checkbox").on("change.danbooru", function(event) {
|
||||
$("td .post-version-select-checkbox:not(:disabled)").prop("checked", $("#post-version-select-all-checkbox").prop("checked")).change();
|
||||
});
|
||||
|
||||
$(".post-version-select-checkbox").on("change.danbooru", function(event) {
|
||||
let checked = $("td .post-version-select-checkbox:checked");
|
||||
$("#subnav-undo-selected-link").text(`Undo selected (${checked.length})`).toggle(checked.length > 0);
|
||||
});
|
||||
|
||||
$("#subnav-undo-selected-link").on("click.danbooru", PostVersion.undo_selected);
|
||||
};
|
||||
|
||||
PostVersion.undo_selected = async function () {
|
||||
event.preventDefault();
|
||||
|
||||
let updated = 0;
|
||||
let selected_rows = $("td .post-version-select-checkbox:checked").parents("tr");
|
||||
|
||||
for (let row of selected_rows) {
|
||||
let id = $(row).data("post-version-id");
|
||||
await $.ajax(`/post_versions/${id}/undo.json`, { method: "PUT" });
|
||||
|
||||
updated++;
|
||||
Utility.notice(`${updated}/${selected_rows.length} changes undone.`);
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(PostVersion.initialize_all);
|
||||
export default PostVersion;
|
||||
9
app/javascript/src/styles/specific/post_versions.scss
Normal file
9
app/javascript/src/styles/specific/post_versions.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
body.c-post-versions.a-index {
|
||||
#subnav-undo-selected-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.post-version-select-column {
|
||||
min-width: 2em;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
class PostArchive < ApplicationRecord
|
||||
class RevertError < Exception ; end
|
||||
extend Memoist
|
||||
|
||||
belongs_to :post
|
||||
@@ -218,7 +219,9 @@ class PostArchive < ApplicationRecord
|
||||
source.gsub(/^http:\/\//, "").sub(/\/.+/, "")
|
||||
end
|
||||
|
||||
def undo
|
||||
def undo!
|
||||
raise RevertError unless post.visible?
|
||||
|
||||
added = changes[:added_tags] - changes[:obsolete_added_tags]
|
||||
removed = changes[:removed_tags] - changes[:obsolete_removed_tags]
|
||||
|
||||
@@ -239,11 +242,16 @@ class PostArchive < ApplicationRecord
|
||||
post.tag_string = "#{post.tag_string} #{tag}".strip
|
||||
end
|
||||
end
|
||||
|
||||
post.save!
|
||||
end
|
||||
|
||||
def undo!
|
||||
undo
|
||||
post.save!
|
||||
def can_undo?(user)
|
||||
version > 1 && post&.visible? && user.is_member?
|
||||
end
|
||||
|
||||
def can_revert_to?(user)
|
||||
post&.visible? && user.is_member?
|
||||
end
|
||||
|
||||
def updater_name
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
<table class="striped autofit">
|
||||
<thead>
|
||||
<tr>
|
||||
<% if CurrentUser.user.is_builder? %>
|
||||
<th class="post-version-select-column">
|
||||
<label><input type="checkbox" id="post-version-select-all-checkbox" class="post-version-select-checkbox"></label>
|
||||
</th>
|
||||
<% end %>
|
||||
<th width="5%">Post</th>
|
||||
<th width="15%">Date</th>
|
||||
<th width="10%">User</th>
|
||||
@@ -18,7 +23,12 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @post_versions.each do |post_version| %>
|
||||
<tr id="post-version-<%= post_version.id %>">
|
||||
<tr id="post-version-<%= post_version.id %>" data-post-version-id="<%= post_version.id %>">
|
||||
<% if CurrentUser.user.is_builder? %>
|
||||
<td class="post-version-select-column">
|
||||
<input type="checkbox" class="post-version-select-checkbox" <%= "disabled" unless post_version.can_undo?(CurrentUser.user) %>>
|
||||
</td>
|
||||
<% end %>
|
||||
<td><%= link_to("#{post_version.post_id}.#{post_version.id}", post_path(post_version.post_id)) %></td>
|
||||
<td><%= compact_time(post_version.updated_at) %></td>
|
||||
<td>
|
||||
@@ -34,16 +44,14 @@
|
||||
</td>
|
||||
<% end %>
|
||||
<td class="col-expand"><%= post_version_diff(post_version) %></td>
|
||||
<% if CurrentUser.is_member? %>
|
||||
<td>
|
||||
<% if post_version.visible? %>
|
||||
<% if post_version.version != 1 %>
|
||||
<%= link_to "Undo", undo_post_version_path(post_version), :method => :put, :remote => true %> |
|
||||
<% end %>
|
||||
<%= link_to "Revert to", revert_post_path(post_version.post_id, :version_id => post_version.id), :method => :put, :remote => true %>
|
||||
<% end %>
|
||||
</td>
|
||||
<% end %>
|
||||
<td>
|
||||
<% if post_version.can_undo?(CurrentUser.user) %>
|
||||
<%= link_to "Undo", undo_post_version_path(post_version), method: :put, remote: true, class: "post-version-undo-link" %> |
|
||||
<% end %>
|
||||
<% if post_version.can_revert_to?(CurrentUser.user) %>
|
||||
<%= link_to "Revert to", revert_post_path(post_version.post_id, version_id: post_version.id), method: :put, remote: true %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
|
||||
@@ -4,4 +4,7 @@
|
||||
<%= subnav_link_to "Search", search_post_versions_path %>
|
||||
<%= subnav_link_to "Changes", post_versions_path %>
|
||||
<%= subnav_link_to "Help", wiki_pages_path(:title => "help:posts") %>
|
||||
<% if params[:action] == "index" %>
|
||||
| <%= subnav_link_to "Undo selected", "" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
<table class="striped autofit">
|
||||
<thead>
|
||||
<tr>
|
||||
<% if CurrentUser.user.is_builder? %>
|
||||
<th class="post-version-select-column">
|
||||
<label><input type="checkbox" id="post-version-select-all-checkbox" class="post-version-select-checkbox"></label>
|
||||
</th>
|
||||
<% end %>
|
||||
<th width="5%">Post</th>
|
||||
<th width="15%">Date</th>
|
||||
<th width="10%">User</th>
|
||||
@@ -18,7 +23,12 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @post_versions.each do |post_version| %>
|
||||
<tr id="post-version-<%= post_version.id %>">
|
||||
<tr id="post-version-<%= post_version.id %>" data-post-version-id="<%= post_version.id %>">
|
||||
<% if CurrentUser.user.is_builder? %>
|
||||
<td class="post-version-select-column">
|
||||
<input type="checkbox" class="post-version-select-checkbox" <%= "disabled" unless post_version.can_undo?(CurrentUser.user) %>>
|
||||
</td>
|
||||
<% end %>
|
||||
<td>
|
||||
<%= link_to("#{post_version.post_id}.#{post_version.id}", post_path(post_version.post_id)) %>
|
||||
<%= link_to "»", post_versions_path(search: {post_id: post_version.post_id}) %>
|
||||
@@ -37,18 +47,13 @@
|
||||
</td>
|
||||
<% end %>
|
||||
<td class="col-expand"><%= post_version_diff(post_version) %></td>
|
||||
<% if CurrentUser.is_member? %>
|
||||
<td>
|
||||
<% if post_version.visible? %>
|
||||
<% if post_version.version != 1 %>
|
||||
<%= link_to "Undo", undo_post_version_path(post_version), :method => :put, :remote => true %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</td>
|
||||
<% end %>
|
||||
<td>
|
||||
<% if post_version.can_undo?(CurrentUser.user) %>
|
||||
<%= link_to "Undo", undo_post_version_path(post_version), method: :put, remote: true, class: "post-version-undo-link" %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
location.reload();
|
||||
Danbooru.Utility.notice("1 change undone.");
|
||||
|
||||
33
test/system/post_version_test.rb
Normal file
33
test/system/post_version_test.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
require "application_system_test_case"
|
||||
|
||||
class PostVersionTest < ApplicationSystemTestCase
|
||||
context "Post versions" do
|
||||
setup do
|
||||
@user = create(:builder_user)
|
||||
|
||||
as @user do
|
||||
@post = create(:post, tag_string: "tagme")
|
||||
travel 2.hours
|
||||
@post.update!(tag_string: "touhou")
|
||||
travel 2.hours
|
||||
@post.update!(tag_string: "touhou bkub")
|
||||
travel 2.hours
|
||||
end
|
||||
|
||||
signin @user
|
||||
visit post_versions_path
|
||||
end
|
||||
|
||||
context "clicking the undo selected button" do
|
||||
should "undo all selected post versions" do
|
||||
check id: "post-version-select-all-checkbox"
|
||||
assert all("td .post-version-select-checkbox:not(:disabled)").all?(&:checked?)
|
||||
|
||||
click_link "subnav-undo-selected-link"
|
||||
assert_selector "#notice span.prose", text: "2/2 changes undone."
|
||||
|
||||
assert_equal("tagme", @post.reload.tag_string)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,4 +6,11 @@ module SystemTestHelper
|
||||
fill_in "Password confirmation", with: password
|
||||
click_button "Sign up"
|
||||
end
|
||||
|
||||
def signin(user)
|
||||
visit new_session_path
|
||||
fill_in "Name", with: user.name
|
||||
fill_in "Password", with: user.password
|
||||
click_button "Submit"
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user