From bb728ecebff35efd525f793e794aed847fc749e9 Mon Sep 17 00:00:00 2001 From: evazion Date: Sun, 11 Sep 2022 17:23:53 -0500 Subject: [PATCH] tags: add /tag_versions page. --- app/controllers/tag_versions_controller.rb | 34 ++++++++ app/helpers/application_helper.rb | 4 +- app/logical/concerns/version_for.rb | 5 ++ app/models/tag_version.rb | 35 ++++++++ app/policies/tag_version_policy.rb | 4 + app/views/static/site_map.html.erb | 3 +- app/views/tag_versions/index.html.erb | 79 +++++++++++++++++++ app/views/tags/_secondary_links.html.erb | 1 + app/views/wiki_pages/_sidebar.html.erb | 3 +- config/routes.rb | 1 + .../tag_versions_controller_test.rb | 53 +++++++++++++ 11 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 app/controllers/tag_versions_controller.rb create mode 100644 app/policies/tag_version_policy.rb create mode 100644 app/views/tag_versions/index.html.erb create mode 100644 test/functional/tag_versions_controller_test.rb diff --git a/app/controllers/tag_versions_controller.rb b/app/controllers/tag_versions_controller.rb new file mode 100644 index 000000000..e822f2d95 --- /dev/null +++ b/app/controllers/tag_versions_controller.rb @@ -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 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c27d2a4c2..8b490a17c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -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) diff --git a/app/logical/concerns/version_for.rb b/app/logical/concerns/version_for.rb index 7e7ba692c..0a8896bbb 100644 --- a/app/logical/concerns/version_for.rb +++ b/app/logical/concerns/version_for.rb @@ -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] }`. diff --git a/app/models/tag_version.rb b/app/models/tag_version.rb index b566ee2d7..fbbbba6f1 100644 --- a/app/models/tag_version.rb +++ b/app/models/tag_version.rb @@ -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 diff --git a/app/policies/tag_version_policy.rb b/app/policies/tag_version_policy.rb new file mode 100644 index 000000000..646c24245 --- /dev/null +++ b/app/policies/tag_version_policy.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class TagVersionPolicy < ApplicationPolicy +end diff --git a/app/views/static/site_map.html.erb b/app/views/static/site_map.html.erb index 24cd35eb4..a3f798f4b 100644 --- a/app/views/static/site_map.html.erb +++ b/app/views/static/site_map.html.erb @@ -48,9 +48,10 @@
  • Tags

  • <%= link_to_wiki "Help", "help:tags" %>
  • <%= link_to_wiki "Cheat sheet", "help:cheatsheet" %>
  • +
  • <%= link_to("Listing", tags_path) %>
  • +
  • <%= link_to("History", tag_versions_path) %>
  • <%= link_to("Aliases", tag_aliases_path) %>
  • <%= link_to("Implications", tag_implications_path) %>
  • -
  • <%= link_to("Listing", tags_path) %>
  • <%= link_to("AI Tags", ai_tags_path) %>
  • <%= link_to("Related Tags", related_tag_path) %>
  • diff --git a/app/views/tag_versions/index.html.erb b/app/views/tag_versions/index.html.erb new file mode 100644 index 000000000..b97d47654 --- /dev/null +++ b/app/views/tag_versions/index.html.erb @@ -0,0 +1,79 @@ +
    +
    + <% if @tag %> +

    Tag History: <%= link_to_search @tag %>

    + <%= link_to "« Back", tag_versions_path, class: "text-xs" %> + <% elsif @updater %> +

    Tag History: <%= link_to_user @updater %>

    + <%= link_to "« Back", tag_versions_path, class: "text-xs" %> + <% else %> +

    Tag History

    + <% 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 %> + +
    + <%= table_for @tag_versions, class: "striped autofit", width: "100%" do |t| %> + <% t.column "Tag" do |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 }) %> + + <% 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 %> +
    + + <%= numbered_paginator(@tag_versions) %> +
    +
    + +<%= render "tags/secondary_links" %> diff --git a/app/views/tags/_secondary_links.html.erb b/app/views/tags/_secondary_links.html.erb index d28e477be..8b5d3f262 100644 --- a/app/views/tags/_secondary_links.html.erb +++ b/app/views/tags/_secondary_links.html.erb @@ -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 %> diff --git a/app/views/wiki_pages/_sidebar.html.erb b/app/views/wiki_pages/_sidebar.html.erb index 11c2035f0..f846b6300 100644 --- a/app/views/wiki_pages/_sidebar.html.erb +++ b/app/views/wiki_pages/_sidebar.html.erb @@ -7,7 +7,8 @@