Merge pull request #4247 from BrokenEagle/pool-version-enhancements
Add pool version enhancements
This commit is contained in:
@@ -12,6 +12,9 @@ class PoolVersionsController < ApplicationController
|
||||
respond_with(@pool_versions)
|
||||
end
|
||||
|
||||
def search
|
||||
end
|
||||
|
||||
def diff
|
||||
@pool_version = PoolArchive.find(params[:id])
|
||||
|
||||
|
||||
@@ -3,4 +3,24 @@ module PoolVersionsHelper
|
||||
params.dig(:search, :pool_id).present? ? :revert : :standard
|
||||
end
|
||||
|
||||
end
|
||||
def pool_version_status_diff(pool_version)
|
||||
cur = pool_version
|
||||
prev = pool_version.previous
|
||||
|
||||
return "New" if prev.blank?
|
||||
|
||||
status = []
|
||||
status += ["Renamed"] if cur.name != prev.name
|
||||
status += ["DescChanged"] if cur.description != prev.description
|
||||
status += ["Deleted"] if cur.is_deleted? && !prev.is_deleted?
|
||||
status += ["Undeleted"] if !cur.is_deleted? && prev.is_deleted?
|
||||
status += ["Activated"] if cur.is_active? && !prev.is_active?
|
||||
status += ["Deactivated"] if !cur.is_active? && prev.is_active?
|
||||
status.join(" ")
|
||||
end
|
||||
|
||||
def pool_page_diff(pool_version, other_version)
|
||||
pattern = Regexp.new('(?:<.+?>)|(?:\w+)|(?:[ \t]+)|(?:\r?\n)|(?:.+?)')
|
||||
DiffBuilder.new(other_version.description, pool_version.description, pattern).build
|
||||
end
|
||||
end
|
||||
@@ -12,59 +12,13 @@ module WikiPageVersionsHelper
|
||||
status.join(" ")
|
||||
end
|
||||
|
||||
def wiki_page_diff(thispage, otherpage)
|
||||
def wiki_other_names_diff(thispage, otherpage)
|
||||
pattern = Regexp.new('\S+|\s+')
|
||||
DiffBuilder.new("#{thispage.other_names}\n\n", "#{otherpage.other_names}\n\n", pattern).build
|
||||
end
|
||||
|
||||
def wiki_body_diff(thispage, otherpage)
|
||||
pattern = Regexp.new('(?:<.+?>)|(?:\w+)|(?:[ \t]+)|(?:\r?\n)|(?:.+?)')
|
||||
other_names_pattern = Regexp.new('\S+|\s+')
|
||||
|
||||
thisarr = thispage.body.scan(pattern)
|
||||
otharr = otherpage.body.scan(pattern)
|
||||
|
||||
if thispage.other_names.present? || otherpage.other_names.present?
|
||||
thisarr = "#{thispage.other_names}\n\n".scan(other_names_pattern) + thisarr
|
||||
otharr = "#{otherpage.other_names}\n\n".scan(other_names_pattern) + otharr
|
||||
end
|
||||
|
||||
cbo = Diff::LCS::ContextDiffCallbacks.new
|
||||
diffs = thisarr.diff(otharr, cbo)
|
||||
|
||||
escape_html = ->(str) {str.gsub(/&/, '&').gsub(/</, '<').gsub(/>/, '>')}
|
||||
|
||||
output = thisarr
|
||||
output.each { |q| q.replace(escape_html[q]) }
|
||||
|
||||
diffs.reverse_each do |hunk|
|
||||
newchange = hunk.max {|a, b| a.old_position <=> b.old_position}
|
||||
newstart = newchange.old_position
|
||||
oldstart = hunk.min {|a, b| a.old_position <=> b.old_position}.old_position
|
||||
|
||||
if newchange.action == '+'
|
||||
output.insert(newstart, '</ins>')
|
||||
end
|
||||
|
||||
hunk.reverse_each do |chg|
|
||||
case chg.action
|
||||
when '-'
|
||||
oldstart = chg.old_position
|
||||
output[chg.old_position] = '<br>' if chg.old_element.match(/^\r?\n$/)
|
||||
when '+'
|
||||
if chg.new_element.match(/^\r?\n$/)
|
||||
output.insert(chg.old_position, '<br>')
|
||||
else
|
||||
output.insert(chg.old_position, (escape_html[chg.new_element]).to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if newchange.action == '+'
|
||||
output.insert(newstart, '<ins>')
|
||||
end
|
||||
|
||||
if hunk[0].action == '-'
|
||||
output.insert((newstart == oldstart || newchange.action != '+') ? newstart + 1 : newstart, '</del>')
|
||||
output.insert(oldstart, '<del>')
|
||||
end
|
||||
end
|
||||
|
||||
output.join.gsub(/\r?\n/, '<br>').html_safe
|
||||
DiffBuilder.new(thispage.body, otherpage.body, pattern).build
|
||||
end
|
||||
end
|
||||
|
||||
17
app/javascript/src/styles/specific/pool_versions.scss
Normal file
17
app/javascript/src/styles/specific/pool_versions.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
div#c-pool-versions {
|
||||
#a-diff {
|
||||
del {
|
||||
background: var(--wiki-page-versions-diff-del-background);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
ins {
|
||||
background: var(--wiki-page-versions-diff-ins-background);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
span.paragraph-mark {
|
||||
opacity: 0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,10 @@ div#c-wiki-page-versions {
|
||||
background: var(--wiki-page-versions-diff-ins-background);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
span.paragraph-mark {
|
||||
opacity: 0.25;
|
||||
}
|
||||
}
|
||||
|
||||
#a-index {
|
||||
|
||||
57
app/logical/diff_builder.rb
Normal file
57
app/logical/diff_builder.rb
Normal file
@@ -0,0 +1,57 @@
|
||||
class DiffBuilder
|
||||
attr_reader :this_text, :that_text, :pattern
|
||||
|
||||
def initialize(this_text, that_text, pattern)
|
||||
@this_text = this_text
|
||||
@that_text = that_text
|
||||
@pattern = pattern
|
||||
end
|
||||
|
||||
def build
|
||||
thisarr = this_text.scan(pattern)
|
||||
otharr = that_text.scan(pattern)
|
||||
|
||||
cbo = Diff::LCS::ContextDiffCallbacks.new
|
||||
diffs = thisarr.diff(otharr, cbo)
|
||||
|
||||
escape_html = ->(str) {str.gsub(/&/, '&').gsub(/</, '<').gsub(/>/, '>')}
|
||||
|
||||
output = thisarr
|
||||
output.each { |q| q.replace(escape_html[q]) }
|
||||
|
||||
diffs.reverse_each do |hunk|
|
||||
newchange = hunk.max {|a, b| a.old_position <=> b.old_position}
|
||||
newstart = newchange.old_position
|
||||
oldstart = hunk.min {|a, b| a.old_position <=> b.old_position}.old_position
|
||||
|
||||
if newchange.action == '+'
|
||||
output.insert(newstart, '</ins>')
|
||||
end
|
||||
|
||||
hunk.reverse_each do |chg|
|
||||
case chg.action
|
||||
when '-'
|
||||
oldstart = chg.old_position
|
||||
output[chg.old_position] = '<span class="paragraph-mark">¶</span><br>' if chg.old_element.match(/^\r?\n$/)
|
||||
when '+'
|
||||
if chg.new_element.match(/^\r?\n$/)
|
||||
output.insert(chg.old_position, '<span class="paragraph-mark">¶</span><br>')
|
||||
else
|
||||
output.insert(chg.old_position, (escape_html[chg.new_element]).to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if newchange.action == '+'
|
||||
output.insert(newstart, '<ins>')
|
||||
end
|
||||
|
||||
if hunk[0].action == '-'
|
||||
output.insert((newstart == oldstart || newchange.action != '+') ? newstart + 1 : newstart, '</del>')
|
||||
output.insert(oldstart, '<del>')
|
||||
end
|
||||
end
|
||||
|
||||
output.join.gsub(/\r?\n/, '<span class="paragraph-mark">¶</span><br>').html_safe
|
||||
end
|
||||
end
|
||||
@@ -21,14 +21,34 @@ class PoolArchive < ApplicationRecord
|
||||
where_array_includes_any(:added_post_ids, [post_id]).or(where_array_includes_any(:removed_post_ids, [post_id]))
|
||||
end
|
||||
|
||||
def name_matches(name)
|
||||
name = normalize_name_for_search(name)
|
||||
name = "*#{name}*" unless name =~ /\*/
|
||||
where_ilike(:name, name)
|
||||
end
|
||||
|
||||
def search(params)
|
||||
q = super
|
||||
q = q.search_attributes(params, :pool_id, :post_ids, :added_post_ids, :removed_post_ids, :updater, :description, :description_changed, :name, :name_changed, :version, :is_active, :is_deleted, :category)
|
||||
q = q.search_attributes(params, :pool_id, :post_ids, :added_post_ids, :removed_post_ids, :updater_id, :description, :description_changed, :name, :name_changed, :version, :is_active, :is_deleted, :category)
|
||||
|
||||
if params[:post_id]
|
||||
q = q.for_post_id(params[:post_id].to_i)
|
||||
end
|
||||
|
||||
if params[:name_matches].present?
|
||||
q = q.name_matches(params[:name_matches])
|
||||
end
|
||||
|
||||
if params[:updater_name].present?
|
||||
q = q.where(updater_id: User.name_to_id(params[:updater_name]))
|
||||
end
|
||||
|
||||
if params[:is_new].to_s.truthy?
|
||||
q = q.where(version: 1)
|
||||
elsif params[:is_new].to_s.falsy?
|
||||
q = q.where("version != 1")
|
||||
end
|
||||
|
||||
q.apply_default_order(params)
|
||||
end
|
||||
end
|
||||
@@ -61,6 +81,14 @@ class PoolArchive < ApplicationRecord
|
||||
sqs_service.send_message(msg, message_group_id: "pool:#{pool.id}")
|
||||
end
|
||||
|
||||
def self.normalize_name(name)
|
||||
name.gsub(/[_[:space:]]+/, "_").gsub(/\A_|_\z/, "")
|
||||
end
|
||||
|
||||
def self.normalize_name_for_search(name)
|
||||
normalize_name(name).mb_chars.downcase
|
||||
end
|
||||
|
||||
def build_diff(other = previous)
|
||||
diff = {}
|
||||
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
<div id="p-<%= pool_versions_listing_type %>-listing">
|
||||
|
||||
<%= table_for @pool_versions, {class: "striped autofit", width: "100%"} do |t| %>
|
||||
<% t.column th: {width: "3%"} do |pool_version| %>
|
||||
<%= link_to_if pool_version.previous.present?, "diff", diff_pool_version_path(pool_version.id) %>
|
||||
<% end %>
|
||||
<% t.column "Pool" do |pool_version| %>
|
||||
<%= link_to pool_version.pretty_name, pool_path(pool_version.pool_id), class: "pool-category-#{pool_version.pool.category}" %>
|
||||
<%= link_to "»", pool_versions_path(search: { pool_id: pool_version.pool_id }), class: "pool-category-#{pool_version.pool.category}" %>
|
||||
<% end %>
|
||||
<% t.column "Changes", td: { class: "col-expand" } do |pool_version| %>
|
||||
<% t.column "Post Changes", td: { class: "col-expand" } do |pool_version| %>
|
||||
<%= render "pool_versions/diff", diff: pool_version.build_diff %>
|
||||
<% end %>
|
||||
<% t.column "Post Count" do |pool_version| %>
|
||||
<%= link_to pool_version.post_ids.size, pool_versions_path(search: { pool_id: pool_version.pool_id }) %>
|
||||
<% end %>
|
||||
<% t.column "Desc Chg" do |pool_version| %>
|
||||
<%= link_to_if pool_version.description_changed, pool_version.description_changed, diff_pool_version_path(pool_version.id) %>
|
||||
<% t.column "Status", td: {class: "col-expand"} do |pool_version| %>
|
||||
<%= pool_version_status_diff(pool_version) %>
|
||||
<% end %>
|
||||
<% t.column "Updater" do |pool_version| %>
|
||||
<% if pool_version.updater %>
|
||||
|
||||
5
app/views/pool_versions/_secondary_links.html.erb
Normal file
5
app/views/pool_versions/_secondary_links.html.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
<% content_for(:secondary_links) do %>
|
||||
<%= quick_search_form_for(:name_matches, pool_versions_path, "pools", autocomplete: "pool") %>
|
||||
<%= subnav_link_to "Listing", pool_versions_path %>
|
||||
<%= subnav_link_to "Search", search_pool_versions_path %>
|
||||
<% end %>
|
||||
@@ -2,20 +2,37 @@
|
||||
<div id="a-diff">
|
||||
<h1>Pool Version Comparison: <%= @pool_version.name %></h1>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Posts</strong>:
|
||||
<%= render "pool_versions/diff", diff: @pool_version.build_diff(@other_version) %>
|
||||
</li>
|
||||
<% if @other_version %>
|
||||
<li><strong>Old Desc</strong>: <%= @other_version.description %></li>
|
||||
<% end %>
|
||||
<li><strong>New Desc</strong>: <%= @pool_version.description %></li>
|
||||
</ul>
|
||||
<% if @other_version.present? %>
|
||||
<p>Showing differences between <%= compact_time @pool_version.updated_at %> (<%= link_to_user @pool_version.updater %>) and <%= compact_time @other_version.updated_at %> (<%= link_to_user @other_version.updater %>)</p>
|
||||
<div>
|
||||
<h2>Name:</h2>
|
||||
<p>
|
||||
<% if @pool_version.name != @other_version.name %>
|
||||
<del><%= @other_version.name %></del> -> <ins><%= @pool_version.name %></ins>
|
||||
<% else %>
|
||||
<%= @pool_version.name %>
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Posts:</h2>
|
||||
<p><%= render "pool_versions/diff", diff: @pool_version.build_diff(@other_version) %></p>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Description:</h2>
|
||||
<p>
|
||||
<% if @pool_version.description != @other_version.description %>
|
||||
<%= pool_page_diff(@pool_version, @other_version) %>
|
||||
<% else %>
|
||||
<i>Unchanged.</i>
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "pools/secondary_links" %>
|
||||
<%= render "secondary_links" %>
|
||||
|
||||
<% content_for(:page_title) do %>
|
||||
Pool Version Comparison - <%= @pool_version.name %> - <%= Danbooru.config.app_name %>
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "pools/secondary_links" %>
|
||||
<%= render "secondary_links" %>
|
||||
|
||||
19
app/views/pool_versions/search.html.erb
Normal file
19
app/views/pool_versions/search.html.erb
Normal file
@@ -0,0 +1,19 @@
|
||||
<div id="c-pool-versions">
|
||||
<div id="a-search">
|
||||
<h1>Search Changes</h1>
|
||||
|
||||
<%= search_form_for(pool_versions_path) do |f| %>
|
||||
<%= f.input :updater_name, label: "Updater", input_html: { value: params.dig(:search, :updater_name), "data-autocomplete": "user" } %>
|
||||
<%= f.input :name_matches, label: "Pool", input_html: { value: params.dig(:search, :name_matches), "data-autocomplete": "pool" } %>
|
||||
<%= f.input :category, label: "Category", collection: [["Series", "series"], ["Collection", "collection"]], include_blank: true %>
|
||||
<%= f.input :is_new, label: "New?", collection: [["Yes", true], ["No", false]], include_blank: true %>
|
||||
<%= f.input :name_changed, label: "Name changed?", collection: [["Yes", true], ["No", false]], include_blank: true %>
|
||||
<%= f.input :description_changed, label: "Description changed?", collection: [["Yes", true], ["No", false]], include_blank: true %>
|
||||
<%= f.input :is_active, label: "Active?", collection: [["Yes", true], ["No", false]], include_blank: true %>
|
||||
<%= f.input :is_banned, label: "Deleted?", collection: [["Yes", true], ["No", false]], include_blank: true %>
|
||||
<%= f.submit "Search" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "secondary_links" %>
|
||||
@@ -7,7 +7,10 @@
|
||||
<p>Showing differences between <%= compact_time @thispage.updated_at %> (<%= link_to_user @thispage.updater %>) and <%= compact_time @otherpage.updated_at %> (<%= link_to_user @otherpage.updater %>)</p>
|
||||
|
||||
<div>
|
||||
<%= wiki_page_diff(@thispage, @otherpage) %>
|
||||
<%= wiki_other_names_diff(@thispage, @otherpage) %>
|
||||
</div>
|
||||
<div>
|
||||
<%= wiki_body_diff(@thispage, @otherpage) %>
|
||||
</div>
|
||||
<% else %>
|
||||
<p>The artist requested removal of this page.</p>
|
||||
|
||||
@@ -191,6 +191,9 @@ Rails.application.routes.draw do
|
||||
member do
|
||||
get :diff
|
||||
end
|
||||
collection do
|
||||
get :search
|
||||
end
|
||||
end
|
||||
resources :post_replacements, :only => [:index, :new, :create, :update]
|
||||
resources :post_votes, only: [:index]
|
||||
|
||||
Reference in New Issue
Block a user