397 lines
14 KiB
Ruby
397 lines
14 KiB
Ruby
class BookmarksController < ApplicationController
|
|
before_action :load_collection
|
|
before_action :load_owner, only: [:index]
|
|
before_action :load_bookmarkable, only: [:index, :new, :create]
|
|
before_action :users_only, only: [:new, :create, :edit, :update]
|
|
before_action :check_user_status, only: [:new, :create, :edit, :update]
|
|
before_action :check_parent_visible, only: [:index, :new]
|
|
before_action :load_bookmark, only: [:show, :edit, :update, :destroy, :confirm_delete, :share]
|
|
before_action :check_visibility, only: [:show, :share]
|
|
before_action :check_ownership, only: [:edit, :update, :destroy, :confirm_delete, :share]
|
|
|
|
before_action :check_pseud_ownership, only: [:create, :update]
|
|
|
|
skip_before_action :store_location, only: [:share]
|
|
|
|
def check_pseud_ownership
|
|
if params[:bookmark][:pseud_id]
|
|
pseud = Pseud.find(bookmark_params[:pseud_id])
|
|
unless pseud && current_user && current_user.pseuds.include?(pseud)
|
|
flash[:error] = ts("You can't bookmark with that pseud.")
|
|
redirect_to root_path and return
|
|
end
|
|
end
|
|
end
|
|
|
|
def check_parent_visible
|
|
check_visibility_for(@bookmarkable)
|
|
end
|
|
|
|
# get the parent
|
|
def load_bookmarkable
|
|
if params[:work_id]
|
|
@bookmarkable = Work.find(params[:work_id])
|
|
elsif params[:external_work_id]
|
|
@bookmarkable = ExternalWork.find(params[:external_work_id])
|
|
elsif params[:series_id]
|
|
@bookmarkable = Series.find(params[:series_id])
|
|
end
|
|
end
|
|
|
|
def load_bookmark
|
|
@bookmark = Bookmark.find(params[:id])
|
|
@check_ownership_of = @bookmark
|
|
@check_visibility_of = @bookmark
|
|
end
|
|
|
|
def search
|
|
@languages = Language.default_order
|
|
options = params[:bookmark_search].present? ? bookmark_search_params : {}
|
|
options.merge!(page: params[:page]) if params[:page].present?
|
|
options[:show_private] = false
|
|
options[:show_restricted] = logged_in? || logged_in_as_admin?
|
|
@search = BookmarkSearchForm.new(options)
|
|
@page_subtitle = ts("Search Bookmarks")
|
|
if params[:bookmark_search].present? && params[:edit_search].blank?
|
|
if @search.query.present?
|
|
@page_subtitle = ts("Bookmarks Matching '%{query}'", query: @search.query)
|
|
end
|
|
@bookmarks = @search.search_results.scope(:for_blurb)
|
|
flash_search_warnings(@bookmarks)
|
|
set_own_bookmarks
|
|
render 'search_results'
|
|
end
|
|
end
|
|
|
|
def index
|
|
if @bookmarkable
|
|
@bookmarks = @bookmarkable.bookmarks.not_private.order_by_created_at.paginate(page: params[:page], per_page: ArchiveConfig.ITEMS_PER_PAGE)
|
|
@bookmarks = @bookmarks.where(hidden_by_admin: false) unless logged_in_as_admin?
|
|
else
|
|
base_options = {
|
|
show_private: (@user.present? && @user == current_user),
|
|
show_restricted: logged_in? || logged_in_as_admin?,
|
|
page: params[:page]
|
|
}
|
|
|
|
options = params[:bookmark_search].present? ? bookmark_search_params : {}
|
|
|
|
if params[:include_bookmark_search].present?
|
|
params[:include_bookmark_search].keys.each do |key|
|
|
options[key] ||= []
|
|
options[key] << params[:include_bookmark_search][key]
|
|
options[key].flatten!
|
|
end
|
|
end
|
|
|
|
if params[:exclude_bookmark_search].present?
|
|
params[:exclude_bookmark_search].keys.each do |key|
|
|
# Keep bookmarker tags separate, so we can search for them on bookmarks
|
|
# and search for the rest on bookmarkables
|
|
options_key = key == "tag_ids" ? :excluded_bookmark_tag_ids : :excluded_tag_ids
|
|
options[options_key] ||= []
|
|
options[options_key] << params[:exclude_bookmark_search][key]
|
|
options[options_key].flatten!
|
|
end
|
|
end
|
|
|
|
options.merge!(base_options)
|
|
@page_subtitle = index_page_title
|
|
|
|
if @owner.present?
|
|
@search = BookmarkSearchForm.new(options.merge(faceted: true, parent: @owner))
|
|
|
|
if @user.blank?
|
|
# When it's not a particular user's bookmarks, we want
|
|
# to list *bookmarkable* items to avoid duplication
|
|
@bookmarkable_items = @search.bookmarkable_search_results.scope(:for_blurb)
|
|
flash_search_warnings(@bookmarkable_items)
|
|
@facets = @bookmarkable_items.facets
|
|
else
|
|
# We're looking at a particular user's bookmarks, so
|
|
# just retrieve the standard search results and their facets.
|
|
@bookmarks = @search.search_results.scope(:for_blurb)
|
|
flash_search_warnings(@bookmarks)
|
|
@facets = @bookmarks.facets
|
|
end
|
|
|
|
if @search.options[:excluded_tag_ids].present? || @search.options[:excluded_bookmark_tag_ids].present?
|
|
# Excluded tags do not appear in search results, so we need to generate empty facets
|
|
# to keep them as checkboxes on the filters.
|
|
excluded_tag_ids = @search.options[:excluded_tag_ids] || []
|
|
excluded_bookmark_tag_ids = @search.options[:excluded_bookmark_tag_ids] || []
|
|
|
|
# It's possible to determine the tag types by looking at
|
|
# the original parameters params[:exclude_bookmark_search],
|
|
# but we need the tag names too, so a database query is unavoidable.
|
|
tags = Tag.where(id: excluded_tag_ids + excluded_bookmark_tag_ids)
|
|
tags.each do |tag|
|
|
if excluded_tag_ids.include?(tag.id.to_s)
|
|
key = tag.class.to_s.underscore
|
|
@facets[key] ||= []
|
|
@facets[key] << QueryFacet.new(tag.id, tag.name, 0)
|
|
end
|
|
if excluded_bookmark_tag_ids.include?(tag.id.to_s)
|
|
key = 'tag'
|
|
@facets[key] ||= []
|
|
@facets[key] << QueryFacet.new(tag.id, tag.name, 0)
|
|
end
|
|
end
|
|
end
|
|
elsif use_caching?
|
|
@bookmarks = Rails.cache.fetch("bookmarks/index/latest/v2_true", expires_in: ArchiveConfig.SECONDS_UNTIL_BOOKMARK_INDEX_EXPIRE.seconds) do
|
|
search = BookmarkSearchForm.new(show_private: false, show_restricted: false, sort_column: 'created_at')
|
|
results = search.search_results.scope(:for_blurb)
|
|
flash_search_warnings(results)
|
|
results.to_a
|
|
end
|
|
else
|
|
@bookmarks = Bookmark.latest.for_blurb.to_a
|
|
end
|
|
end
|
|
set_own_bookmarks
|
|
|
|
@pagy =
|
|
if @bookmarks.respond_to?(:total_pages)
|
|
pagy_query_result(@bookmarks)
|
|
elsif @bookmarkable_items.respond_to?(:total_pages)
|
|
pagy_query_result(@bookmarkable_items)
|
|
end
|
|
end
|
|
|
|
# GET /:locale/bookmark/:id
|
|
# GET /:locale/users/:user_id/bookmarks/:id
|
|
# GET /:locale/works/:work_id/bookmark/:id
|
|
# GET /:locale/external_works/:external_work_id/bookmark/:id
|
|
def show
|
|
end
|
|
|
|
# GET /bookmarks/new
|
|
# GET /bookmarks/new.xml
|
|
def new
|
|
@bookmark = Bookmark.new
|
|
respond_to do |format|
|
|
format.html
|
|
format.js {
|
|
@button_name = ts("Create")
|
|
@action = :create
|
|
render action: "bookmark_form_dynamic"
|
|
}
|
|
end
|
|
end
|
|
|
|
# GET /bookmarks/1/edit
|
|
def edit
|
|
@bookmarkable = @bookmark.bookmarkable
|
|
respond_to do |format|
|
|
format.html
|
|
format.js {
|
|
@button_name = ts("Update")
|
|
@action = :update
|
|
render action: "bookmark_form_dynamic"
|
|
}
|
|
end
|
|
end
|
|
|
|
# POST /bookmarks
|
|
# POST /bookmarks.xml
|
|
def create
|
|
@bookmarkable ||= ExternalWork.new(external_work_params)
|
|
@bookmark = Bookmark.new(bookmark_params.merge(bookmarkable: @bookmarkable))
|
|
if @bookmark.errors.empty? && @bookmark.save
|
|
flash[:notice] = ts("Bookmark was successfully created. It should appear in bookmark listings within the next few minutes.")
|
|
redirect_to(bookmark_path(@bookmark))
|
|
else
|
|
render :new
|
|
end
|
|
end
|
|
|
|
# PUT /bookmarks/1
|
|
# PUT /bookmarks/1.xml
|
|
def update
|
|
new_collections = []
|
|
unapproved_collections = []
|
|
errors = []
|
|
bookmark_params[:collection_names]&.split(",")&.map(&:strip)&.uniq&.each do |collection_name|
|
|
collection = Collection.find_by(name: collection_name)
|
|
if collection.nil?
|
|
errors << ts("%{name} does not exist.", name: collection_name)
|
|
else
|
|
if @bookmark.collections.include?(collection)
|
|
next
|
|
elsif collection.closed? && !collection.user_is_maintainer?(User.current_user)
|
|
errors << ts("%{title} is closed to new submissions.", title: collection.title)
|
|
elsif @bookmark.add_to_collection(collection) && @bookmark.save
|
|
if @bookmark.approved_collections.include?(collection)
|
|
new_collections << collection
|
|
else
|
|
unapproved_collections << collection
|
|
end
|
|
else
|
|
errors << ts("Something went wrong trying to add collection %{title}, sorry!", title: collection.title)
|
|
end
|
|
end
|
|
end
|
|
|
|
# messages to the user
|
|
unless errors.empty?
|
|
flash[:error] = ts("We couldn't add your submission to the following collections: ") + errors.join("<br />")
|
|
end
|
|
|
|
unless new_collections.empty?
|
|
flash[:notice] = ts("Added to collection(s): %{collections}.",
|
|
collections: new_collections.collect(&:title).join(", "))
|
|
end
|
|
unless unapproved_collections.empty?
|
|
flash[:notice] = flash[:notice] ? flash[:notice] + " " : ""
|
|
flash[:notice] += if unapproved_collections.size > 1
|
|
ts("You have submitted your bookmark to moderated collections (%{all_collections}). It will not become a part of those collections until it has been approved by a moderator.", all_collections: unapproved_collections.map(&:title).join(", "))
|
|
else
|
|
ts("You have submitted your bookmark to the moderated collection '%{collection}'. It will not become a part of the collection until it has been approved by a moderator.", collection: unapproved_collections.first.title)
|
|
end
|
|
end
|
|
|
|
flash[:notice] = (flash[:notice]).html_safe unless flash[:notice].blank?
|
|
flash[:error] = (flash[:error]).html_safe unless flash[:error].blank?
|
|
|
|
if @bookmark.update(bookmark_params) && errors.empty?
|
|
flash[:notice] = flash[:notice] ? " " + flash[:notice] : ""
|
|
flash[:notice] = ts("Bookmark was successfully updated.").html_safe + flash[:notice]
|
|
flash[:notice] = flash[:notice].html_safe
|
|
redirect_to(@bookmark)
|
|
else
|
|
@bookmarkable = @bookmark.bookmarkable
|
|
render :edit and return
|
|
end
|
|
end
|
|
|
|
# GET /bookmarks/1/share
|
|
def share
|
|
if request.xhr?
|
|
if @bookmark.bookmarkable.is_a?(Work) && @bookmark.bookmarkable.unrevealed?
|
|
render template: "errors/404", status: :not_found
|
|
else
|
|
render layout: false
|
|
end
|
|
else
|
|
# Avoid getting an unstyled page if JavaScript is disabled
|
|
flash[:error] = ts("Sorry, you need to have JavaScript enabled for this.")
|
|
redirect_back(fallback_location: root_path)
|
|
end
|
|
end
|
|
|
|
def confirm_delete
|
|
end
|
|
|
|
# DELETE /bookmarks/1
|
|
# DELETE /bookmarks/1.xml
|
|
def destroy
|
|
@bookmark.destroy
|
|
flash[:notice] = ts("Bookmark was successfully deleted.")
|
|
redirect_to user_bookmarks_path(current_user)
|
|
end
|
|
|
|
protected
|
|
|
|
def load_owner
|
|
if params[:user_id].present?
|
|
@user = User.find_by(login: params[:user_id])
|
|
unless @user
|
|
raise ActiveRecord::RecordNotFound, "Couldn't find user named '#{params[:user_id]}'"
|
|
end
|
|
if params[:pseud_id].present?
|
|
@pseud = @user.pseuds.find_by(name: params[:pseud_id])
|
|
unless @pseud
|
|
raise ActiveRecord::RecordNotFound, "Couldn't find pseud named '#{params[:pseud_id]}'"
|
|
end
|
|
end
|
|
end
|
|
if params[:tag_id]
|
|
@tag = Tag.find_by_name(params[:tag_id])
|
|
unless @tag
|
|
raise ActiveRecord::RecordNotFound, "Couldn't find tag named '#{params[:tag_id]}'"
|
|
end
|
|
unless @tag.canonical?
|
|
if @tag.merger.present?
|
|
redirect_to tag_bookmarks_path(@tag.merger) and return
|
|
else
|
|
redirect_to tag_path(@tag) and return
|
|
end
|
|
end
|
|
end
|
|
@owner = @bookmarkable || @pseud || @user || @collection || @tag
|
|
end
|
|
|
|
def index_page_title
|
|
if @owner.present?
|
|
owner_name = case @owner.class.to_s
|
|
when 'Pseud'
|
|
@owner.name
|
|
when 'User'
|
|
@owner.login
|
|
when 'Collection'
|
|
@owner.title
|
|
else
|
|
@owner.try(:name)
|
|
end
|
|
"#{owner_name} - Bookmarks".html_safe
|
|
else
|
|
"Latest Bookmarks"
|
|
end
|
|
end
|
|
|
|
def set_own_bookmarks
|
|
return unless @bookmarks
|
|
@own_bookmarks = []
|
|
if current_user.is_a?(User)
|
|
pseud_ids = current_user.pseuds.pluck(:id)
|
|
@own_bookmarks = @bookmarks.select do |b|
|
|
pseud_ids.include?(b.pseud_id)
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def bookmark_params
|
|
params.require(:bookmark).permit(
|
|
:pseud_id, :bookmarker_notes, :tag_string, :collection_names, :private, :rec
|
|
)
|
|
end
|
|
|
|
def external_work_params
|
|
params.require(:external_work).permit(
|
|
:url, :author, :title, :fandom_string, :rating_string, :relationship_string,
|
|
:character_string, :summary, category_strings: []
|
|
)
|
|
end
|
|
|
|
def bookmark_search_params
|
|
params.require(:bookmark_search).permit(
|
|
:bookmark_query,
|
|
:bookmarkable_query,
|
|
:bookmarker,
|
|
:bookmark_notes,
|
|
:rec,
|
|
:with_notes,
|
|
:bookmarkable_type,
|
|
:language_id,
|
|
:date,
|
|
:bookmarkable_date,
|
|
:sort_column,
|
|
:other_tag_names,
|
|
:excluded_tag_names,
|
|
:other_bookmark_tag_names,
|
|
:excluded_bookmark_tag_names,
|
|
rating_ids: [],
|
|
warning_ids: [], # backwards compatibility
|
|
archive_warning_ids: [],
|
|
category_ids: [],
|
|
fandom_ids: [],
|
|
character_ids: [],
|
|
relationship_ids: [],
|
|
freeform_ids: [],
|
|
tag_ids: [],
|
|
)
|
|
end
|
|
end
|