impress/app/controllers/closet_hangers_controller.rb
Matchu a2feee2d9b Add support for is_manually_nc
A really really simple change! It works on the item page, the item
index page, item search, the homepage, and the item lists page.

The main reason I avoided this for so long (even before modernizing the
Rails app) was that the ElasticSearch stuff felt like it made it messy?
But now it's pretty simple, and it works in search already cuz I did
that when I implemented item search, so, nice!
2023-11-03 16:27:39 -07:00

281 lines
8.7 KiB
Ruby

class ClosetHangersController < ApplicationController
before_action :authorize_user!, :only => [:destroy, :create, :update, :update_quantities, :petpage]
before_action :find_item, :only => [:create, :update_quantities]
before_action :find_user, :only => [:index, :petpage, :update_quantities]
def destroy
if params[:list_id]
@closet_list = current_user.find_closet_list_by_id_or_null_owned params[:list_id]
@closet_list.hangers.destroy_all
respond_to do |format|
format.html {
flash[:notice] = t("closet_hangers.destroy_all.success")
redirect_back!(user_closet_hangers_path(current_user))
}
format.json { render :json => true }
end
elsif params[:ids]
ClosetHanger.transaction do
current_user.closet_hangers.where(id: params[:ids]).destroy_all
end
render json: true
else
@closet_hanger = current_user.closet_hangers.find params[:id]
@closet_hanger.destroy
@item = @closet_hanger.item
closet_hanger_destroyed
end
end
def index
is_user = user_signed_in? && current_user == @user
@public_perspective = params.has_key?(:public) || !is_user
@perspective_user = current_user unless @public_perspective
closet_lists = @user.closet_lists
unless @perspective_user == @user
# If we run this when the user matches, we'll end up with effectively:
# WHERE belongs_to_user AND (is_public OR belongs_to_user)
# and it's a bit silly to put the SQL server through a condition that's
# always true.
closet_lists = closet_lists.visible_to(@perspective_user)
end
@closet_lists_by_owned = find_closet_lists_by_owned(closet_lists)
visible_groups = @user.closet_hangers_groups_visible_to(@perspective_user)
@unlisted_closet_hangers_by_owned = find_unlisted_closet_hangers_by_owned(visible_groups)
items = []
@closet_lists_by_owned.each do |owned, lists|
lists.each do |list|
list.hangers.each do |hanger|
items << hanger.item
end
end
end
@unlisted_closet_hangers_by_owned.each do |owned, hangers|
hangers.each do |hanger|
items << hanger.item
end
end
if @public_perspective && user_signed_in?
current_user.assign_closeted_to_items!(items)
end
@campaign = Campaign.current
end
def petpage
# Find all closet lists, and also the hangers of the visible closet lists
closet_lists = @user.closet_lists.select([:id, :name, :hangers_owned]).alphabetical
if params[:filter]
# If user specified which lists should be visible, restrict to those
if params[:lists] && params[:lists].respond_to?(:keys)
visible_closet_lists = closet_lists.where(:id => params[:lists].keys)
else
visible_closet_lists = []
end
else
# Otherwise, default to public lists
visible_closet_lists = closet_lists.publicly_visible
end
@closet_lists_by_owned = closet_lists.group_by(&:hangers_owned)
@visible_closet_lists_by_owned = find_closet_lists_by_owned(visible_closet_lists)
# Find which groups (own/want) should be visible
if params[:filter]
# If user specified which groups should be visible, restrict to those
# (must be either true or false)
@visible_groups = []
if params[:groups] && params[:groups].respond_to?(:keys)
@visible_groups << true if params[:groups].keys.include?('true')
@visible_groups << false if params[:groups].keys.include?('false')
end
else
# Otherwise, default to public groups
@visible_groups = @user.public_closet_hangers_groups
end
@visible_unlisted_closet_hangers_by_owned =
find_unlisted_closet_hangers_by_owned(@visible_groups)
end
def create
@closet_hanger = current_user.closet_hangers.build(closet_hanger_params)
@closet_hanger.item = @item
if @closet_hanger.save
closet_hanger_saved
else
closet_hanger_invalid
end
end
def update
if params[:ids]
ClosetHanger.transaction do
@closet_hangers = current_user.closet_hangers.includes(:list).find params[:ids]
@closet_hangers.each do |h|
h.possibly_null_list_id = params[:list_id]
h.save!
end
end
redirect_back!(user_closet_hangers_path(current_user))
else
@closet_hanger = current_user.closet_hangers.find(params[:id])
@closet_hanger.attributes = closet_hanger_params
@item = @closet_hanger.item
unless @closet_hanger.quantity == 0 # save the hanger, new record or not
if @closet_hanger.save
closet_hanger_saved
else
closet_hanger_invalid
end
else # delete the hanger since the user doesn't want it
@closet_hanger.destroy
closet_hanger_destroyed
end
end
end
def update_quantities
begin
ClosetHanger.transaction do
params[:quantity].each do |key, quantity|
ClosetHanger.set_quantity!(quantity, :user_id => @user.id,
:item_id => @item.id, :key => key)
end
flash[:notice] = t('closet_hangers.update_quantities.success',
:item_name => @item.name)
end
rescue ActiveRecord::RecordInvalid => e
flash[:alert] = t('closet_hangers.update_quantities.invalid',
:errors => e.message)
end
redirect_to @item
end
private
def closet_hanger_params
params.require(:closet_hanger).permit(:list_id, :owned, :quantity)
end
def closet_hanger_destroyed
respond_to do |format|
format.html {
ownership_key = @closet_hanger.owned? ? 'owned' : 'wanted'
flash[:notice] = t("closet_hangers.destroy.success.#{ownership_key}",
:item_name => @item.name)
redirect_back!(@item)
}
format.json { render :json => true }
end
end
def closet_hanger_invalid
respond_to do |format|
format.html {
ownership_key = @closet_hanger.owned? ? 'owned' : 'wanted'
flash[:alert] = t("closet_hangers.create.invalid.#{ownership_key}",
:item_name => @item.name,
:errors => @closet_hanger.errors.full_messages.to_sentence)
redirect_back!(@item)
}
format.json { render :json => {:errors => @closet_hanger.errors.full_messages}, :status => :unprocessable_entity }
end
end
def closet_hanger_saved
respond_to do |format|
format.html {
ownership_key = @closet_hanger.owned? ? 'owned' : 'wanted'
if @closet_hanger.list
flash[:notice] = t("closet_hangers.create.success.#{ownership_key}.in_list",
:item_name => @item.name,
:list_name => @closet_hanger.list.name,
:count => @closet_hanger.quantity)
else
flash[:notice] = t("closet_hangers.create.success.#{ownership_key}.unlisted",
:item_name => @item.name,
:count => @closet_hanger.quantity)
end
redirect_back!(@item)
}
format.json { render :json => true }
end
end
def find_item
@item = Item.find params[:item_id]
end
def find_user
if params[:user_id]
@user = User.find params[:user_id]
elsif user_signed_in?
redirect_to user_closet_hangers_path(current_user)
else
redirect_to new_auth_user_session_path(:return_to => request.fullpath)
end
end
def find_closet_lists_by_owned(lists_scope)
return {} if lists_scope == []
lists = lists_scope.alphabetical
ClosetList.preload_items(
lists,
hangers_scope: hangers_scope,
items_scope: items_scope,
item_translations_scope: item_translations_scope,
)
lists.group_by(&:hangers_owned)
end
def find_unlisted_closet_hangers_by_owned(visible_groups)
unless visible_groups.empty?
hangers = @user.closet_hangers.unlisted.
owned_before_wanted.alphabetical_by_item_name.
where(:owned => [visible_groups])
ClosetHanger.preload_items(
hangers,
items_scope: items_scope,
item_translations_scope: item_translations_scope,
)
hangers.group_by(&:owned)
else
{}
end
end
def hangers_scope
ClosetHanger.select(:id, :item_id, :list_id, :quantity)
end
def items_scope
Item.select(:id, :thumbnail_url, :rarity_index, :is_manually_nc)
end
def item_translations_scope
Item::Translation.select(:id, :item_id, :locale, :name, :description).
where(locale: I18n.locale)
end
def owned
owned = true
if closet_hanger_params
owned = case closet_hanger_params[:owned]
when 'true', '1' then true
when 'false', '0' then false
end
end
end
end