forked from e621ng/e621ng
Remove saved searches
This commit is contained in:
parent
66ab994b25
commit
160b0cb22e
@ -1,60 +0,0 @@
|
||||
class SavedSearchesController < ApplicationController
|
||||
before_action :check_availability
|
||||
respond_to :html, :xml, :json, :js
|
||||
|
||||
def index
|
||||
@saved_searches = saved_searches.order("id")
|
||||
|
||||
if params[:label]
|
||||
@saved_searches = saved_searches.labeled(params[:label])
|
||||
end
|
||||
|
||||
respond_with(@saved_searches) do |format|
|
||||
format.xml do
|
||||
render :xml => @saved_searches.to_xml(:root => "saved-searches")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def labels
|
||||
@labels = SavedSearch.search_labels(CurrentUser.id, params[:search])
|
||||
respond_with(@labels)
|
||||
end
|
||||
|
||||
def create
|
||||
@saved_search = saved_searches.create(saved_search_params)
|
||||
respond_with(@saved_search)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@saved_search = saved_searches.find(params[:id])
|
||||
@saved_search.destroy
|
||||
respond_with(@saved_search)
|
||||
end
|
||||
|
||||
def edit
|
||||
@saved_search = saved_searches.find(params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
@saved_search = saved_searches.find(params[:id])
|
||||
@saved_search.update(saved_search_params)
|
||||
respond_with(@saved_search, :location => saved_searches_path)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def saved_searches
|
||||
CurrentUser.user.saved_searches
|
||||
end
|
||||
|
||||
def check_availability
|
||||
if !SavedSearch.enabled?
|
||||
raise NotImplementedError.new("Saved searches are not available.")
|
||||
end
|
||||
end
|
||||
|
||||
def saved_search_params
|
||||
params.fetch(:saved_search, {}).permit(%i[query label_string])
|
||||
end
|
||||
end
|
@ -1,5 +1,4 @@
|
||||
import Utility from './utility'
|
||||
import SavedSearch from './saved_searches'
|
||||
|
||||
let Autocomplete = {};
|
||||
|
||||
@ -152,9 +151,6 @@ Autocomplete.initialize_tag_autocomplete = function() {
|
||||
case "ordpool":
|
||||
Autocomplete.pool_source(term, resp, metatag);
|
||||
break;
|
||||
case "search":
|
||||
Autocomplete.saved_search_source(term, resp);
|
||||
break;
|
||||
default:
|
||||
Autocomplete.normal_source(term, resp);
|
||||
break;
|
||||
@ -482,17 +478,6 @@ Autocomplete.pool_source = function(term, resp, metatag) {
|
||||
});
|
||||
}
|
||||
|
||||
Autocomplete.saved_search_source = function(term, resp) {
|
||||
return SavedSearch.labels(term).then(function(labels) {
|
||||
resp(labels.map(function(label) {
|
||||
return {
|
||||
label: label.replace(/_/g, " "),
|
||||
value: "search:" + label,
|
||||
};
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
Autocomplete.initialize_all();
|
||||
});
|
||||
|
@ -2,7 +2,6 @@ import Utility from './utility'
|
||||
import Hammer from 'hammerjs'
|
||||
import LS from './local_storage'
|
||||
import Note from './notes'
|
||||
import SavedSearch from './saved_searches'
|
||||
import { SendQueue } from './send_queue'
|
||||
|
||||
let Post = {};
|
||||
@ -14,7 +13,6 @@ Post.initialize_all = function() {
|
||||
|
||||
if ($("#c-posts").length) {
|
||||
this.initialize_shortcuts();
|
||||
this.initialize_saved_searches();
|
||||
}
|
||||
|
||||
if ($("#c-posts").length && $("#a-index").length) {
|
||||
@ -43,10 +41,6 @@ Post.initialize_all = function() {
|
||||
var $fields_multiple = $('[data-autocomplete="tag-edit"]');
|
||||
$fields_multiple.on("keypress.danbooru", Post.update_tag_count);
|
||||
$fields_multiple.on("click", Post.update_tag_count);
|
||||
|
||||
$(window).on('danbooru:initialize_saved_seraches', () => {
|
||||
Post.initialize_saved_searches();
|
||||
});
|
||||
}
|
||||
|
||||
Post.initialize_voting = function() {
|
||||
@ -675,53 +669,6 @@ Post.approve = function(post_id) {
|
||||
});
|
||||
}
|
||||
|
||||
Post.initialize_saved_searches = function() {
|
||||
$("#new_saved_search #saved_search_label_string").autocomplete({
|
||||
search: function() {
|
||||
$(this).data("ui-autocomplete").menu.bindings = $();
|
||||
},
|
||||
source: function(req, resp) {
|
||||
SavedSearch.labels(req.term).then(function(labels) {
|
||||
resp(labels.map(function(label) {
|
||||
return {
|
||||
label: label.replace(/_/g, " "),
|
||||
value: label
|
||||
};
|
||||
}));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#save-search-dialog").dialog({
|
||||
width: 500,
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
buttons: {
|
||||
"Submit": function() {
|
||||
$("#save-search-dialog form").submit();
|
||||
$(this).dialog("close");
|
||||
},
|
||||
"Cancel": function() {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#save-search").on("click.danbooru", function(e) {
|
||||
$("#save-search-dialog #saved_search_query").val($("#tags").val());
|
||||
$.post(
|
||||
"/saved_searches.js",
|
||||
{
|
||||
"saved_search": {
|
||||
"query": $("#tags").val()
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
Post.update_tag_count = function(event) {
|
||||
let string = "0 tags";
|
||||
let count = 0;
|
||||
|
@ -1,18 +0,0 @@
|
||||
let SavedSearch = {};
|
||||
|
||||
SavedSearch.initialize_all = function() {
|
||||
if ($("#c-saved-searches").length) {
|
||||
$("#c-saved-searches table").stupidtable();
|
||||
}
|
||||
}
|
||||
|
||||
SavedSearch.labels = function(term) {
|
||||
return $.getJSON("/saved_searches/labels", {
|
||||
"search[label]": term + "*",
|
||||
"limit": 10
|
||||
});
|
||||
}
|
||||
|
||||
$(SavedSearch.initialize_all);
|
||||
|
||||
export default SavedSearch
|
@ -1,7 +0,0 @@
|
||||
class SavedSearchJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(*args)
|
||||
SavedSearch.populate(args[0])
|
||||
end
|
||||
end
|
@ -15,7 +15,6 @@ class TagBatchJob < ApplicationJob
|
||||
CurrentUser.without_safe_mode do
|
||||
CurrentUser.scoped(updater, @updater_ip_addr) do
|
||||
migrate_posts(normalized_antecedent, normalized_consequent)
|
||||
migrate_saved_searches(normalized_antecedent, normalized_consequent)
|
||||
migrate_blacklists(normalized_antecedent, normalized_consequent)
|
||||
end
|
||||
end
|
||||
@ -35,19 +34,6 @@ class TagBatchJob < ApplicationJob
|
||||
end
|
||||
end
|
||||
|
||||
def migrate_saved_searches(normalized_antecedent, normalized_consequent)
|
||||
if SavedSearch.enabled?
|
||||
tags = Tag.scan_tags(normalized_antecedent.join(" "), strip_metatags: true)
|
||||
|
||||
# https://www.postgresql.org/docs/current/static/functions-array.html
|
||||
saved_searches = SavedSearch.where("string_to_array(query, ' ') @> ARRAY[?]", tags)
|
||||
saved_searches.find_each do |ss|
|
||||
ss.query = (ss.query.split - tags + normalized_consequent).uniq.join(" ")
|
||||
ss.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# this can't handle negated tags or other special cases
|
||||
def migrate_blacklists(normalized_antecedent, normalized_consequent)
|
||||
query = normalized_antecedent
|
||||
|
@ -6,7 +6,6 @@ class UserDeletionJob < ApplicationJob
|
||||
|
||||
|
||||
remove_favorites(user)
|
||||
remove_saved_searches(user)
|
||||
rename(user)
|
||||
end
|
||||
|
||||
@ -18,10 +17,6 @@ class UserDeletionJob < ApplicationJob
|
||||
end
|
||||
end
|
||||
|
||||
def remove_saved_searches(user)
|
||||
SavedSearch.where(user_id: user.id).destroy_all
|
||||
end
|
||||
|
||||
def rename(user)
|
||||
name = "user_#{user.id}"
|
||||
n = 0
|
||||
|
@ -61,21 +61,6 @@ class ElasticPostQueryBuilder
|
||||
}})
|
||||
end
|
||||
|
||||
def saved_search_relation(saved_searches, should)
|
||||
if SavedSearch.enabled?
|
||||
saved_searches.map do |saved_search|
|
||||
if saved_search == "all"
|
||||
post_ids = SavedSearch.post_ids_for(CurrentUser.id)
|
||||
else
|
||||
post_ids = SavedSearch.post_ids_for(CurrentUser.id, label: saved_search)
|
||||
end
|
||||
|
||||
post_ids = [] if post_ids.empty?
|
||||
should.push({terms: {id: post_ids}})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def table_for_metatag(metatag)
|
||||
if metatag.in?(Tag::COUNT_METATAGS)
|
||||
metatag[/(?<table>[a-z]+)_count\z/i, :table]
|
||||
@ -278,11 +263,6 @@ class ElasticPostQueryBuilder
|
||||
must_not.concat(q[:fav_ids_neg].map {|x| {term: {faves: x}}})
|
||||
end
|
||||
|
||||
if q[:saved_searches]
|
||||
# TODO
|
||||
# saved_search_relation(q[:saved_searches], should)
|
||||
end
|
||||
|
||||
if q[:uploader_id_neg]
|
||||
must_not.concat(q[:uploader_id_neg].map {|x| {term: {uploader: x.to_i}}})
|
||||
end
|
||||
|
@ -68,23 +68,6 @@ class PostQueryBuilder
|
||||
relation
|
||||
end
|
||||
|
||||
def add_saved_search_relation(saved_searches, relation)
|
||||
if SavedSearch.enabled?
|
||||
saved_searches.each do |saved_search|
|
||||
if saved_search == "all"
|
||||
post_ids = SavedSearch.post_ids_for(CurrentUser.id)
|
||||
else
|
||||
post_ids = SavedSearch.post_ids_for(CurrentUser.id, label: saved_search)
|
||||
end
|
||||
|
||||
post_ids = [0] if post_ids.empty?
|
||||
relation = relation.where("posts.id": post_ids)
|
||||
end
|
||||
end
|
||||
|
||||
relation
|
||||
end
|
||||
|
||||
def table_for_metatag(metatag)
|
||||
if metatag.in?(Tag::COUNT_METATAGS)
|
||||
metatag[/(?<table>[a-z]+)_count\z/i, :table]
|
||||
@ -225,10 +208,6 @@ class PostQueryBuilder
|
||||
relation = relation.where("posts.pool_string != ''")
|
||||
end
|
||||
|
||||
if q[:saved_searches]
|
||||
relation = add_saved_search_relation(q[:saved_searches], relation)
|
||||
end
|
||||
|
||||
if q[:uploader_id_neg]
|
||||
relation = relation.where.not("posts.uploader_id": q[:uploader_id_neg])
|
||||
end
|
||||
|
@ -164,10 +164,6 @@ module PostSets
|
||||
[page.to_i, 1].max
|
||||
end
|
||||
|
||||
def is_saved_search?
|
||||
tag_string =~ /search:/
|
||||
end
|
||||
|
||||
def presenter
|
||||
@presenter ||= ::PostSetPresenters::Post.new(self)
|
||||
end
|
||||
|
@ -1,152 +0,0 @@
|
||||
class SavedSearch < ApplicationRecord
|
||||
REDIS_EXPIRY = 3600
|
||||
QUERY_LIMIT = 1000
|
||||
|
||||
def self.enabled?
|
||||
Danbooru.config.redis_url.present?
|
||||
end
|
||||
|
||||
concerning :Redis do
|
||||
class_methods do
|
||||
extend Memoist
|
||||
|
||||
def redis
|
||||
::Redis.new(url: Danbooru.config.redis_url)
|
||||
end
|
||||
memoize :redis
|
||||
|
||||
def post_ids_for(user_id, label: nil)
|
||||
label = normalize_label(label) if label
|
||||
queries = queries_for(user_id, label: label)
|
||||
post_ids = Set.new
|
||||
queries.each do |query|
|
||||
redis_key = "search:#{query}"
|
||||
if redis.exists(redis_key)
|
||||
sub_ids = redis.smembers(redis_key).map(&:to_i)
|
||||
post_ids.merge(sub_ids)
|
||||
redis.expire(redis_key, REDIS_EXPIRY)
|
||||
else
|
||||
SavedSearchJob.perform_later(query)
|
||||
end
|
||||
end
|
||||
post_ids.to_a.sort.last(QUERY_LIMIT)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
concerning :Labels do
|
||||
class_methods do
|
||||
def normalize_label(label)
|
||||
label.
|
||||
to_s.
|
||||
strip.
|
||||
downcase.
|
||||
gsub(/[[:space:]]/, "_")
|
||||
end
|
||||
|
||||
def search_labels(user_id, params)
|
||||
labels = labels_for(user_id)
|
||||
|
||||
if params[:label].present?
|
||||
query = Regexp.escape(params[:label]).gsub("\\*", ".*")
|
||||
query = ".*#{query}.*" unless query.include?("*")
|
||||
query = /\A#{query}\z/
|
||||
labels = labels.grep(query)
|
||||
end
|
||||
|
||||
labels
|
||||
end
|
||||
|
||||
def labels_for(user_id)
|
||||
SavedSearch.
|
||||
where(user_id: user_id).
|
||||
order("label").
|
||||
pluck(Arel.sql("distinct unnest(labels) as label"))
|
||||
end
|
||||
end
|
||||
|
||||
def normalize_labels
|
||||
self.labels = labels.
|
||||
map {|x| SavedSearch.normalize_label(x)}.
|
||||
reject {|x| x.blank?}
|
||||
end
|
||||
|
||||
def label_string
|
||||
labels.join(" ")
|
||||
end
|
||||
|
||||
def label_string=(val)
|
||||
self.labels = val.to_s.split(/[[:space:]]+/)
|
||||
end
|
||||
|
||||
def labels=(labels)
|
||||
labels = labels.map { |label| SavedSearch.normalize_label(label) }
|
||||
super(labels)
|
||||
end
|
||||
end
|
||||
|
||||
concerning :Search do
|
||||
class_methods do
|
||||
def populate(query)
|
||||
CurrentUser.as_system do
|
||||
redis_key = "search:#{query}"
|
||||
return if redis.exists(redis_key)
|
||||
post_ids = Post.tag_match(query, true).limit(QUERY_LIMIT).records.pluck(:id)
|
||||
redis.sadd(redis_key, post_ids)
|
||||
redis.expire(redis_key, REDIS_EXPIRY)
|
||||
end
|
||||
rescue Exception
|
||||
# swallow
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
concerning :Queries do
|
||||
class_methods do
|
||||
def queries_for(user_id, label: nil, options: {})
|
||||
SavedSearch.
|
||||
where(user_id: user_id).
|
||||
labeled(label).
|
||||
pluck(:query).
|
||||
map {|x| Tag.normalize_query(x, sort: true)}.
|
||||
sort.
|
||||
uniq
|
||||
end
|
||||
end
|
||||
|
||||
def normalized_query
|
||||
Tag.normalize_query(query, sort: true)
|
||||
end
|
||||
|
||||
def normalize_query
|
||||
self.query = Tag.normalize_query(query, sort: false)
|
||||
end
|
||||
end
|
||||
|
||||
belongs_to :user
|
||||
validates :query, presence: true
|
||||
validate :validate_count
|
||||
before_create :update_user_on_create
|
||||
after_destroy :update_user_on_destroy
|
||||
before_validation :normalize_query
|
||||
before_validation :normalize_labels
|
||||
scope :labeled, ->(label) { label.present? ? where("labels @> string_to_array(?, '~~~~')", label) : where("true") }
|
||||
|
||||
def validate_count
|
||||
if user.saved_searches.count + 1 > user.max_saved_searches
|
||||
self.errors[:user] << "can only have up to #{user.max_saved_searches} " + "saved search".pluralize(user.max_saved_searches)
|
||||
end
|
||||
end
|
||||
|
||||
def update_user_on_create
|
||||
if !user.has_saved_searches?
|
||||
user.update(has_saved_searches: true)
|
||||
end
|
||||
end
|
||||
|
||||
def update_user_on_destroy
|
||||
if user.saved_searches.count == 0
|
||||
user.update(has_saved_searches: false)
|
||||
end
|
||||
end
|
||||
end
|
@ -728,10 +728,6 @@ class Tag < ApplicationRecord
|
||||
|
||||
q[:fav_ids] << favuser.id
|
||||
|
||||
when "search"
|
||||
q[:saved_searches] ||= []
|
||||
q[:saved_searches] << g2
|
||||
|
||||
when "md5"
|
||||
q[:md5] = g2.downcase.split(/,/)[0..99]
|
||||
|
||||
|
@ -27,6 +27,7 @@ class User < ApplicationRecord
|
||||
|
||||
# candidates for removal:
|
||||
# - disable_cropped_thumbnails (enabled by 22)
|
||||
# - has_saved_searches (removed in removal of saved searches)
|
||||
BOOLEAN_ATTRIBUTES = %w(
|
||||
show_avatars
|
||||
blacklist_avatars
|
||||
@ -112,7 +113,6 @@ class User < ApplicationRecord
|
||||
has_one :dmail_filter
|
||||
has_many :note_versions, :foreign_key => "updater_id"
|
||||
has_many :dmails, -> {order("dmails.id desc")}, :foreign_key => "owner_id"
|
||||
has_many :saved_searches
|
||||
has_many :forum_posts, -> {order("forum_posts.created_at, forum_posts.id")}, :foreign_key => "creator_id"
|
||||
has_many :user_name_change_requests, -> {visible.order("user_name_change_requests.id desc")}
|
||||
has_many :post_sets, -> {order(name: :asc)}, foreign_key: :creator_id
|
||||
@ -495,18 +495,6 @@ class User < ApplicationRecord
|
||||
create_user_throttle(:ticket, ->{ Danbooru.config.ticket_limit - Ticket.for_creator(id).where("created_at > ?", 1.hour.ago).count },
|
||||
:general_bypass_throttle?, 3.days)
|
||||
|
||||
def max_saved_searches
|
||||
if is_contributor?
|
||||
1_000
|
||||
else
|
||||
250
|
||||
end
|
||||
end
|
||||
|
||||
def show_saved_searches?
|
||||
true
|
||||
end
|
||||
|
||||
def can_remove_from_pools?
|
||||
older_than 7.days
|
||||
end
|
||||
|
@ -18,8 +18,6 @@ module PostSetPresenters
|
||||
def related_tags
|
||||
if post_set.is_pattern_search?
|
||||
pattern_tags
|
||||
elsif post_set.is_saved_search?
|
||||
["search:all"] + SavedSearch.labels_for(CurrentUser.user.id).map {|x| "search:#{x}"}
|
||||
elsif post_set.is_empty_tag? || post_set.tag_string == "order:rank"
|
||||
popular_tags
|
||||
elsif post_set.is_single_tag?
|
||||
@ -63,12 +61,8 @@ module PostSetPresenters
|
||||
RelatedTagCalculator.calculate_from_posts_to_array(post_set.posts).map(&:first)
|
||||
end
|
||||
|
||||
def saved_search_labels
|
||||
SavedSearch.labels_for(CurrentUser.user.id).map {|x| "search:#{x}"}
|
||||
end
|
||||
|
||||
def tag_list_html(**options)
|
||||
tag_set_presenter.tag_list_html(name_only: post_set.is_saved_search?, **options)
|
||||
tag_set_presenter.tag_list_html(name_only: false, **options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -39,10 +39,6 @@ class UserPresenter
|
||||
permissions.join(", ")
|
||||
end
|
||||
|
||||
def posts_for_saved_search_category(category)
|
||||
Post.tag_match("search:#{category}").limit(10).records
|
||||
end
|
||||
|
||||
def upload_limit(template)
|
||||
if user.can_upload_free?
|
||||
return "none"
|
||||
@ -140,14 +136,6 @@ class UserPresenter
|
||||
template.link_to("positive:#{positive} neutral:#{neutral} negative:#{negative}", template.user_feedbacks_path(:search => {:user_id => user.id}))
|
||||
end
|
||||
|
||||
def saved_search_labels
|
||||
if CurrentUser.user.id == user.id
|
||||
SavedSearch.labels_for(CurrentUser.user.id)
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def previous_names(template)
|
||||
user.user_name_change_requests.map { |req| template.link_to req.original_name, req }.join(" -> ").html_safe
|
||||
end
|
||||
|
@ -15,8 +15,6 @@
|
||||
<%= @post_set.presenter.tag_list_html(current_query: params[:tags], show_extra_links: CurrentUser.user.is_privileged?) %>
|
||||
</section>
|
||||
|
||||
<%= render "posts/partials/index/options" %>
|
||||
|
||||
<%= render "posts/partials/index/related" %>
|
||||
</aside>
|
||||
|
||||
@ -46,18 +44,11 @@
|
||||
|
||||
|
||||
<%= post_search_count_js %>
|
||||
|
||||
<div id="saved-searches-nav">
|
||||
<%= render "saved_searches/interface" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if params[:tags] =~ /search:/ %>
|
||||
<%= render "saved_searches/secondary_links" %>
|
||||
<% else %>
|
||||
<%= render "posts/partials/common/secondary_links" %>
|
||||
<% end %>
|
||||
|
||||
<%= render "posts/partials/common/secondary_links" %>
|
||||
|
||||
<% content_for(:page_title) do %>
|
||||
<% if @post_set.public_tag_string.present? %>
|
||||
|
@ -8,9 +8,6 @@
|
||||
<% end %>
|
||||
<% unless CurrentUser.is_anonymous? %>
|
||||
<%= subnav_link_to "Favorites", favorites_path %>
|
||||
<% if CurrentUser.has_saved_searches? %>
|
||||
<%= subnav_link_to "Saved searches", posts_path(:tags => "search:all") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<%= subnav_link_to "Changes", post_versions_path %>
|
||||
<% if CurrentUser.can_approve_posts? %>
|
||||
|
@ -1,8 +0,0 @@
|
||||
<section id="options-box">
|
||||
<h1>Options</h1>
|
||||
<ul>
|
||||
<% if SavedSearch.enabled? && CurrentUser.is_member? %>
|
||||
<li><%= button_tag(tag.i(class: "fas fa-bookmark") + " Save search", id: "save-search", class: "ui-button ui-widget ui-corner-all sub") %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</section>
|
@ -1,9 +0,0 @@
|
||||
<% if SavedSearch.enabled? %>
|
||||
<div id="save-search-dialog" title="Save Search" style="display: none;">
|
||||
|
||||
<%= simple_form_for(SavedSearch.new, remote: true) do |f| %>
|
||||
<%= f.input :query, as: :string, input_html: { value: params[:tags], data: { autocomplete: "tag-query" } } %>
|
||||
<%= f.input :label_string, label: "Labels", hint: "A list of tags to help categorize this search. Space delimited." %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
@ -1,6 +0,0 @@
|
||||
<% content_for(:secondary_links) do %>
|
||||
<menu>
|
||||
<%= subnav_link_to "View posts", posts_path(:tags => "search:all") %>
|
||||
<%= subnav_link_to "Manage saved searches", saved_searches_path %>
|
||||
</menu>
|
||||
<% end %>
|
@ -1,5 +0,0 @@
|
||||
<% if @saved_search.errors.any? %>
|
||||
$(window).trigger("danbooru:error", "<%= j @saved_search.errors.full_messages.join(', ') %>");
|
||||
<% else %>
|
||||
$(window).trigger("danbooru:notice", "Search '<%= j @saved_search.query %>' was saved");
|
||||
<% end %>
|
@ -1,4 +0,0 @@
|
||||
$(window).trigger("danbooru:notice", "Search '<%= j @saved_search.query %>' was deleted");
|
||||
$("#saved-searches-nav").html("<%= j render('saved_searches/interface', :saved_searches => CurrentUser.user.saved_searches) %>");
|
||||
$(window).trigger("danbooru:initialize_saved_searches");
|
||||
$("#saved-search-<%= @saved_search.id %>").remove();
|
@ -1,19 +0,0 @@
|
||||
<div id="c-saved-searches">
|
||||
<div id="a-edit">
|
||||
<h1>Edit Saved Search</h1>
|
||||
|
||||
<%= error_messages_for :saved_search %>
|
||||
|
||||
<%= simple_form_for(@saved_search) do |f| %>
|
||||
<%= f.input :query, :as => :string %>
|
||||
<%= f.input :label_string, :label => "Labels", :hint => "A list of tags to help categorize this search. Space delimited." %>
|
||||
<%= f.button :submit, :value => "Submit" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "secondary_links" %>
|
||||
|
||||
<% content_for(:page_title) do %>
|
||||
Edit Saved Search - <%= Danbooru.config.app_name %>
|
||||
<% end %>
|
@ -1,43 +0,0 @@
|
||||
<div id="c-saved-searches">
|
||||
<div id="a-index">
|
||||
<h1>
|
||||
Saved Searches
|
||||
<% if params[:label] %>
|
||||
(<%= params[:label] %>)
|
||||
<% end %>
|
||||
</h1>
|
||||
|
||||
<table class="striped" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sort="string" width="60%">Query</th>
|
||||
<th data-sort="string" width="20%">Labels</th>
|
||||
<th width="20%" class="links"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<% @saved_searches.each do |ss| %>
|
||||
<tr id="saved-search-<%= ss.id %>">
|
||||
<td><%= link_to ss.query, posts_path(:tags => ss.query) %></td>
|
||||
<td>
|
||||
<% ss.labels.each do |label| %>
|
||||
<%= link_to label, posts_path(:tags => "search:#{label}") %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="links">
|
||||
<%= link_to "edit", edit_saved_search_path(ss) %>
|
||||
| <%= link_to "delete", saved_search_path(ss), :method => :delete, :remote => true %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "secondary_links" %>
|
||||
|
||||
<% content_for(:page_title) do %>
|
||||
Saved Searches - <%= Danbooru.config.app_name %>
|
||||
<% end %>
|
@ -23,20 +23,3 @@
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if CurrentUser.user.id == @user.id && @user.has_saved_searches? && @user.is_privileged? %>
|
||||
<% presenter.saved_search_labels.each do |label| %>
|
||||
<div class="box user-saved-search" data-label="<%= label %>">
|
||||
<h2>
|
||||
Saved Search: <%= link_to label, posts_path(:tags => "search:#{label}") %>
|
||||
(<%= link_to "manage", saved_searches_path(label: label) %>)
|
||||
</h2>
|
||||
|
||||
<div class="vertical-section">
|
||||
<% presenter.posts_for_saved_search_category(label).each do |post| %>
|
||||
<%= PostPresenter.preview(post, :tags => "search:#{label}") %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
@ -113,17 +113,6 @@
|
||||
<% end %>
|
||||
|
||||
<% if CurrentUser.id == user.id %>
|
||||
<% if CurrentUser.has_saved_searches? %>
|
||||
<tr>
|
||||
<th>Saved Searches</th>
|
||||
<td>
|
||||
<% SavedSearch.labels_for(CurrentUser.user.id).each do |label| %>
|
||||
<%= link_to label, posts_path(tags: "search:#{label}") %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<tr>
|
||||
<th>API Key</th>
|
||||
<td>
|
||||
|
@ -59,5 +59,5 @@ Rails.application.configure do
|
||||
# Use an evented file watcher to asynchronously detect changes in source code,
|
||||
# routes, locales, etc. This feature depends on the listen gem.
|
||||
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
|
||||
config.hosts << 'e621.lc'
|
||||
config.hosts << 'e621ng.local'
|
||||
end
|
||||
|
@ -37,6 +37,3 @@ en:
|
||||
user_feedback:
|
||||
creator: "You"
|
||||
creator_id: "You"
|
||||
saved_search:
|
||||
user: "You"
|
||||
user_id: "You"
|
@ -295,11 +295,6 @@ Rails.application.routes.draw do
|
||||
get "reports/down_voting_post" => "reports#down_voting_post"
|
||||
post "reports/down_voting_post_create" => "reports#down_voting_post_create"
|
||||
resource :recommended_posts, only: [:show]
|
||||
resources :saved_searches, :except => [:show] do
|
||||
collection do
|
||||
get :labels
|
||||
end
|
||||
end
|
||||
resource :session, only: [:new, :create, :destroy] do
|
||||
get :sign_out, on: :collection
|
||||
end
|
||||
|
@ -1,7 +0,0 @@
|
||||
FactoryBot.define do
|
||||
factory(:saved_search) do
|
||||
query { FFaker::Lorem.words }
|
||||
labels { [FFaker::Lorem.word] }
|
||||
user
|
||||
end
|
||||
end
|
@ -1,4 +0,0 @@
|
||||
FactoryBot.define do
|
||||
factory(:super_voter) do
|
||||
end
|
||||
end
|
@ -1,63 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
class SavedSearchesControllerTest < ActionDispatch::IntegrationTest
|
||||
context "The saved searches controller" do
|
||||
setup do
|
||||
SavedSearch.stubs(:enabled?).returns(true)
|
||||
@user = create(:user)
|
||||
as_user do
|
||||
@saved_search = create(:saved_search, user: @user)
|
||||
end
|
||||
mock_saved_search_service!
|
||||
end
|
||||
|
||||
context "index action" do
|
||||
should "render" do
|
||||
get_auth saved_searches_path, @user
|
||||
assert_response :success
|
||||
assert_select "#saved-search-#{@saved_search.id}"
|
||||
end
|
||||
end
|
||||
|
||||
context "create action" do
|
||||
should "render" do
|
||||
post_auth saved_searches_path, @user, params: { saved_search: { query: "bkub", label_string: "artist" }}
|
||||
assert_response :redirect
|
||||
end
|
||||
end
|
||||
|
||||
context "edit action" do
|
||||
should "render" do
|
||||
as_user do
|
||||
@saved_search = create(:saved_search, user: @user)
|
||||
end
|
||||
|
||||
get_auth edit_saved_search_path(@saved_search), @user, params: { id: @saved_search.id }
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
context "update action" do
|
||||
should "render" do
|
||||
as_user do
|
||||
@saved_search = create(:saved_search, user: @user)
|
||||
end
|
||||
params = { id: @saved_search.id, saved_search: { label_string: "foo" } }
|
||||
put_auth saved_search_path(@saved_search), @user, params: params
|
||||
assert_redirected_to saved_searches_path
|
||||
assert_equal(["foo"], @saved_search.reload.labels)
|
||||
end
|
||||
end
|
||||
|
||||
context "destroy action" do
|
||||
should "render" do
|
||||
as_user do
|
||||
@saved_search = create(:saved_search, user: @user)
|
||||
end
|
||||
|
||||
delete_auth saved_search_path(@saved_search), @user
|
||||
assert_redirected_to saved_searches_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -38,7 +38,6 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
|
||||
# flesh out profile to get more test coverage of user presenter.
|
||||
@user = create(:banned_user, can_approve_posts: true, is_super_voter: true)
|
||||
as_user do
|
||||
create(:saved_search, user: @user)
|
||||
create(:post, uploader: @user, tag_string: "fav:#{@user.name}")
|
||||
end
|
||||
end
|
||||
|
@ -70,7 +70,6 @@ class ActiveSupport::TestCase
|
||||
include ReportbooruHelper
|
||||
include DownloadTestHelper
|
||||
include IqdbTestHelper
|
||||
include SavedSearchTestHelper
|
||||
include UploadTestHelper
|
||||
include TestHelpers
|
||||
|
||||
|
@ -1,5 +0,0 @@
|
||||
module SavedSearchTestHelper
|
||||
def mock_saved_search_service!
|
||||
SavedSearch.stubs(:enabled?).returns(true)
|
||||
end
|
||||
end
|
@ -4,7 +4,6 @@ module Moderator
|
||||
class TagBatchChangeTest < ActiveSupport::TestCase
|
||||
def setup
|
||||
super
|
||||
mock_saved_search_service!
|
||||
end
|
||||
|
||||
context "a tag batch change" do
|
||||
@ -37,14 +36,6 @@ module Moderator
|
||||
assert_equal("bbb", @post.tag_string)
|
||||
end
|
||||
|
||||
should "move saved searches" do
|
||||
ss = FactoryBot.create(:saved_search, :user => @user, :query => "123 ... 456")
|
||||
tag_batch_change = TagBatchChange.new("...", "bbb", @user.id, "127.0.0.1")
|
||||
tag_batch_change.perform
|
||||
|
||||
assert_equal("123 456 bbb", ss.reload.normalized_query)
|
||||
end
|
||||
|
||||
should "move blacklists" do
|
||||
@user.update(blacklisted_tags: "123 456\n789\n")
|
||||
tag_batch_change = TagBatchChange.new("456", "xxx", @user.id, "127.0.0.1")
|
||||
@ -53,19 +44,6 @@ module Moderator
|
||||
assert_equal("123 xxx\n789", @user.blacklisted_tags)
|
||||
end
|
||||
|
||||
should "move only saved searches that match the mass update exactly" do
|
||||
ss = FactoryBot.create(:saved_search, :user => @user, :query => "123 ... 456")
|
||||
tag_batch_change = TagBatchChange.new("1", "bbb", @user.id, "127.0.0.1")
|
||||
tag_batch_change.perform
|
||||
|
||||
assert_equal("... 123 456", ss.reload.normalized_query, "expected '123' to remain unchanged")
|
||||
|
||||
tag_batch_change = TagBatchChange.new("123 456", "789", @user.id, "127.0.0.1")
|
||||
tag_batch_change.perform
|
||||
|
||||
assert_equal("... 789", ss.reload.normalized_query, "expected '123 456' to be changed to '789'")
|
||||
end
|
||||
|
||||
should "raise an error if there is no predicate" do
|
||||
tag_batch_change = TagBatchChange.new("", "bbb", @user.id, "127.0.0.1")
|
||||
assert_raises(TagBatchChange::Error) do
|
||||
|
@ -13,7 +13,6 @@ class PostTest < ActiveSupport::TestCase
|
||||
end
|
||||
CurrentUser.user = @user
|
||||
CurrentUser.ip_addr = "127.0.0.1"
|
||||
mock_saved_search_service!
|
||||
mock_pool_archive_service!
|
||||
end
|
||||
|
||||
@ -2196,37 +2195,6 @@ class PostTest < ActiveSupport::TestCase
|
||||
assert_tag_match([post], "pixiv_id:none")
|
||||
end
|
||||
|
||||
context "saved searches" do
|
||||
setup do
|
||||
SavedSearch.stubs(:enabled?).returns(true)
|
||||
@post1 = FactoryBot.create(:post, tag_string: "aaa")
|
||||
@post2 = FactoryBot.create(:post, tag_string: "bbb")
|
||||
FactoryBot.create(:saved_search, query: "aaa", labels: ["zzz"], user: CurrentUser.user)
|
||||
FactoryBot.create(:saved_search, query: "bbb", user: CurrentUser.user)
|
||||
end
|
||||
|
||||
context "labeled" do
|
||||
should "work" do
|
||||
SavedSearch.expects(:post_ids_for).with(CurrentUser.id, label: "zzz").returns([@post1.id])
|
||||
assert_tag_match([@post1], "search:zzz")
|
||||
end
|
||||
end
|
||||
|
||||
context "missing" do
|
||||
should "work" do
|
||||
SavedSearch.expects(:post_ids_for).with(CurrentUser.id, label: "uncategorized").returns([@post2.id])
|
||||
assert_tag_match([@post2], "search:uncategorized")
|
||||
end
|
||||
end
|
||||
|
||||
context "all" do
|
||||
should "work" do
|
||||
SavedSearch.expects(:post_ids_for).with(CurrentUser.id).returns([@post1.id, @post2.id])
|
||||
assert_tag_match([@post2, @post1], "search:all")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "return posts for a rating:<s|q|e> metatag" do
|
||||
s = FactoryBot.create(:post, :rating => "s")
|
||||
q = FactoryBot.create(:post, :rating => "q")
|
||||
|
@ -1,168 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
class SavedSearchTest < ActiveSupport::TestCase
|
||||
def setup
|
||||
super
|
||||
Sidekiq::Testing::inline!
|
||||
@user = FactoryBot.create(:user)
|
||||
CurrentUser.user = @user
|
||||
CurrentUser.ip_addr = "127.0.0.1"
|
||||
@mock_redis = MockRedis.new
|
||||
SavedSearch.stubs(:redis).returns(@mock_redis)
|
||||
end
|
||||
|
||||
def teardown
|
||||
super
|
||||
Sidekiq::Testing::fake!
|
||||
CurrentUser.user = nil
|
||||
CurrentUser.ip_addr = nil
|
||||
end
|
||||
|
||||
context ".labels_for" do
|
||||
setup do
|
||||
FactoryBot.create(:saved_search, user: @user, label_string: "blah", query: "blah")
|
||||
FactoryBot.create(:saved_search, user: @user, label_string: "zah", query: "blah")
|
||||
end
|
||||
|
||||
should "fetch the labels used by a user" do
|
||||
assert_equal(%w(blah zah), SavedSearch.labels_for(@user.id))
|
||||
end
|
||||
end
|
||||
|
||||
context ".queries_for" do
|
||||
setup do
|
||||
FactoryBot.create(:tag_alias, antecedent_name: "bbb", consequent_name: "ccc", creator: @user)
|
||||
FactoryBot.create(:saved_search, user: @user, label_string: "blah", query: "aaa")
|
||||
FactoryBot.create(:saved_search, user: @user, label_string: "zah", query: "CCC BBB AAA")
|
||||
FactoryBot.create(:saved_search, user: @user, label_string: "qux", query: " aaa bbb ccc ")
|
||||
end
|
||||
|
||||
should "fetch the queries used by a user for a label" do
|
||||
assert_equal(%w(aaa), SavedSearch.queries_for(@user.id, label: "blah"))
|
||||
end
|
||||
|
||||
should "fetch the queries used by a user without a label" do
|
||||
assert_equal(["aaa", "aaa ccc"], SavedSearch.queries_for(@user.id))
|
||||
end
|
||||
end
|
||||
|
||||
context ".search_labels" do
|
||||
setup do
|
||||
FactoryBot.create(:tag_alias, antecedent_name: "bbb", consequent_name: "ccc", creator: @user)
|
||||
FactoryBot.create(:saved_search, user: @user, label_string: "blah", query: "aaa")
|
||||
FactoryBot.create(:saved_search, user: @user, label_string: "blahbling", query: "CCC BBB AAA")
|
||||
FactoryBot.create(:saved_search, user: @user, label_string: "qux", query: " aaa bbb ccc ")
|
||||
end
|
||||
|
||||
should "fetch the queries used by a user for a label" do
|
||||
assert_equal(%w(blah blahbling), SavedSearch.search_labels(@user.id, label: "blah"))
|
||||
end
|
||||
end
|
||||
|
||||
context ".post_ids_for" do
|
||||
context "with a label" do
|
||||
setup do
|
||||
SavedSearch.expects(:queries_for).with(1, label: "blah").returns(%w(a b c))
|
||||
end
|
||||
|
||||
context "without a primed cache" do
|
||||
should "delay processing three times" do
|
||||
SavedSearch.expects(:populate).times(3)
|
||||
post_ids = SavedSearch.post_ids_for(1, label: "blah")
|
||||
assert_equal([], post_ids)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a primed cached" do
|
||||
setup do
|
||||
@mock_redis.sadd("search:a", 1)
|
||||
@mock_redis.sadd("search:b", 2)
|
||||
@mock_redis.sadd("search:c", 3)
|
||||
end
|
||||
|
||||
should "fetch the post ids" do
|
||||
SavedSearch.expects(:delay).never
|
||||
post_ids = SavedSearch.post_ids_for(1, label: "blah")
|
||||
assert_equal([1,2,3], post_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "without a label" do
|
||||
setup do
|
||||
SavedSearch.expects(:queries_for).with(1, label: nil).returns(%w(a b c))
|
||||
end
|
||||
|
||||
context "without a primed cache" do
|
||||
should "delay processing three times" do
|
||||
SavedSearch.expects(:populate).times(3)
|
||||
post_ids = SavedSearch.post_ids_for(1)
|
||||
assert_equal([], post_ids)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a primed cache" do
|
||||
setup do
|
||||
@mock_redis.sadd("search:a", 1)
|
||||
@mock_redis.sadd("search:b", 2)
|
||||
@mock_redis.sadd("search:c", 3)
|
||||
end
|
||||
|
||||
should "fetch the post ids" do
|
||||
SavedSearch.expects(:delay).never
|
||||
post_ids = SavedSearch.post_ids_for(1)
|
||||
assert_equal([1,2,3], post_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Creating a saved search" do
|
||||
setup do
|
||||
FactoryBot.create(:tag_alias, antecedent_name: "zzz", consequent_name: "yyy", creator: @user)
|
||||
@saved_search = @user.saved_searches.create(query: " ZZZ xxx ")
|
||||
end
|
||||
|
||||
should "update the bitpref on the user" do
|
||||
@user.reload
|
||||
assert(@user.has_saved_searches?, "should have saved_searches bitpref set")
|
||||
end
|
||||
|
||||
should "normalize the query aside from the order" do
|
||||
assert_equal("yyy xxx", @saved_search.query)
|
||||
end
|
||||
|
||||
should "normalize the label string" do
|
||||
@saved_search.label_string = "Foo Bar"
|
||||
assert_equal(%w[foo bar], @saved_search.labels)
|
||||
|
||||
@saved_search.labels = ["Artist 1", "Artist 2"]
|
||||
assert_equal(%w[artist_1 artist_2], @saved_search.labels)
|
||||
end
|
||||
end
|
||||
|
||||
context "Destroying a saved search" do
|
||||
setup do
|
||||
@saved_search = @user.saved_searches.create(query: "xxx")
|
||||
@saved_search.destroy
|
||||
end
|
||||
|
||||
should "update the bitpref on the user" do
|
||||
@user.reload
|
||||
assert(!@user.has_saved_searches?, "should not have the saved_searches bitpref set")
|
||||
end
|
||||
end
|
||||
|
||||
context "A user with max saved searches" do
|
||||
setup do
|
||||
@user = FactoryBot.create(:privileged_user)
|
||||
CurrentUser.user = @user
|
||||
User.any_instance.stubs(:max_saved_searches).returns(0)
|
||||
@saved_search = @user.saved_searches.create(:query => "xxx")
|
||||
end
|
||||
|
||||
should "not be able to create another saved search" do
|
||||
assert_equal(["You can only have up to 0 saved searches"], @saved_search.errors.full_messages)
|
||||
end
|
||||
end
|
||||
end
|
@ -18,7 +18,6 @@ class TagAliasTest < ActiveSupport::TestCase
|
||||
CurrentUser.user = user
|
||||
end
|
||||
CurrentUser.ip_addr = "127.0.0.1"
|
||||
mock_saved_search_service!
|
||||
end
|
||||
|
||||
teardown do
|
||||
@ -125,22 +124,6 @@ class TagAliasTest < ActiveSupport::TestCase
|
||||
assert_equal(["bbb", "bbb"], TagAlias.to_aliased(["aaa", "aaa"]))
|
||||
end
|
||||
|
||||
context "saved searches" do
|
||||
setup do
|
||||
SavedSearch.stubs(:enabled?).returns(true)
|
||||
end
|
||||
|
||||
should "move saved searches" do
|
||||
tag1 = FactoryBot.create(:tag, :name => "...")
|
||||
tag2 = FactoryBot.create(:tag, :name => "bbb")
|
||||
ss = FactoryBot.create(:saved_search, :query => "123 ... 456", :user => CurrentUser.user)
|
||||
ta = FactoryBot.create(:tag_alias, :antecedent_name => "...", :consequent_name => "bbb")
|
||||
ta.approve!(approver: @admin)
|
||||
|
||||
assert_equal(%w(123 456 bbb), ss.reload.query.split.sort)
|
||||
end
|
||||
end
|
||||
|
||||
should "update any affected posts when saved" do
|
||||
post1 = FactoryBot.create(:post, :tag_string => "aaa bbb")
|
||||
post2 = FactoryBot.create(:post, :tag_string => "ccc ddd")
|
||||
|
Loading…
Reference in New Issue
Block a user