impress/app/controllers/items_controller.rb

273 lines
8.5 KiB
Ruby
Raw Normal View History

2010-05-15 10:47:46 -07:00
class ItemsController < ApplicationController
before_action :set_query
before_action :support_staff_only, except: [:index, :show, :sources]
rescue_from Item::Search::Error, :with => :search_error
2010-05-15 10:47:46 -07:00
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,
}
}
2010-05-15 10:47:46 -07:00
end
2010-10-10 19:18:42 -07:00
elsif params.has_key?(:ids) && params[:ids].is_a?(Array)
@items = Item.find(params[:ids])
assign_closeted!(@items)
2010-10-10 19:18:42 -07:00
respond_to do |format|
format.json { render json: @items }
2010-10-10 19:18:42 -07:00
end
else
respond_to do |format|
2011-08-04 07:01:44 -07:00
format.html {
@campaign = Fundraising::Campaign.current rescue nil
@newest_items = Item.newest.limit(18)
2011-08-04 07:01:44 -07:00
}
end
2010-05-15 10:47:46 -07:00
end
end
2010-05-15 17:46:41 -07:00
def show
@item = Item.find params[:id]
2011-07-30 21:19:28 -07:00
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 }
2024-09-05 18:48:41 -07:00
@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
2011-07-14 09:50:24 -07:00
end
2010-05-15 17:46:41 -07:00
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
2011-07-12 22:21:48 -07:00
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?
2011-07-12 22:21:48 -07:00
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
2010-06-07 17:02:46 -07:00
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
2010-06-07 17:02:46 -07:00
end
2010-05-15 10:47:46 -07:00
end