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 :member_only, except: [:index, :search]
|
||||||
before_action :check_availabililty
|
before_action :check_availabililty
|
||||||
respond_to :html, :xml, :json
|
respond_to :html, :xml, :json
|
||||||
|
respond_to :js, only: [:undo]
|
||||||
|
|
||||||
def index
|
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])
|
@post_versions = PostArchive.includes(:updater, post: [:versions]).search(search_params).paginate(params[:page], :limit => params[:limit], :search_count => params[:search])
|
||||||
respond_with(@post_versions)
|
respond_with(@post_versions)
|
||||||
end
|
end
|
||||||
@@ -13,14 +15,9 @@ class PostVersionsController < ApplicationController
|
|||||||
|
|
||||||
def undo
|
def undo
|
||||||
@post_version = PostArchive.find(params[:id])
|
@post_version = PostArchive.find(params[:id])
|
||||||
|
@post_version.undo!
|
||||||
|
|
||||||
if @post_version.post.visible?
|
respond_with(@post_version)
|
||||||
@post_version.undo!
|
|
||||||
end
|
|
||||||
|
|
||||||
respond_with(@post_version) do |format|
|
|
||||||
format.js
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
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 Post } from '../src/javascripts/posts.js.erb';
|
||||||
export { default as PostModeMenu } from '../src/javascripts/post_mode_menu.js';
|
export { default as PostModeMenu } from '../src/javascripts/post_mode_menu.js';
|
||||||
export { default as PostTooltip } from '../src/javascripts/post_tooltips.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 RelatedTag } from '../src/javascripts/related_tag.js';
|
||||||
export { default as Shortcuts } from '../src/javascripts/shortcuts.js';
|
export { default as Shortcuts } from '../src/javascripts/shortcuts.js';
|
||||||
export { default as Upload } from '../src/javascripts/uploads.js.erb';
|
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 PostArchive < ApplicationRecord
|
||||||
|
class RevertError < Exception ; end
|
||||||
extend Memoist
|
extend Memoist
|
||||||
|
|
||||||
belongs_to :post
|
belongs_to :post
|
||||||
@@ -218,7 +219,9 @@ class PostArchive < ApplicationRecord
|
|||||||
source.gsub(/^http:\/\//, "").sub(/\/.+/, "")
|
source.gsub(/^http:\/\//, "").sub(/\/.+/, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
def undo
|
def undo!
|
||||||
|
raise RevertError unless post.visible?
|
||||||
|
|
||||||
added = changes[:added_tags] - changes[:obsolete_added_tags]
|
added = changes[:added_tags] - changes[:obsolete_added_tags]
|
||||||
removed = changes[:removed_tags] - changes[:obsolete_removed_tags]
|
removed = changes[:removed_tags] - changes[:obsolete_removed_tags]
|
||||||
|
|
||||||
@@ -239,11 +242,16 @@ class PostArchive < ApplicationRecord
|
|||||||
post.tag_string = "#{post.tag_string} #{tag}".strip
|
post.tag_string = "#{post.tag_string} #{tag}".strip
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
post.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def undo!
|
def can_undo?(user)
|
||||||
undo
|
version > 1 && post&.visible? && user.is_member?
|
||||||
post.save!
|
end
|
||||||
|
|
||||||
|
def can_revert_to?(user)
|
||||||
|
post&.visible? && user.is_member?
|
||||||
end
|
end
|
||||||
|
|
||||||
def updater_name
|
def updater_name
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
<table class="striped autofit">
|
<table class="striped autofit">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<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="5%">Post</th>
|
||||||
<th width="15%">Date</th>
|
<th width="15%">Date</th>
|
||||||
<th width="10%">User</th>
|
<th width="10%">User</th>
|
||||||
@@ -18,7 +23,12 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% @post_versions.each do |post_version| %>
|
<% @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><%= 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><%= compact_time(post_version.updated_at) %></td>
|
||||||
<td>
|
<td>
|
||||||
@@ -34,16 +44,14 @@
|
|||||||
</td>
|
</td>
|
||||||
<% end %>
|
<% end %>
|
||||||
<td class="col-expand"><%= post_version_diff(post_version) %></td>
|
<td class="col-expand"><%= post_version_diff(post_version) %></td>
|
||||||
<% if CurrentUser.is_member? %>
|
<td>
|
||||||
<td>
|
<% if post_version.can_undo?(CurrentUser.user) %>
|
||||||
<% if post_version.visible? %>
|
<%= link_to "Undo", undo_post_version_path(post_version), method: :put, remote: true, class: "post-version-undo-link" %> |
|
||||||
<% if post_version.version != 1 %>
|
<% end %>
|
||||||
<%= link_to "Undo", undo_post_version_path(post_version), :method => :put, :remote => true %> |
|
<% if post_version.can_revert_to?(CurrentUser.user) %>
|
||||||
<% end %>
|
<%= link_to "Revert to", revert_post_path(post_version.post_id, version_id: post_version.id), method: :put, remote: true %>
|
||||||
<%= link_to "Revert to", revert_post_path(post_version.post_id, :version_id => post_version.id), :method => :put, :remote => true %>
|
<% end %>
|
||||||
<% end %>
|
</td>
|
||||||
</td>
|
|
||||||
<% end %>
|
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -4,4 +4,7 @@
|
|||||||
<%= subnav_link_to "Search", search_post_versions_path %>
|
<%= subnav_link_to "Search", search_post_versions_path %>
|
||||||
<%= subnav_link_to "Changes", post_versions_path %>
|
<%= subnav_link_to "Changes", post_versions_path %>
|
||||||
<%= subnav_link_to "Help", wiki_pages_path(:title => "help:posts") %>
|
<%= subnav_link_to "Help", wiki_pages_path(:title => "help:posts") %>
|
||||||
|
<% if params[:action] == "index" %>
|
||||||
|
| <%= subnav_link_to "Undo selected", "" %>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
<table class="striped autofit">
|
<table class="striped autofit">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<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="5%">Post</th>
|
||||||
<th width="15%">Date</th>
|
<th width="15%">Date</th>
|
||||||
<th width="10%">User</th>
|
<th width="10%">User</th>
|
||||||
@@ -18,7 +23,12 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% @post_versions.each do |post_version| %>
|
<% @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>
|
<td>
|
||||||
<%= link_to("#{post_version.post_id}.#{post_version.id}", post_path(post_version.post_id)) %>
|
<%= 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}) %>
|
<%= link_to "»", post_versions_path(search: {post_id: post_version.post_id}) %>
|
||||||
@@ -37,18 +47,13 @@
|
|||||||
</td>
|
</td>
|
||||||
<% end %>
|
<% end %>
|
||||||
<td class="col-expand"><%= post_version_diff(post_version) %></td>
|
<td class="col-expand"><%= post_version_diff(post_version) %></td>
|
||||||
<% if CurrentUser.is_member? %>
|
<td>
|
||||||
<td>
|
<% if post_version.can_undo?(CurrentUser.user) %>
|
||||||
<% if post_version.visible? %>
|
<%= link_to "Undo", undo_post_version_path(post_version), method: :put, remote: true, class: "post-version-undo-link" %>
|
||||||
<% if post_version.version != 1 %>
|
<% end %>
|
||||||
<%= link_to "Undo", undo_post_version_path(post_version), :method => :put, :remote => true %>
|
</td>
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
</td>
|
|
||||||
<% end %>
|
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</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
|
fill_in "Password confirmation", with: password
|
||||||
click_button "Sign up"
|
click_button "Sign up"
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user