272 lines
8.5 KiB
Ruby
272 lines
8.5 KiB
Ruby
class ItemsController < ApplicationController
|
|
before_action :set_query
|
|
before_action :support_staff_only, except: [:index, :show, :sources]
|
|
rescue_from Item::Search::Error, :with => :search_error
|
|
|
|
def index
|
|
if @query
|
|
if params[:per_page]
|
|
per_page = params[:per_page].to_i
|
|
per_page = 50 if per_page && per_page > 50
|
|
else
|
|
per_page = 30
|
|
end
|
|
|
|
@items = @query.results.paginate(
|
|
page: params[:page], per_page: per_page)
|
|
assign_closeted!(@items)
|
|
|
|
respond_to do |format|
|
|
format.html {
|
|
@campaign = Fundraising::Campaign.current rescue nil
|
|
if @items.count == 1
|
|
redirect_to @items.first
|
|
else
|
|
render
|
|
end
|
|
}
|
|
format.json {
|
|
render json: {
|
|
items: @items.as_json(
|
|
methods: [:nc?, :pb?, :owned?, :wanted?],
|
|
include: {
|
|
restricted_zones: {
|
|
only: [:id, :depth, :label],
|
|
methods: [:is_commonly_used_by_items],
|
|
},
|
|
},
|
|
),
|
|
appearances: load_appearances.as_json(
|
|
include: {
|
|
swf_assets: {
|
|
only: [:id, :remote_id, :body_id],
|
|
include: {
|
|
zone: {
|
|
only: [:id, :depth, :label],
|
|
methods: [:is_commonly_used_by_items],
|
|
},
|
|
restricted_zones: {
|
|
only: [:id, :depth, :label],
|
|
methods: [:is_commonly_used_by_items],
|
|
},
|
|
},
|
|
methods: [:urls, :known_glitches],
|
|
},
|
|
}
|
|
),
|
|
total_pages: @items.total_pages,
|
|
query: @query.to_s,
|
|
}
|
|
}
|
|
end
|
|
elsif params.has_key?(:ids) && params[:ids].is_a?(Array)
|
|
@items = Item.find(params[:ids])
|
|
assign_closeted!(@items)
|
|
respond_to do |format|
|
|
format.json { render json: @items }
|
|
end
|
|
else
|
|
respond_to do |format|
|
|
format.html {
|
|
@campaign = Fundraising::Campaign.current rescue nil
|
|
@newest_items = Item.newest.limit(18)
|
|
}
|
|
end
|
|
end
|
|
end
|
|
|
|
def show
|
|
@item = Item.find params[:id]
|
|
|
|
respond_to do |format|
|
|
format.html do
|
|
@trades = @item.closet_hangers.trading.user_is_active.to_trades
|
|
|
|
@contributors_with_counts = @item.contributors_with_counts
|
|
|
|
if user_signed_in?
|
|
@current_user_lists = current_user.closet_lists.alphabetical.
|
|
group_by_owned
|
|
@current_user_quantities = current_user.item_quantities_for(@item)
|
|
end
|
|
|
|
@selected_preview_pet_type = load_selected_preview_pet_type
|
|
@preview_outfit = Outfit.new(
|
|
pet_state: load_preview_pet_type.canonical_pet_state,
|
|
worn_items: [@item],
|
|
)
|
|
@preview_error = validate_preview
|
|
|
|
@all_appearances = @item.appearances
|
|
@appearances_by_occupied_zone = @item.appearances_by_occupied_zone.
|
|
sort_by { |z, a| z.label }
|
|
@selected_item_appearance = @preview_outfit.item_appearances.first
|
|
|
|
@preview_pet_type_options = PetType.where(color: @preview_outfit.color).
|
|
includes(:species).merge(Species.alphabetical)
|
|
end
|
|
|
|
format.gif do
|
|
expires_in 1.month
|
|
redirect_to @item.thumbnail_url, allow_other_host: true
|
|
end
|
|
end
|
|
end
|
|
|
|
def edit
|
|
@item = Item.find params[:id]
|
|
render layout: "application"
|
|
end
|
|
|
|
def update
|
|
@item = Item.find params[:id]
|
|
if @item.update(item_params)
|
|
flash[:notice] = "\"#{@item.name}\" successfully saved!"
|
|
redirect_to @item
|
|
else
|
|
render action: "edit", layout: "application"
|
|
end
|
|
end
|
|
|
|
def sources
|
|
# Load all the items, then group them by source.
|
|
item_ids = params[:ids].split(",")
|
|
@all_items = Item.where(id: item_ids).includes(:nc_mall_record).
|
|
includes(:dyeworks_base_item).order(:name).limit(50)
|
|
@items = @all_items.group_by(&:source).tap { |i| i.default = [] }
|
|
|
|
assign_closeted!(@all_items)
|
|
|
|
if @all_items.empty?
|
|
render file: "public/404.html", status: :not_found, layout: nil
|
|
return
|
|
end
|
|
|
|
# For Dyeworks items whose base is currently in the NC Mall, preload their
|
|
# trade values. We'll use this to determine which ones are fully buyable rn
|
|
# (because Owls tracks this data and we don't).
|
|
Item.preload_nc_trade_values(@items[:dyeworks])
|
|
|
|
# Start loading the NC trade values for the non-Mall NC items.
|
|
trade_values_task = Async { Item.preload_nc_trade_values(@items[:other_nc]) }
|
|
|
|
# Also, PB items have some special handling: we group them by color, then
|
|
# load example pet types for the colors that don't have paint brushes.
|
|
@pb_items_by_color = @items[:pb].group_by(&:pb_color).
|
|
sort_by { |color, items| color&.name }.to_h
|
|
|
|
colors_without_thumbnails = @pb_items_by_color.keys.
|
|
select(&:present?).reject(&:pb_item_thumbnail_url?)
|
|
|
|
@pb_color_pet_types = colors_without_thumbnails.map do |color|
|
|
# Infer the ideal species from the first item we can, then try to find a
|
|
# matching pet type to use as the thumbnail, if needed.
|
|
species = @pb_items_by_color[color].map(&:pb_species).select(&:present?)
|
|
.first
|
|
[color, color.example_pet_type(preferred_species: species)]
|
|
end.to_h
|
|
|
|
# Create a second value that only include the items the user *needs*: that
|
|
# is, that they don't already own.
|
|
@items_needed = @items.transform_values { |items| items.reject(&:owned?) }
|
|
@pb_items_needed_by_color =
|
|
@pb_items_by_color.transform_values { |items| items.reject(&:owned?) }
|
|
|
|
# Finish loading the NC trade values.
|
|
trade_values_task.wait
|
|
|
|
render layout: "application"
|
|
end
|
|
|
|
protected
|
|
|
|
def item_params
|
|
params.require(:item).permit(
|
|
:name, :thumbnail_url, :description, :modeling_status_hint,
|
|
:is_manually_nc, :explicitly_body_specific,
|
|
).tap do |p|
|
|
p[:modeling_status_hint] = nil if p[:modeling_status_hint] == ""
|
|
end
|
|
end
|
|
|
|
def assign_closeted!(items)
|
|
current_user.assign_closeted_to_items!(items) if user_signed_in?
|
|
end
|
|
|
|
def load_appearances
|
|
appearance_params = params[:with_appearances_for]
|
|
return {} if appearance_params.blank?
|
|
|
|
if appearance_params[:alt_style_id].present?
|
|
target = Item::Search::Query.load_alt_style_by_id(
|
|
appearance_params[:alt_style_id])
|
|
else
|
|
target = Item::Search::Query.load_pet_type_by_color_and_species(
|
|
appearance_params[:color_id], appearance_params[:species_id])
|
|
end
|
|
|
|
target.appearances_for(@items, swf_asset_includes: [:zone]).
|
|
tap do |appearances|
|
|
# Preload the manifests for these SWF assets concurrently, rather than
|
|
# loading them in sequence when we generate the JSON.
|
|
swf_assets = appearances.values.map(&:swf_assets).flatten
|
|
SwfAsset.preload_manifests(swf_assets)
|
|
end
|
|
end
|
|
|
|
def load_selected_preview_pet_type
|
|
color_id = params.dig(:preview, :color_id)
|
|
species_id = params.dig(:preview, :species_id)
|
|
|
|
return load_default_preview_pet_type if color_id.nil? || species_id.nil?
|
|
|
|
PetType.find_or_initialize_by(color_id:, species_id:).tap do |pet_type|
|
|
if pet_type.persisted?
|
|
cookies["preferred-preview-color-id"] = color_id
|
|
cookies["preferred-preview-species-id"] = species_id
|
|
end
|
|
end
|
|
end
|
|
|
|
def load_preview_pet_type
|
|
if @selected_preview_pet_type.persisted?
|
|
@selected_preview_pet_type
|
|
else
|
|
load_default_preview_pet_type
|
|
end
|
|
end
|
|
|
|
def load_default_preview_pet_type
|
|
@item.compatible_pet_types.
|
|
preferring_species(cookies["preferred-preview-species-id"] || "<ignore>").
|
|
preferring_color(cookies["preferred-preview-color-id"] || "<ignore>").
|
|
preferring_simple.first ||
|
|
PetType.matching_name("Blue", "Acara").first!
|
|
end
|
|
|
|
def validate_preview
|
|
if @selected_preview_pet_type.new_record?
|
|
:pet_type_does_not_exist
|
|
elsif @preview_outfit.item_appearances.any?(&:empty?)
|
|
:no_item_data
|
|
end
|
|
end
|
|
|
|
def search_error(e)
|
|
@items = []
|
|
@query = params[:q]
|
|
respond_to do |format|
|
|
format.html { flash.now[:alert] = e.message; render }
|
|
format.json { render :json => {error: e.message} }
|
|
end
|
|
end
|
|
|
|
def set_query
|
|
q = params[:q]
|
|
if q.is_a?(String)
|
|
@query = Item::Search::Query.from_text(q, current_user)
|
|
elsif q.is_a?(ActionController::Parameters)
|
|
@query = Item::Search::Query.from_params(q, current_user)
|
|
end
|
|
end
|
|
end
|