tags: add /tag_versions page.

This commit is contained in:
evazion
2022-09-11 17:23:53 -05:00
parent 54a45a3021
commit bb728ecebf
11 changed files with 218 additions and 4 deletions

View File

@@ -0,0 +1,34 @@
# frozen_string_literal: true
class TagVersionsController < ApplicationController
respond_to :html, :xml, :json
def index
tag_id = params[:tag_id] || params[:search][:tag_id]
tag_name = params[:search][:name_matches]
updater_id = params[:updater_id] || params[:search][:updater_id]
updater_name = params[:search][:updater_name]
@tag = Tag.find(tag_id) if tag_id
@tag = Tag.find_by_name(tag_name) if tag_name
@updater = User.find(updater_id) if updater_id
@updater = User.find_by_name(updater_name) if updater_name
if request.format.html?
@tag_versions = authorize TagVersion.visible(CurrentUser.user).paginated_search(params, defaults: { tag_id: @tag&.id, updater_id: @updater&.id, order: "updated_at" }, count_pages: true)
@tag_versions = @tag_versions.includes(:tag, :updater, :previous_version)
else
@tag_versions = authorize TagVersion.visible(CurrentUser.user).paginated_search(params, defaults: { tag_id: @tag&.id, updater_id: @updater&.id })
end
respond_with(@tag_versions)
end
def show
@tag_version = authorize TagVersion.find(params[:id])
respond_with(@tag_version) do |format|
format.html { redirect_to tag_versions_path(search: { id: @tag_version.id }) }
end
end
end

View File

@@ -198,8 +198,8 @@ module ApplicationHelper
link_to ip_addr.to_s, ip_addresses_path(search: { ip_addr: ip, group_by: "user" }), **options
end
def link_to_search(search)
link_to search, posts_path(tags: search)
def link_to_search(tag, **options)
link_to tag.name, posts_path(tags: tag.name), class: tag_class(tag), **options
end
def link_to_wiki(text, title = text, **options)

View File

@@ -78,6 +78,11 @@ module VersionFor
previous_version.nil?
end
# True if this version was updated after it was created (it was a merged edit).
def revised?
updated_at > created_at
end
# Return a hash of changes made by this edit (compared to the previous version, or to another version).
#
# The hash looks like `{ attr => [old_value, new_value] }`.

View File

@@ -4,4 +4,39 @@ class TagVersion < ApplicationRecord
include VersionFor
version_for :tag
def self.name_matches(name)
where_like(:name, Tag.normalize_name(name))
end
def self.search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :version, :name, :category, :is_deprecated, :tag, :updater, :previous_version)
if params[:name_matches].present?
q = q.name_matches(params[:name_matches])
end
case params[:order]
when "created_at", "created_at_desc"
q = q.order(created_at: :desc, id: :desc)
when "created_at_asc"
q = q.order(created_at: :asc, id: :asc)
when "updated_at", "updated_at_desc"
q = q.order(updated_at: :desc, id: :desc)
when "updated_at_asc"
q = q.order(updated_at: :asc, id: :asc)
when "id", "id_desc"
q = q.order(id: :desc)
when "id_asc"
q = q.order(id: :asc)
else
q = q.apply_default_order(params)
end
q
end
def category_name
TagCategory.reverse_mapping[category].capitalize
end
end

View File

@@ -0,0 +1,4 @@
# frozen_string_literal: true
class TagVersionPolicy < ApplicationPolicy
end

View File

@@ -48,9 +48,10 @@
<li><h2>Tags</h2></li>
<li><%= link_to_wiki "Help", "help:tags" %></li>
<li><%= link_to_wiki "Cheat sheet", "help:cheatsheet" %></li>
<li><%= link_to("Listing", tags_path) %></li>
<li><%= link_to("History", tag_versions_path) %></li>
<li><%= link_to("Aliases", tag_aliases_path) %></li>
<li><%= link_to("Implications", tag_implications_path) %></li>
<li><%= link_to("Listing", tags_path) %></li>
<li><%= link_to("AI Tags", ai_tags_path) %></li>
<li><%= link_to("Related Tags", related_tag_path) %></li>
</ul>

View File

@@ -0,0 +1,79 @@
<div id="c-tag-versions">
<div id="a-index">
<% if @tag %>
<h1>Tag History: <%= link_to_search @tag %></h1>
<%= link_to "« Back", tag_versions_path, class: "text-xs" %>
<% elsif @updater %>
<h1>Tag History: <%= link_to_user @updater %></h1>
<%= link_to "« Back", tag_versions_path, class: "text-xs" %>
<% else %>
<h1>Tag History</h1>
<% end %>
<%= search_form_for(tag_versions_path) do |f| %>
<%= f.input :name_matches, label: "Tag", input_html: { value: @tag&.name, "data-autocomplete": "tag" } %>
<%= f.input :updater_name, label: "User", input_html: { value: @updater&.name, "data-autocomplete": "user" } %>
<%= f.input :order, collection: [%w[Newest updated_at], %w[Oldest updated_at_asc]], include_blank: true, selected: params[:search][:order] %>
<%= f.submit "Search" %>
<% end %>
<div id="p-<%= listing_type(:tag_id, :updater_id) %>-listing" class="mt-4">
<%= table_for @tag_versions, class: "striped autofit", width: "100%" do |t| %>
<% t.column "Tag" do |tag_version| %>
<span class="<%= tag_class(tag_version) %>">
<%= link_to_wiki "?", tag_version.tag.name %>
<%= link_to tag_version.tag.name, posts_path(tags: tag_version.tag.name) %>
<%= link_to "»", tag_versions_path(search: { tag_id: tag_version.tag_id }) %>
</span>
<% end %>
<% t.column "Change", td: { class: "col-expand" } do |tag_version| %>
<% if tag_version.first_version? && tag_version.created_at - tag_version.tag.created_at < 1.minute %>
Anonymous created <%= link_to_search tag_version %>.
<% elsif tag_version.first_version? %>
Anonymous updated <%= link_to_search tag_version %>.
<% else %>
<% if !tag_version.previous_version.is_deprecated? && tag_version.is_deprecated? %>
<%= link_to_user tag_version.updater %> deprecated <%= link_to_search tag_version %>.
<% elsif tag_version.previous_version.is_deprecated? && !tag_version.is_deprecated? %>
<%= link_to_user tag_version.updater %> undeprecated <%= link_to_search tag_version %>.
<% end %>
<% if tag_version.previous_version.category != tag_version.category %>
<%= link_to_user tag_version.updater %> changed <%= link_to_search tag_version %> from <%= tag_version.previous_version.category_name.downcase %> to <%= tag_version.category_name.downcase %>.
<% end %>
<% end %>
<% end %>
<% t.column "Date" do |tag_version| %>
<%= time_ago_in_words_tagged(tag_version.updated_at) %>
<% end %>
<% t.column "User" do |tag_version| %>
<%= link_to_user tag_version.updater %>
<%= link_to "»", tag_versions_path(search: { **search_params, updater_id: tag_version.updater_id }) %>
<% end %>
<% t.column column: "control" do |tag_version| %>
<%= render PopupMenuComponent.new do |menu| %>
<% if policy(tag_version.tag).update? %>
<% menu.item do %>
<%= link_to "Edit tag", edit_tag_path(tag_version.tag) %>
<% end %>
<% end %>
<% unless @tag %>
<% menu.item do %>
<%= link_to "Tag history", tag_versions_path(search: { tag_id: tag_version.tag_id }) %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
</div>
<%= numbered_paginator(@tag_versions) %>
</div>
</div>
<%= render "tags/secondary_links" %>

View File

@@ -1,6 +1,7 @@
<% content_for(:secondary_links) do %>
<%= quick_search_form_for(:name_matches, tags_path, "tags", autocomplete: "tag") %>
<%= subnav_link_to "Tags", tags_path %>
<%= subnav_link_to "History", tag_versions_path %>
<%= subnav_link_to("Aliases", tag_aliases_path) %>
<%= subnav_link_to("Implications", tag_implications_path) %>
<%= subnav_link_to "Request alias/implication", new_bulk_update_request_path %>

View File

@@ -7,7 +7,8 @@
<ul>
<% unless @wiki_page.is_meta_wiki? %>
<li><%= link_to "Tag History", post_versions_path(search: { changed_tags: @wiki_page.title }) %></li>
<li><%= link_to "Tag History", tag_versions_path(search: { tag_id: @wiki_page.tag.id }) %></li>
<li><%= link_to "Post History", post_versions_path(search: { changed_tags: @wiki_page.title }) %></li>
<% end %>
<li><%= link_to "Wiki History", wiki_page_versions_path(search: { wiki_page_id: @wiki_page.id }) %></li>
<% if Danbooru.config.forum_enabled?.to_s.truthy? %>

View File

@@ -251,6 +251,7 @@ Rails.application.routes.draw do
resources :tags
resources :tag_aliases, only: [:show, :index, :destroy]
resources :tag_implications, only: [:show, :index, :destroy]
resources :tag_versions, only: [:index, :show]
get "/redeem", to: "upgrade_codes#redeem", as: "redeem_upgrade_codes"
resources :upgrade_codes, only: [:create, :index] do

View File

@@ -0,0 +1,53 @@
require 'test_helper'
class TagVersionsControllerTest < ActionDispatch::IntegrationTest
context "The tag versions controller" do
context "index action" do
setup do
@user = create(:user)
@tag = create(:tag, name: "test", created_at: 6.months.ago, updated_at: 3.months.ago)
travel_to(4.hours.ago) { @tag.update!(category: Tag.categories.character, updater: @user) }
travel_to(3.hours.ago) { @tag.update!(is_deprecated: true, updater: @user) }
travel_to(2.hours.ago) { @tag.update!(is_deprecated: false, updater: @user) }
end
should "render" do
get tag_versions_path
assert_response :success
end
should "render for a tag" do
get tag_versions_path(search: { name_matches: @tag.name })
assert_response :success
end
should "render for a user" do
get tag_versions_path(search: { updater_id: @user.id })
assert_response :success
end
should "render for a json response" do
get tag_versions_path, as: :json
assert_response :success
end
end
context "show action" do
setup do
@user = create(:user)
@tag = create(:tag)
@tag.update!(category: Tag.categories.character, updater: @user)
end
should "render" do
get tag_version_path(@tag.versions.last)
assert_redirected_to tag_versions_path(search: { id: @tag.versions.last.id })
end
should "render for a json response" do
get tag_version_path(@tag.versions.last), as: :json
assert_response :success
end
end
end
end