forked from e621ng/e621ng
[WikiPages] Implement basic redirects (#683)
This commit is contained in:
parent
852129269b
commit
ba5b6b0fff
@ -55,6 +55,9 @@ class WikiPagesController < ApplicationController
|
||||
end
|
||||
|
||||
if @wiki_page.present?
|
||||
if @wiki_page.parent.present?
|
||||
@wiki_redirect = WikiPage.titled(@wiki_page.parent)
|
||||
end
|
||||
respond_with(@wiki_page)
|
||||
elsif request.format.html?
|
||||
redirect_to show_or_new_wiki_pages_path(title: params[:id])
|
||||
@ -121,6 +124,7 @@ class WikiPagesController < ApplicationController
|
||||
|
||||
def wiki_page_params(context)
|
||||
permitted_params = %i[body skip_secondary_validations edit_reason]
|
||||
permitted_params += %i[parent] if CurrentUser.is_privileged?
|
||||
permitted_params += %i[is_locked is_deleted] if CurrentUser.is_janitor?
|
||||
permitted_params += %i[title] if context == :create || CurrentUser.is_janitor?
|
||||
|
||||
|
@ -77,6 +77,7 @@
|
||||
@import "specific/user_feedback.scss";
|
||||
@import "specific/user_warned.scss";
|
||||
@import "specific/users.scss";
|
||||
@import "specific/wiki_pages.scss";
|
||||
@import "specific/wiki_page_versions.scss";
|
||||
|
||||
@import "common/z_responsive.scss";
|
||||
|
20
app/javascript/src/styles/specific/wiki_pages.scss
Normal file
20
app/javascript/src/styles/specific/wiki_pages.scss
Normal file
@ -0,0 +1,20 @@
|
||||
#c-wiki-pages #a-show,
|
||||
#c-wiki-page-versions {
|
||||
.wiki-page-redirect {
|
||||
margin-left: 1em;
|
||||
color: var(--color-text-muted);
|
||||
& > i {
|
||||
display: inline-flex;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.wiki-redirect-history {
|
||||
color: var(--color-text-muted);
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#wiki-page-body {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
}
|
@ -5,15 +5,17 @@ class WikiPage < ApplicationRecord
|
||||
|
||||
before_validation :normalize_title
|
||||
before_validation :normalize_other_names
|
||||
before_validation :normalize_parent
|
||||
after_save :create_version
|
||||
validates :title, uniqueness: { :case_sensitive => false }
|
||||
validates :title, presence: true
|
||||
validates :title, tag_name: true, if: :title_changed?
|
||||
validates :body, presence: { :unless => -> { is_deleted? || other_names.present? } }
|
||||
validates :body, presence: { unless: -> { is_deleted? || other_names.present? || parent.present? } }
|
||||
validates :title, length: { minimum: 1, maximum: 100 }
|
||||
validates :body, length: { maximum: Danbooru.config.wiki_page_max_size }
|
||||
validate :user_not_limited
|
||||
validate :validate_rename
|
||||
validate :validate_redirect
|
||||
validate :validate_not_locked
|
||||
|
||||
before_destroy :validate_not_used_as_help_page
|
||||
@ -94,6 +96,8 @@ class WikiPage < ApplicationRecord
|
||||
q = q.where("is_deleted = false")
|
||||
end
|
||||
|
||||
q = q.attribute_matches(:parent, params[:parent].try(:tr, " ", "_"))
|
||||
|
||||
if params[:other_names_present].to_s.truthy?
|
||||
q = q.where("other_names is not null and other_names != '{}'")
|
||||
elsif params[:other_names_present].to_s.falsy?
|
||||
@ -169,6 +173,18 @@ class WikiPage < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def validate_redirect
|
||||
return unless will_save_change_to_parent? && parent.present?
|
||||
if WikiPage.find_by(title: parent).blank?
|
||||
errors.add(:parent, "does not exist")
|
||||
return
|
||||
end
|
||||
|
||||
if HelpPage.find_by(wiki_page: title).present?
|
||||
errors.add(:title, "is used as a help page and cannot be redirected")
|
||||
end
|
||||
end
|
||||
|
||||
def revert_to(version)
|
||||
if id != version.wiki_page_id
|
||||
raise RevertError.new("You cannot revert to a previous version of another wiki page.")
|
||||
@ -176,6 +192,7 @@ class WikiPage < ApplicationRecord
|
||||
|
||||
self.title = version.title
|
||||
self.body = version.body
|
||||
self.parent = version.parent
|
||||
self.other_names = version.other_names
|
||||
end
|
||||
|
||||
@ -192,6 +209,10 @@ class WikiPage < ApplicationRecord
|
||||
self.other_names = other_names.map { |name| WikiPage.normalize_other_name(name) }.uniq
|
||||
end
|
||||
|
||||
def normalize_parent
|
||||
self.parent = nil if parent == ""
|
||||
end
|
||||
|
||||
def self.normalize_other_name(name)
|
||||
name.unicode_normalize(:nfkc).gsub(/[[:space:]]+/, " ").strip.tr(" ", "_")
|
||||
end
|
||||
@ -214,19 +235,20 @@ class WikiPage < ApplicationRecord
|
||||
end
|
||||
|
||||
def wiki_page_changed?
|
||||
saved_change_to_title? || saved_change_to_body? || saved_change_to_is_locked? || saved_change_to_is_deleted? || saved_change_to_other_names?
|
||||
saved_change_to_title? || saved_change_to_body? || saved_change_to_is_locked? || saved_change_to_is_deleted? || saved_change_to_other_names? || saved_change_to_parent?
|
||||
end
|
||||
|
||||
def create_new_version
|
||||
versions.create(
|
||||
:updater_id => CurrentUser.user.id,
|
||||
:updater_ip_addr => CurrentUser.ip_addr,
|
||||
:title => title,
|
||||
:body => body,
|
||||
:is_locked => is_locked,
|
||||
:is_deleted => is_deleted,
|
||||
:other_names => other_names,
|
||||
reason: edit_reason
|
||||
updater_id: CurrentUser.user.id,
|
||||
updater_ip_addr: CurrentUser.ip_addr,
|
||||
title: title,
|
||||
body: body,
|
||||
is_locked: is_locked,
|
||||
is_deleted: is_deleted,
|
||||
other_names: other_names,
|
||||
parent: parent,
|
||||
reason: edit_reason,
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -5,6 +5,14 @@
|
||||
<% if @thispage.visible? %>
|
||||
<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>
|
||||
|
||||
<% if @thispage.parent != @otherpage.parent %>
|
||||
<div class="wiki-redirect-history">
|
||||
Page redirect changed
|
||||
from <%= @thispage.parent.blank? ? "none" : link_to(@thispage.parent, show_or_new_wiki_pages_path(title: @thispage.parent)) %>
|
||||
to <%= @otherpage.parent.blank? ? "none" : link_to(@otherpage.parent, show_or_new_wiki_pages_path(title: @otherpage.parent)) %>.
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div>
|
||||
<%= text_diff(@thispage.body, @otherpage.body) %>
|
||||
</div>
|
||||
|
@ -5,6 +5,10 @@
|
||||
<section id="content">
|
||||
<h1 id="wiki-page-title"><%= @wiki_page_version.pretty_title %> <span class="version">(<%= time_ago_in_words_tagged(@wiki_page_version.updated_at) %>)</span></h1>
|
||||
|
||||
<% if @wiki_page_version.parent.present? %>
|
||||
<div class="wiki-page-redirect"><i class="fa-solid fa-turn-up fa-rotate-90"></i> Redirects to <%= link_to @wiki_page_version.parent, show_or_new_wiki_pages_path(title: @wiki_page_version.parent) %></div>
|
||||
<% end %>
|
||||
|
||||
<div id="wiki-page-body" class="dtext dtext-container">
|
||||
<% if @wiki_page_version.visible? %>
|
||||
<%= format_text(@wiki_page_version.body) %>
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
<%= f.input :body, as: :dtext, limit: Danbooru.config.wiki_page_max_size, allow_color: true %>
|
||||
|
||||
<%= f.input :parent, label: "Redirects to", autocomplete: "wiki-page", input_html: { disabled: !CurrentUser.is_privileged? } %>
|
||||
|
||||
<% if CurrentUser.is_janitor? && @wiki_page.is_deleted? %>
|
||||
<%= f.input :is_deleted, :label => "Deleted", :hint => "Uncheck to restore this wiki page" %>
|
||||
<% end %>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<%= f.input :title, label: "Title", hint: "Use * for wildcard searches", autocomplete: "wiki-page" %>
|
||||
<%= f.input :body_matches, label: "Body" %>
|
||||
<%= f.user :creator %>
|
||||
<%= f.input :parent, label: "Redirects to", autocomplete: "wiki-page" %>
|
||||
<%= f.input :other_names_match, label: "Other names", hint: "Use * for wildcard searches" %>
|
||||
<%= f.input :other_names_present, collection: %w[Yes No], include_blank: true %>
|
||||
<%= f.input :hide_deleted, collection: %w[Yes No] %>
|
||||
|
@ -1,3 +1,4 @@
|
||||
<% wiki_content = @wiki_redirect.presence || @wiki_page %>
|
||||
<div id="c-wiki-pages">
|
||||
<div id="a-show">
|
||||
<%= render "sidebar" %>
|
||||
@ -5,38 +6,41 @@
|
||||
<section id="content">
|
||||
<h1 id="wiki-page-title">
|
||||
|
||||
<%= link_to @wiki_page.pretty_title_with_category, posts_path(:tags => @wiki_page.title), :class => "tag-type-#{@wiki_page.category_id}" %>
|
||||
<%= link_to wiki_content.pretty_title_with_category, posts_path(:tags => wiki_content.title), :class => "tag-type-#{wiki_content.category_id}" %>
|
||||
|
||||
<% if @wiki_page.is_locked? %>
|
||||
<% if wiki_content.is_locked? %>
|
||||
(locked)
|
||||
<% end %>
|
||||
|
||||
<% if @wiki_page.is_deleted? %>
|
||||
<% if wiki_content.is_deleted? %>
|
||||
(deleted)
|
||||
<% end %>
|
||||
</h1>
|
||||
<% if @wiki_redirect.present? %>
|
||||
<div class="wiki-page-redirect"><i class="fa-solid fa-turn-up fa-rotate-90"></i> <%= @wiki_page.title %></div>
|
||||
<% end %>
|
||||
|
||||
<div id="wiki-page-body" class="dtext-container">
|
||||
<% if @wiki_page.visible? %>
|
||||
<%= format_text(@wiki_page.body, allow_color: true, max_thumbs: 75) %>
|
||||
<% if wiki_content.visible? %>
|
||||
<%= format_text(wiki_content.body, allow_color: true, max_thumbs: 75) %>
|
||||
|
||||
<% if @wiki_page.artist %>
|
||||
<p><%= link_to "View artist", @wiki_page.artist %></p>
|
||||
<% if wiki_content.artist %>
|
||||
<p><%= link_to "View artist", wiki_content.artist %></p>
|
||||
<% end %>
|
||||
|
||||
<%= wiki_page_alias_and_implication_list(@wiki_page) %>
|
||||
<%= wiki_page_alias_and_implication_list(wiki_content) %>
|
||||
<% else %>
|
||||
<p>This artist has requested removal of their information.</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= wiki_page_post_previews(@wiki_page) %>
|
||||
<%= wiki_page_post_previews(wiki_content) %>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% content_for(:page_title) do %>
|
||||
Wiki - <%= @wiki_page.pretty_title %>
|
||||
Wiki - <%= wiki_content.pretty_title %>
|
||||
<% end %>
|
||||
|
||||
<%= render "secondary_links" %>
|
||||
|
8
db/migrate/20240726170041_add_wiki_page_parent_name.rb
Normal file
8
db/migrate/20240726170041_add_wiki_page_parent_name.rb
Normal file
@ -0,0 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddWikiPageParentName < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :wiki_pages, :parent, :string
|
||||
add_column :wiki_page_versions, :parent, :string
|
||||
end
|
||||
end
|
@ -2316,7 +2316,8 @@ CREATE TABLE public.wiki_page_versions (
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
other_names text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
is_deleted boolean DEFAULT false NOT NULL,
|
||||
reason character varying
|
||||
reason character varying,
|
||||
parent character varying
|
||||
);
|
||||
|
||||
|
||||
@ -2354,7 +2355,8 @@ CREATE TABLE public.wiki_pages (
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
updater_id integer,
|
||||
other_names text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
is_deleted boolean DEFAULT false NOT NULL
|
||||
is_deleted boolean DEFAULT false NOT NULL,
|
||||
parent character varying
|
||||
);
|
||||
|
||||
|
||||
@ -4496,6 +4498,7 @@ ALTER TABLE ONLY public.favorites
|
||||
SET search_path TO "$user", public;
|
||||
|
||||
INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20240726170041'),
|
||||
('20240709134926'),
|
||||
('20240706061122'),
|
||||
('20240101042716'),
|
||||
|
Loading…
Reference in New Issue
Block a user