Merge pull request #3957 from evazion/fix-related-tags
Related tags: build html server-side, eliminate cookies
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
class ArtistUrlsController < ApplicationController
|
||||
respond_to :json, :xml, :html
|
||||
respond_to :js, :json, :xml, :html
|
||||
before_action :member_only, except: [:index]
|
||||
|
||||
def index
|
||||
|
||||
@@ -46,7 +46,6 @@ class PostsController < ApplicationController
|
||||
@post = Post.find(params[:id])
|
||||
|
||||
@post.update(post_params) if @post.visible?
|
||||
save_recent_tags
|
||||
respond_with_post_after_update(@post)
|
||||
end
|
||||
|
||||
@@ -96,15 +95,6 @@ private
|
||||
params[:tags] || (params[:post] && params[:post][:tags])
|
||||
end
|
||||
|
||||
def save_recent_tags
|
||||
if @post
|
||||
tags = Tag.scan_tags(@post.tag_string)
|
||||
tags = (TagAlias.to_aliased(tags) + Tag.scan_tags(cookies[:recent_tags])).uniq.slice(0, 30)
|
||||
cookies[:recent_tags] = tags.join(" ")
|
||||
cookies[:recent_tags_with_categories] = Tag.categories_for(tags).to_a.flatten.join(" ")
|
||||
end
|
||||
end
|
||||
|
||||
def respond_with_post_after_update(post)
|
||||
respond_with(post) do |format|
|
||||
format.html do
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
class RelatedTagsController < ApplicationController
|
||||
respond_to :json
|
||||
respond_to :html, :only=>[:show]
|
||||
respond_to :json, :xml, :js, :html, except: [:update]
|
||||
before_action :require_reportbooru_key, only: [:update]
|
||||
|
||||
def show
|
||||
@query = RelatedTagQuery.new(params[:query].to_s.downcase, params[:category])
|
||||
@query = RelatedTagQuery.new(query: params[:query], category: params[:category], user: CurrentUser.user)
|
||||
respond_with(@query) do |format|
|
||||
format.json do
|
||||
render :json => @query.to_json
|
||||
|
||||
@@ -58,21 +58,11 @@ class UploadsController < ApplicationController
|
||||
flash[:notice] = @service.warnings.join(".\n \n")
|
||||
end
|
||||
|
||||
save_recent_tags
|
||||
respond_with(@upload)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def save_recent_tags
|
||||
if @upload
|
||||
tags = Tag.scan_tags(@upload.tag_string)
|
||||
tags = (TagAlias.to_aliased(tags) + Tag.scan_tags(cookies[:recent_tags])).compact.uniq.slice(0, 30)
|
||||
cookies[:recent_tags] = tags.join(" ")
|
||||
cookies[:recent_tags_with_categories] = Tag.categories_for(tags).to_a.flatten.join(" ")
|
||||
end
|
||||
end
|
||||
|
||||
def upload_params
|
||||
permitted_params = %i[
|
||||
file source tag_string rating status parent_id artist_commentary_title
|
||||
|
||||
@@ -66,8 +66,6 @@ class UsersController < ApplicationController
|
||||
@user = User.find(params[:id])
|
||||
check_privilege(@user)
|
||||
@user.update(user_params(:update))
|
||||
cookies.delete(:favorite_tags)
|
||||
cookies.delete(:favorite_tags_with_categories)
|
||||
if @user.errors.any?
|
||||
flash[:notice] = @user.errors.full_messages.join("; ")
|
||||
else
|
||||
|
||||
@@ -38,7 +38,7 @@ export { default as Note } from '../src/javascripts/notes.js';
|
||||
export { default as Post } from '../src/javascripts/posts.js.erb';
|
||||
export { default as PostModeMenu } from '../src/javascripts/post_mode_menu.js';
|
||||
export { default as PostTooltip } from '../src/javascripts/post_tooltips.js';
|
||||
export { default as RelatedTag } from '../src/javascripts/related_tag.js.erb';
|
||||
export { default as RelatedTag } from '../src/javascripts/related_tag.js';
|
||||
export { default as Shortcuts } from '../src/javascripts/shortcuts.js';
|
||||
export { default as Upload } from '../src/javascripts/uploads.js';
|
||||
export { default as Utility } from '../src/javascripts/utility.js';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import Utility from './utility'
|
||||
import Hammer from 'hammerjs'
|
||||
import RelatedTag from './related_tag.js.erb'
|
||||
import Cookie from './cookie'
|
||||
import Note from './notes'
|
||||
import SavedSearch from './saved_searches'
|
||||
@@ -83,11 +82,6 @@ Post.initialize_edit_dialog = function() {
|
||||
Post.open_edit_dialog();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$("#toggle-related-tags-link").on("click.danbooru", function(e) {
|
||||
RelatedTag.toggle();
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
Post.open_edit_dialog = function() {
|
||||
@@ -99,14 +93,11 @@ Post.open_edit_dialog = function() {
|
||||
$("#comments").hide();
|
||||
$("#post-sections li").removeClass("active");
|
||||
$("#post-edit-link").parent("li").addClass("active");
|
||||
$("#related-tags-container").show();
|
||||
|
||||
var $tag_string = $("#post_tag_string,#upload_tag_string");
|
||||
$("div.input").has($tag_string).prevAll().hide();
|
||||
$("#open-edit-dialog").hide();
|
||||
|
||||
$("#toggle-related-tags-link").show().click();
|
||||
|
||||
var dialog = $("<div/>").attr("id", "edit-dialog");
|
||||
$("#form").appendTo(dialog);
|
||||
dialog.dialog({
|
||||
@@ -158,17 +149,18 @@ Post.open_edit_dialog = function() {
|
||||
|
||||
$tag_string.css({"resize": "none", "width": "100%"});
|
||||
$tag_string.focus().selectEnd().height($tag_string[0].scrollHeight);
|
||||
|
||||
$(document).trigger("danbooru:open-post-edit-dialog");
|
||||
}
|
||||
|
||||
Post.close_edit_dialog = function(e, ui) {
|
||||
$("#form").appendTo($("#c-posts #edit,#c-uploads #a-new"));
|
||||
$("#edit-dialog").remove();
|
||||
RelatedTag.show();
|
||||
$("#toggle-related-tags-link").hide();
|
||||
var $tag_string = $("#post_tag_string,#upload_tag_string");
|
||||
$("div.input").has($tag_string).prevAll().show();
|
||||
$("#open-edit-dialog").show();
|
||||
$tag_string.css({"resize": "", "width": ""});
|
||||
$(document).trigger("danbooru:close-post-edit-dialog");
|
||||
}
|
||||
|
||||
Post.initialize_similar = function() {
|
||||
@@ -434,9 +426,8 @@ Post.initialize_post_sections = function() {
|
||||
$("#edit").show();
|
||||
$("#comments").hide();
|
||||
$("#post_tag_string").focus().selectEnd().height($("#post_tag_string")[0].scrollHeight);
|
||||
$("#related-tags-button").trigger("click");
|
||||
$("#fetch-data-manual").trigger("click");
|
||||
$("#recommended").hide();
|
||||
$(document).trigger("danbooru:open-post-edit-tab");
|
||||
} else if (e.target.hash === "#recommended") {
|
||||
$("#comments").hide();
|
||||
$("#edit").hide();
|
||||
|
||||
148
app/javascript/src/javascripts/related_tag.js
Normal file
148
app/javascript/src/javascripts/related_tag.js
Normal file
@@ -0,0 +1,148 @@
|
||||
import Uploads from './uploads';
|
||||
import Utility from './utility';
|
||||
|
||||
let RelatedTag = {};
|
||||
|
||||
RelatedTag.initialize_all = function() {
|
||||
$(document).on("click.danbooru", ".related-tags-button", RelatedTag.on_click_related_tags_button);
|
||||
$(document).on("click.danbooru", ".related-tags a.search-tag", RelatedTag.toggle_tag);
|
||||
$(document).on("click.danbooru", "#show-related-tags-link", RelatedTag.show);
|
||||
$(document).on("click.danbooru", "#hide-related-tags-link", RelatedTag.hide);
|
||||
$(document).on("keyup.danbooru.relatedTags", "#upload_tag_string, #post_tag_string", RelatedTag.update_selected);
|
||||
|
||||
$(document).on("danbooru:update-source-data", RelatedTag.on_update_source_data);
|
||||
$(document).on("danbooru:open-post-edit-dialog", RelatedTag.hide);
|
||||
$(document).on("danbooru:close-post-edit-dialog", RelatedTag.show);
|
||||
|
||||
// Initialize the recent/favorite/translated/artist tag columns once, the first time the related tags are shown.
|
||||
$(document).one("danbooru:show-related-tags", RelatedTag.initialize_recent_and_favorite_tags);
|
||||
$(document).one("danbooru:show-related-tags", Uploads.fetch_data_manual);
|
||||
|
||||
// Show the related tags automatically when the "Edit" tab is opened, or by default on the uploads page.
|
||||
$(document).on("danbooru:open-post-edit-tab", RelatedTag.show);
|
||||
if ($("#c-uploads #a-new").length) {
|
||||
RelatedTag.show();
|
||||
}
|
||||
}
|
||||
|
||||
RelatedTag.initialize_recent_and_favorite_tags = function(event) {
|
||||
$.get("/related_tag.js", { user_tags: true });
|
||||
}
|
||||
|
||||
RelatedTag.on_click_related_tags_button = function (event) {
|
||||
$.get("/related_tag.js", { query: RelatedTag.current_tag(), category: $(event.target).data("category") });
|
||||
RelatedTag.show();
|
||||
}
|
||||
|
||||
RelatedTag.on_update_source_data = function (event, { related_tags_html }) {
|
||||
$(".source-related-tags-columns").replaceWith(related_tags_html);
|
||||
RelatedTag.update_selected();
|
||||
}
|
||||
|
||||
RelatedTag.current_tag = function() {
|
||||
// 1. abc def | -> def
|
||||
// 2. abc def| -> def
|
||||
// 3. abc de|f -> def
|
||||
// 4. abc |def -> def
|
||||
// 5. abc| def -> abc
|
||||
// 6. ab|c def -> abc
|
||||
// 7. |abc def -> abc
|
||||
// 8. | abc def -> abc
|
||||
|
||||
var $field = $("#upload_tag_string,#post_tag_string");
|
||||
var string = $field.val();
|
||||
var n = string.length;
|
||||
var a = $field.prop('selectionStart');
|
||||
var b = $field.prop('selectionStart');
|
||||
|
||||
if ((a > 0) && (a < (n - 1)) && (!/\s/.test(string[a])) && (/\s/.test(string[a - 1]))) {
|
||||
// 4 is the only case where we need to scan forward. in all other cases we
|
||||
// can drag a backwards, and then drag b forwards.
|
||||
|
||||
while ((b < n) && (!/\s/.test(string[b]))) {
|
||||
b++;
|
||||
}
|
||||
} else if (string.search(/\S/) > b) { // case 8
|
||||
b = string.search(/\S/);
|
||||
while ((b < n) && (!/\s/.test(string[b]))) {
|
||||
b++;
|
||||
}
|
||||
} else {
|
||||
while ((a > 0) && ((/\s/.test(string[a])) || (string[a] === undefined))) {
|
||||
a--;
|
||||
b--;
|
||||
}
|
||||
|
||||
while ((a > 0) && (!/\s/.test(string[a - 1]))) {
|
||||
a--;
|
||||
b--;
|
||||
}
|
||||
|
||||
while ((b < (n - 1)) && (!/\s/.test(string[b]))) {
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
b++;
|
||||
return string.slice(a, b);
|
||||
}
|
||||
|
||||
RelatedTag.update_selected = function(e) {
|
||||
var current_tags = $("#upload_tag_string,#post_tag_string").val().toLowerCase().match(/\S+/g) || [];
|
||||
var $all_tags = $(".related-tags a.search-tag");
|
||||
$all_tags.removeClass("selected");
|
||||
|
||||
$all_tags.each(function(i, tag) {
|
||||
if (current_tags.indexOf(tag.textContent.replace(/ /g, "_")) > -1) {
|
||||
$(tag).addClass("selected");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RelatedTag.tags_include = function(name) {
|
||||
var current = $("#upload_tag_string,#post_tag_string").val().toLowerCase().match(/\S+/g) || [];
|
||||
return $.inArray(name.toLowerCase(), current) > -1;
|
||||
}
|
||||
|
||||
RelatedTag.toggle_tag = function(e) {
|
||||
var $field = $("#upload_tag_string,#post_tag_string");
|
||||
var tag = $(e.target).html().replace(/ /g, "_").replace(/>/g, ">").replace(/</g, "<").replace(/&/g, "&");
|
||||
|
||||
if (RelatedTag.tags_include(tag)) {
|
||||
var escaped_tag = Utility.regexp_escape(tag);
|
||||
$field.val($field.val().replace(new RegExp("(^|\\s)" + escaped_tag + "($|\\s)", "gi"), "$1$2"));
|
||||
} else {
|
||||
$field.val($field.val() + " " + tag);
|
||||
}
|
||||
$field.val($field.val().trim().replace(/ +/g, " ") + " ");
|
||||
|
||||
RelatedTag.update_selected();
|
||||
|
||||
// The timeout is needed on Chrome since it will clobber the field attribute otherwise
|
||||
setTimeout(function () { $field.prop('selectionStart', $field.val().length);}, 100);
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
RelatedTag.show = function(e) {
|
||||
$(document).trigger("danbooru:show-related-tags");
|
||||
$("#related-tags-container").removeClass("hidden").addClass("visible");
|
||||
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
RelatedTag.hide = function(e) {
|
||||
$("#related-tags-container").removeClass("visible").addClass("hidden");
|
||||
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
$(function() {
|
||||
RelatedTag.initialize_all();
|
||||
});
|
||||
|
||||
export default RelatedTag
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
import Upload from './uploads';
|
||||
import Utility from './utility';
|
||||
import Cookie from './cookie';
|
||||
|
||||
let RelatedTag = {};
|
||||
|
||||
RelatedTag.initialize_all = function() {
|
||||
if ($("#c-posts #a-show").length || $("#c-uploads #a-new").length) {
|
||||
this.initialize_buttons();
|
||||
$("#upload_tag_string,#post_tag_string").on("keyup.danbooru.relatedTags", RelatedTag.update_selected);
|
||||
$("#related-tags-container").on("click.danbooru", "#artist-related-tags-column a.del", RelatedTag.disable_artist_url)
|
||||
}
|
||||
}
|
||||
|
||||
RelatedTag.initialize_buttons = function() {
|
||||
this.common_bind("#related-tags-button", "");
|
||||
<% TagCategory.related_button_list.each do |category| %>
|
||||
RelatedTag.common_bind("#related-<%= category %>-button", "<%= category %>"); // eslint-disable-line indent
|
||||
<% end %>
|
||||
}
|
||||
|
||||
RelatedTag.tags_include = function(name) {
|
||||
var current = $("#upload_tag_string,#post_tag_string").val().toLowerCase().match(/\S+/g) || [];
|
||||
return $.inArray(name.toLowerCase(), current) > -1;
|
||||
}
|
||||
|
||||
RelatedTag.common_bind = function(button_name, category) {
|
||||
$(button_name).on("click.danbooru", function(e) {
|
||||
var $dest = $("#related-tags");
|
||||
$dest.empty();
|
||||
RelatedTag.build_recent_and_frequent($dest);
|
||||
$dest.append("<em>Loading...</em>");
|
||||
$.get("/related_tag.json", {
|
||||
"query": RelatedTag.current_tag(),
|
||||
"category": category
|
||||
}, RelatedTag.process_response);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
RelatedTag.current_tag = function() {
|
||||
// 1. abc def | -> def
|
||||
// 2. abc def| -> def
|
||||
// 3. abc de|f -> def
|
||||
// 4. abc |def -> def
|
||||
// 5. abc| def -> abc
|
||||
// 6. ab|c def -> abc
|
||||
// 7. |abc def -> abc
|
||||
// 8. | abc def -> abc
|
||||
|
||||
var $field = $("#upload_tag_string,#post_tag_string");
|
||||
var string = $field.val();
|
||||
var n = string.length;
|
||||
var a = $field.prop('selectionStart');
|
||||
var b = $field.prop('selectionStart');
|
||||
|
||||
if ((a > 0) && (a < (n - 1)) && (!/\s/.test(string[a])) && (/\s/.test(string[a - 1]))) {
|
||||
// 4 is the only case where we need to scan forward. in all other cases we
|
||||
// can drag a backwards, and then drag b forwards.
|
||||
|
||||
while ((b < n) && (!/\s/.test(string[b]))) {
|
||||
b++;
|
||||
}
|
||||
} else if (string.search(/\S/) > b) { // case 8
|
||||
b = string.search(/\S/);
|
||||
while ((b < n) && (!/\s/.test(string[b]))) {
|
||||
b++;
|
||||
}
|
||||
} else {
|
||||
while ((a > 0) && ((/\s/.test(string[a])) || (string[a] === undefined))) {
|
||||
a--;
|
||||
b--;
|
||||
}
|
||||
|
||||
while ((a > 0) && (!/\s/.test(string[a - 1]))) {
|
||||
a--;
|
||||
b--;
|
||||
}
|
||||
|
||||
while ((b < (n - 1)) && (!/\s/.test(string[b]))) {
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
b++;
|
||||
return string.slice(a, b);
|
||||
}
|
||||
|
||||
RelatedTag.process_response = function(data) {
|
||||
RelatedTag.recent_search = data;
|
||||
RelatedTag.build_all();
|
||||
}
|
||||
|
||||
RelatedTag.update_selected = function(e) {
|
||||
var current_tags = $("#upload_tag_string,#post_tag_string").val().toLowerCase().match(/\S+/g) || [];
|
||||
var $all_tags = $("#related-tags a");
|
||||
$all_tags.removeClass("selected");
|
||||
|
||||
$all_tags.each(function(i, tag) {
|
||||
if (current_tags.indexOf(tag.textContent.replace(/ /g, "_")) > -1) {
|
||||
$(tag).addClass("selected");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RelatedTag.build_all = function() {
|
||||
if (RelatedTag.recent_search === null || RelatedTag.recent_search === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
RelatedTag.show();
|
||||
|
||||
var query = RelatedTag.recent_search.query;
|
||||
var related_tags = RelatedTag.recent_search.tags;
|
||||
var wiki_page_tags = RelatedTag.recent_search.wiki_page_tags;
|
||||
var other_wikis = RelatedTag.recent_search.other_wikis;
|
||||
var $dest = $("#related-tags");
|
||||
$dest.empty();
|
||||
|
||||
this.build_recent_and_frequent($dest);
|
||||
|
||||
$dest.append(this.build_html(query, related_tags, "general"));
|
||||
this.build_translated($dest);
|
||||
if (wiki_page_tags.length) {
|
||||
$dest.append(RelatedTag.build_html("wiki:" + query, wiki_page_tags, "wiki"));
|
||||
}
|
||||
$.each(other_wikis, function(i, wiki) {
|
||||
$dest.append(RelatedTag.build_html("wiki:" + wiki.title, wiki.wiki_page_tags, "otherwiki" + i.toString()));
|
||||
});
|
||||
if (RelatedTag.recent_artists) {
|
||||
var tags = [];
|
||||
if (RelatedTag.recent_artists.length === 0) {
|
||||
tags.push([" none", 0]);
|
||||
} else if (RelatedTag.recent_artists.length === 1) {
|
||||
tags.push([RelatedTag.recent_artists[0].name, 1]);
|
||||
if (RelatedTag.recent_artists[0].is_banned === true) {
|
||||
tags.push(["BANNED_ARTIST", "banned"]);
|
||||
}
|
||||
$.each(RelatedTag.recent_artists[0].sorted_urls, function(i, url) {
|
||||
var x = url.url;
|
||||
if (!url.is_active) {
|
||||
x = "-" + x;
|
||||
}
|
||||
tags.push([" " + x, 0]);
|
||||
});
|
||||
} else if (RelatedTag.recent_artists.length >= 10) {
|
||||
tags.push([" none", 0]);
|
||||
} else {
|
||||
$.each(RelatedTag.recent_artists, function(i, artist) {
|
||||
tags.push([artist.name, 1]);
|
||||
});
|
||||
}
|
||||
$dest.append(RelatedTag.build_html("artist", tags, "artist", true));
|
||||
}
|
||||
}
|
||||
|
||||
RelatedTag.build_recent_and_frequent = function($dest) {
|
||||
var recent_tags = Cookie.get("recent_tags_with_categories");
|
||||
var favorite_tags = Cookie.get("favorite_tags_with_categories");
|
||||
if (recent_tags.length) {
|
||||
$dest.append(this.build_html("recent", this.other_tags(recent_tags), "recent"));
|
||||
}
|
||||
if (favorite_tags.length) {
|
||||
$dest.append(this.build_html("frequent", this.other_tags(favorite_tags), "frequent"));
|
||||
}
|
||||
}
|
||||
|
||||
RelatedTag.other_tags = function(string) {
|
||||
if (string && string.length) {
|
||||
return $.map(string.match(/\S+ \d+/g), function(x, i) {
|
||||
var submatch = x.match(/(\S+) (\d+)/);
|
||||
return [[submatch[1], submatch[2]]];
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
RelatedTag.build_translated = function($dest) {
|
||||
if (RelatedTag.translated_tags && RelatedTag.translated_tags.length) {
|
||||
$dest.append(this.build_html("Translated Tags", RelatedTag.translated_tags, "translated"));
|
||||
}
|
||||
}
|
||||
|
||||
RelatedTag.build_html = function(query, related_tags, name, is_wide_column) {
|
||||
if (query === null || query === "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
query = query.replace(/_/g, " ");
|
||||
var header = $("<em/>");
|
||||
|
||||
var match = query.match(/^wiki:(.+)/);
|
||||
if (match) {
|
||||
header.html($("<a/>").attr("href", "/wiki_pages?title=" + encodeURIComponent(match[1])).attr("target", "_blank").text(query));
|
||||
} else {
|
||||
header.text(query);
|
||||
}
|
||||
|
||||
var $div = $("<div/>");
|
||||
$div.attr("id", name + "-related-tags-column");
|
||||
$div.addClass("tag-column");
|
||||
if (is_wide_column) {
|
||||
$div.addClass("wide-column");
|
||||
}
|
||||
var $ul = $("<ul/>");
|
||||
$ul.append(
|
||||
$("<li/>").append(
|
||||
header
|
||||
)
|
||||
);
|
||||
|
||||
$.each(related_tags, function(i, tag) {
|
||||
if (tag[0][0] !== " ") {
|
||||
var $link = $("<a/>");
|
||||
$link.text(tag[0].replace(/_/g, " "));
|
||||
$link.addClass("tag-type-" + tag[1]);
|
||||
$link.attr("href", "/posts?tags=" + encodeURIComponent(tag[0]));
|
||||
$link.on("click.danbooru", RelatedTag.toggle_tag);
|
||||
if (RelatedTag.tags_include(tag[0])) {
|
||||
$link.addClass("selected");
|
||||
}
|
||||
$ul.append(
|
||||
$("<li/>").append($link)
|
||||
);
|
||||
} else {
|
||||
var text = tag[0];
|
||||
var desc = "";
|
||||
if (text.match(/^ -http/)) {
|
||||
text = text.substring(1, 1000);
|
||||
desc = text.replace(/^-https?:\/\//, "");
|
||||
if (desc.length > 30) {
|
||||
desc = desc.substring(0, 30) + "...";
|
||||
}
|
||||
$ul.append(
|
||||
$("<li>").append(
|
||||
$("<del>").text(desc)
|
||||
)
|
||||
);
|
||||
} else if (text.match(/^ http/)) {
|
||||
text = text.substring(1, 1000);
|
||||
desc = text.replace(/^https?:\/\//, "");
|
||||
if (desc.length > 30) {
|
||||
desc = desc.substring(0, 30) + "...";
|
||||
}
|
||||
$ul.append(
|
||||
$("<li>").append([
|
||||
$("<a>").text(desc).attr("href", text).attr("target", "_blank"),
|
||||
" ",
|
||||
$("<a>").attr("href", text).addClass("del").append(
|
||||
$("<i>").addClass("fas fa-minus-circle")
|
||||
)
|
||||
])
|
||||
);
|
||||
} else {
|
||||
$ul.append($("<li/>").text(text));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$div.append($ul);
|
||||
return $div;
|
||||
}
|
||||
|
||||
RelatedTag.toggle_tag = function(e) {
|
||||
var $field = $("#upload_tag_string,#post_tag_string");
|
||||
var tag = $(e.target).html().replace(/ /g, "_").replace(/>/g, ">").replace(/</g, "<").replace(/&/g, "&");
|
||||
|
||||
if (RelatedTag.tags_include(tag)) {
|
||||
var escaped_tag = Utility.regexp_escape(tag);
|
||||
$field.val($field.val().replace(new RegExp("(^|\\s)" + escaped_tag + "($|\\s)", "gi"), "$1$2"));
|
||||
} else {
|
||||
$field.val($field.val() + " " + tag);
|
||||
}
|
||||
$field.val($field.val().trim().replace(/ +/g, " ") + " ");
|
||||
|
||||
RelatedTag.update_selected();
|
||||
|
||||
// The timeout is needed on Chrome since it will clobber the field attribute otherwise
|
||||
setTimeout(function () { $field.prop('selectionStart', $field.val().length);}, 100);
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
RelatedTag.toggle = function() {
|
||||
if ($("#related-tags").is(":visible")) {
|
||||
RelatedTag.hide();
|
||||
} else {
|
||||
RelatedTag.show();
|
||||
$("#related-tags-button").trigger("click");
|
||||
$("#find-artist-button").trigger("click");
|
||||
}
|
||||
}
|
||||
|
||||
RelatedTag.show = function() {
|
||||
$("#related-tags").show()
|
||||
$("#toggle-related-tags-link").text("«");
|
||||
$("#edit-dialog").height("auto");
|
||||
}
|
||||
|
||||
RelatedTag.hide = function() {
|
||||
$("#related-tags").hide();
|
||||
$("#toggle-related-tags-link").text("»");
|
||||
}
|
||||
|
||||
RelatedTag.disable_artist_url = function(e) {
|
||||
var url = e.currentTarget.href;
|
||||
$.each(RelatedTag.recent_artists[0].sorted_urls, function(k, v) {
|
||||
if (v.normalized_url === url || v.url === url) {
|
||||
if (!confirm("This will mark the URL as inactive. Continue?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax("/artist_urls/" + v.id, {
|
||||
method: "PUT",
|
||||
data: {
|
||||
artist_url: {
|
||||
is_active: false
|
||||
}
|
||||
}
|
||||
}).done(Upload.fetch_data_manual);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
$(function() {
|
||||
RelatedTag.initialize_all();
|
||||
});
|
||||
|
||||
export default RelatedTag
|
||||
|
||||
@@ -5,6 +5,7 @@ let Upload = {};
|
||||
Upload.initialize_all = function() {
|
||||
if ($("#c-uploads,#c-posts").length) {
|
||||
this.initialize_enter_on_tags();
|
||||
$("#upload_source").on("change.danbooru", Upload.fetch_data_manual);
|
||||
$(document).on("click.danbooru", "#fetch-data-manual", Upload.fetch_data_manual);
|
||||
}
|
||||
|
||||
@@ -14,10 +15,8 @@ Upload.initialize_all = function() {
|
||||
} else {
|
||||
$("#image").on("load.danbooru error.danbooru", this.initialize_image);
|
||||
}
|
||||
this.initialize_info_bookmarklet();
|
||||
this.initialize_similar();
|
||||
this.initialize_submit();
|
||||
$(() => $("#related-tags-button").click()); // delay so we don't click until button is bound (#3895).
|
||||
|
||||
$("#toggle-artist-commentary").on("click.danbooru", function(e) {
|
||||
Upload.toggle_commentary();
|
||||
@@ -77,11 +76,6 @@ Upload.initialize_similar = function() {
|
||||
});
|
||||
}
|
||||
|
||||
Upload.initialize_info_bookmarklet = function() {
|
||||
$("#upload_source").on("change.danbooru", Upload.fetch_data_manual);
|
||||
$("#fetch-data-manual").click();
|
||||
}
|
||||
|
||||
Upload.update_scale = function() {
|
||||
var $image = $("#image");
|
||||
var ratio = $image.data("scale-factor");
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
div#related-tags-container {
|
||||
padding-right: 2em;
|
||||
|
||||
h1 {
|
||||
font-size: $h3_size;
|
||||
&.visible a#show-related-tags-link,
|
||||
&.hidden a#hide-related-tags-link,
|
||||
&.hidden div.related-tags {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
class RelatedTagQuery
|
||||
attr_reader :query, :category
|
||||
attr_reader :query, :category, :user
|
||||
|
||||
def initialize(query, category = nil)
|
||||
@query = TagAlias.to_aliased(query.strip).join(" ")
|
||||
def initialize(query: nil, category: nil, user: nil)
|
||||
@user = user
|
||||
@query = TagAlias.to_aliased(query.to_s.downcase.strip).join(" ")
|
||||
@category = category
|
||||
end
|
||||
|
||||
def pretty_name
|
||||
query.tr("_", " ")
|
||||
end
|
||||
|
||||
def tags
|
||||
if query =~ /\*/
|
||||
pattern_matching_tags
|
||||
@@ -18,6 +23,21 @@ class RelatedTagQuery
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the top 20 most frequently added tags within the last 20 edits made by the user in the last hour.
|
||||
def recent_tags(since: 1.hour.ago, max_edits: 20, max_tags: 20)
|
||||
return [] unless user.present? && PostArchive.enabled?
|
||||
|
||||
versions = PostArchive.where(updater_id: user.id).where("updated_at > ?", since).order(id: :desc).limit(max_edits)
|
||||
tags = versions.flat_map(&:added_tags)
|
||||
tags = tags.reject { |tag| Tag.is_metatag?(tag) }
|
||||
tags = tags.group_by(&:itself).transform_values(&:size).sort_by { |tag, count| [-count, tag] }.map(&:first)
|
||||
tags.take(max_tags)
|
||||
end
|
||||
|
||||
def favorite_tags
|
||||
user&.favorite_tags.to_s.split
|
||||
end
|
||||
|
||||
def wiki_page_tags
|
||||
results = wiki_page.try(:tags) || []
|
||||
results.reject! do |name|
|
||||
@@ -27,17 +47,12 @@ class RelatedTagQuery
|
||||
end
|
||||
|
||||
def other_wiki_category_tags
|
||||
if Tag.category_for(query) != Tag.categories.copyright
|
||||
return []
|
||||
end
|
||||
listtags = (wiki_page.try(:tags) || []).select {|name| name =~ /^list_of_/i }
|
||||
results = listtags.map do |name|
|
||||
listlinks = WikiPage.titled(name).first.try(:tags) || []
|
||||
if listlinks.length > 0
|
||||
{"title" => name, "wiki_page_tags" => map_with_category_data(listlinks)}
|
||||
end
|
||||
end
|
||||
results.reject {|list| list.nil?}
|
||||
return [] unless Tag.category_for(query) == Tag.categories.copyright
|
||||
|
||||
other_wikis = wiki_page&.tags.to_a.grep(/^list_of_/i)
|
||||
other_wikis = other_wikis.map { |name| WikiPage.titled(name).first }
|
||||
other_wikis = other_wikis.select { |wiki| wiki.tags.present? }
|
||||
other_wikis
|
||||
end
|
||||
|
||||
def tags_for_html
|
||||
|
||||
@@ -28,7 +28,6 @@ class SessionLoader
|
||||
update_last_logged_in_at
|
||||
update_last_ip_addr
|
||||
set_time_zone
|
||||
store_favorite_tags_in_cookies
|
||||
CurrentUser.user.unban! if CurrentUser.user.ban_expired?
|
||||
end
|
||||
|
||||
@@ -92,14 +91,6 @@ private
|
||||
cookies[:password_hash] && cookies.signed[:user_name] && User.authenticate_cookie_hash(cookies.signed[:user_name], cookies[:password_hash])
|
||||
end
|
||||
|
||||
def store_favorite_tags_in_cookies
|
||||
if (cookies[:favorite_tags].blank? || cookies[:favorite_tags_with_categories].blank?) && CurrentUser.user.favorite_tags.present?
|
||||
favorite_tags = CurrentUser.user.favorite_tags.slice(0, 1024)
|
||||
cookies[:favorite_tags] = favorite_tags
|
||||
cookies[:favorite_tags_with_categories] = Tag.categories_for(favorite_tags.split(/[[:space:]]+/)).to_a.flatten.join(" ")
|
||||
end
|
||||
end
|
||||
|
||||
def update_last_logged_in_at
|
||||
return if CurrentUser.is_anonymous?
|
||||
return if CurrentUser.last_logged_in_at && CurrentUser.last_logged_in_at > 1.week.ago
|
||||
|
||||
1
app/views/artist_urls/update.js
Normal file
1
app/views/artist_urls/update.js
Normal file
@@ -0,0 +1 @@
|
||||
Danbooru.Upload.fetch_data_manual();
|
||||
@@ -82,20 +82,12 @@
|
||||
<span id="open-edit-dialog" class="ui-icon ui-icon-arrow-1-ne" title="detach" style="display: none;" data-shortcut="shift+e"/>
|
||||
</div>
|
||||
|
||||
<%= button_tag "Related tags", :id => "related-tags-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
|
||||
|
||||
<% TagCategory.related_button_list.each do |category| %>
|
||||
<%= button_tag "#{TagCategory.related_button_mapping[category]}", :id => "related-#{category}-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
|
||||
<% end %>
|
||||
<%= render "related_tags/buttons" %>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<%= submit_tag "Submit", :class => "ui-button ui-widget ui-corner-all" %>
|
||||
</div>
|
||||
|
||||
<div id="related-tags-container">
|
||||
<h1>Related Tags <a href="#" id="toggle-related-tags-link" style="display: none;">«</a></h1>
|
||||
<div id="related-tags" class="related-tags">
|
||||
</div>
|
||||
</div>
|
||||
<%= render "related_tags/container" %>
|
||||
<% end %>
|
||||
|
||||
5
app/views/related_tags/_buttons.html.erb
Normal file
5
app/views/related_tags/_buttons.html.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
<%= button_tag "Related tags", type: :button, class: "related-tags-button ui-button ui-widget ui-corner-all sub gradient" %>
|
||||
|
||||
<% TagCategory.related_button_list.each do |category| %>
|
||||
<%= button_tag TagCategory.related_button_mapping[category], type: :button, "data-category": category, class: "related-tags-button ui-button ui-widget ui-corner-all sub gradient" %>
|
||||
<% end %>
|
||||
13
app/views/related_tags/_container.html.erb
Normal file
13
app/views/related_tags/_container.html.erb
Normal file
@@ -0,0 +1,13 @@
|
||||
<div id="related-tags-container" class="visible">
|
||||
<h3>
|
||||
Related Tags
|
||||
<a href="#" id="show-related-tags-link">»</a>
|
||||
<a href="#" id="hide-related-tags-link">«</a>
|
||||
</h3>
|
||||
|
||||
<div class="related-tags">
|
||||
<%= render "related_tags/user_tags", related_tags: nil %>
|
||||
<%= render "related_tags/current_tags", related_tags: nil %>
|
||||
<%= render "related_tags/source_tags", source: nil %>
|
||||
</div>
|
||||
</div>
|
||||
10
app/views/related_tags/_current_tags.html.erb
Normal file
10
app/views/related_tags/_current_tags.html.erb
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="current-related-tags-columns">
|
||||
<% if related_tags.present? %>
|
||||
<%= render "related_tags/tag_column", tags: related_tags.tags, class: "general-related-tags-column", title: related_tags.pretty_name %>
|
||||
<%= render "related_tags/tag_column", tags: related_tags.wiki_page_tags, class: "wiki-related-tags-column", title: link_to("wiki:#{related_tags.pretty_name}", show_or_new_wiki_pages_path(title: related_tags.query)) %>
|
||||
|
||||
<% related_tags.other_wiki_category_tags.each do |wiki| %>
|
||||
<%= render "related_tags/tag_column", tags: wiki.tags, class: "other-wiki-related-tags-column", title: link_to("wiki:#{wiki.pretty_title}", show_or_new_wiki_pages_path(title: wiki.title)) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
34
app/views/related_tags/_source_tags.html.erb
Normal file
34
app/views/related_tags/_source_tags.html.erb
Normal file
@@ -0,0 +1,34 @@
|
||||
<div class="source-related-tags-columns">
|
||||
<% if source.present? %>
|
||||
<%= render "related_tags/tag_column", tags: source.translated_tags.map(&:first), title: "Translated Tags" %>
|
||||
|
||||
<div class="tag-column wide-column artist-related-tags-column">
|
||||
<h6>Artist</h6>
|
||||
|
||||
<% if source.artists.size == 0 %>
|
||||
none
|
||||
<% else %>
|
||||
<% if source.artists.any?(&:is_banned?) %>
|
||||
<%= TagSetPresenter.new(["banned_artist"]).tag_list_html(name_only: true) %>
|
||||
<% end %>
|
||||
|
||||
<% source.artists.each do |artist| %>
|
||||
<%= TagSetPresenter.new([artist.name]).tag_list_html(name_only: true) %>
|
||||
|
||||
<ul>
|
||||
<% artist.sorted_urls.each do |url| %>
|
||||
<li>
|
||||
<% if url.is_active %>
|
||||
<%= external_link_to url.url, truncate: 30 %>
|
||||
<%= link_to tag.i(class: "fas fa-minus-circle"), artist_url_path(id: url.id, artist_url: { is_active: false }), remote: true, method: :put, "data-confirm": "This will mark the URL as inactive. Continue?" %>
|
||||
<% else %>
|
||||
<del><%= truncate(url.url, length: 30) %></del>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
8
app/views/related_tags/_tag_column.html.erb
Normal file
8
app/views/related_tags/_tag_column.html.erb
Normal file
@@ -0,0 +1,8 @@
|
||||
<%# tags, title, class (optional) %>
|
||||
|
||||
<div class="tag-column <%= local_assigns[:class] || "#{title.parameterize}-related-tags-column" %>">
|
||||
<% if tags.present? %>
|
||||
<h6><%= title %></h6>
|
||||
<%= TagSetPresenter.new(tags).tag_list_html(name_only: true) %>
|
||||
<% end %>
|
||||
</div>
|
||||
6
app/views/related_tags/_user_tags.html.erb
Normal file
6
app/views/related_tags/_user_tags.html.erb
Normal file
@@ -0,0 +1,6 @@
|
||||
<div class="user-related-tags-columns">
|
||||
<% if related_tags.present? %>
|
||||
<%= render "related_tags/tag_column", tags: related_tags.recent_tags, title: "Recent" %>
|
||||
<%= render "related_tags/tag_column", tags: related_tags.favorite_tags, title: "Frequent" %>
|
||||
<% end %>
|
||||
</div>
|
||||
7
app/views/related_tags/show.js.erb
Normal file
7
app/views/related_tags/show.js.erb
Normal file
@@ -0,0 +1,7 @@
|
||||
<% if params[:user_tags] %>
|
||||
$(".user-related-tags-columns").replaceWith("<%= j render "user_tags", related_tags: @query %>");
|
||||
<% else %>
|
||||
$(".current-related-tags-columns").replaceWith("<%= j render "current_tags", related_tags: @query %>");
|
||||
<% end %>
|
||||
|
||||
Danbooru.RelatedTag.update_selected();
|
||||
@@ -1,8 +1,9 @@
|
||||
$("#source-info").replaceWith("<%= j render "info", source: @source %>");
|
||||
|
||||
Danbooru.RelatedTag.recent_artists = <%= raw @source.artists.to_json(include: :sorted_urls) %>;
|
||||
Danbooru.RelatedTag.translated_tags = <%= raw @source.translated_tags.to_json %>;
|
||||
Danbooru.RelatedTag.build_all();
|
||||
$(document).trigger("danbooru:update-source-data", {
|
||||
source: <%= raw @source.to_json %>,
|
||||
related_tags_html: "<%= j render "related_tags/source_tags", source: @source %>",
|
||||
});
|
||||
|
||||
if ($("#c-uploads #a-new").length) {
|
||||
$("#upload_artist_commentary_title").val(<%= raw @source.dtext_artist_commentary_title.to_json %>);
|
||||
|
||||
@@ -97,22 +97,14 @@
|
||||
<span id="open-edit-dialog" class="ui-icon ui-icon-arrow-1-ne" title="detach" style="display: none;" data-shortcut="shift+e"/>
|
||||
</div>
|
||||
|
||||
<%= button_tag "Related tags", :id => "related-tags-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
|
||||
|
||||
<% TagCategory.related_button_list.each do |category| %>
|
||||
<%= button_tag "#{TagCategory.related_button_mapping[category]}", :id => "related-#{category}-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
|
||||
<% end %>
|
||||
<%= render "related_tags/buttons" %>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<%= submit_tag "Submit", :id => "submit-button", :class => "large ui-button ui-widget ui-corner-all gradient", data: {disable_with: false} %>
|
||||
</div>
|
||||
|
||||
<div id="related-tags-container">
|
||||
<h1>Related Tags <a href="#" id="toggle-related-tags-link" style="display: none;">«</a></h1>
|
||||
<div id="related-tags" class="related-tags">
|
||||
</div>
|
||||
</div>
|
||||
<%= render "related_tags/container" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<h2 style="margin-bottom: 1em;">You <%= CurrentUser.user.upload_limited_reason %></h2>
|
||||
|
||||
Reference in New Issue
Block a user