From 36f8efadbff571f99371f372b96f023dd221913c Mon Sep 17 00:00:00 2001 From: Emi Matchu Date: Tue, 3 Sep 2024 12:55:10 -0700 Subject: [PATCH] Add more detailed zone occupy info to simplified item preview page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adapting what the Impress 2020 UI does, but in Ruby instead! I feel like this is case is really starting to show the power of doing this stuff in Rails instead of via an APIā€¦ we can *really* take advantage of our models and our handy idioms at all points. This is just so much less *code* than this feature takes in Node + GraphQL + React. --- app/assets/stylesheets/items/_show.sass | 4 ++++ app/controllers/items_controller.rb | 4 ++++ app/helpers/items_helper.rb | 8 ++++++++ app/models/item.rb | 23 ++++++++++++++++++++++- app/views/items/show.html.haml | 12 +++++++++--- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/items/_show.sass b/app/assets/stylesheets/items/_show.sass index 1eb0500a..d02e4f4c 100644 --- a/app/assets/stylesheets/items/_show.sass +++ b/app/assets/stylesheets/items/_show.sass @@ -183,3 +183,7 @@ body.items-show .no-zones font-style: italic opacity: .85 + + .zone-species-info + font-style: italic + text-decoration: underline dotted diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index a0f05f69..921843ad 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -89,6 +89,10 @@ class ItemsController < ApplicationController 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 } end format.gif do diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index 5a18522d..02829402 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -222,6 +222,14 @@ module ItemsHelper cookies["DTIOutfitViewerIsPlaying"] == "true" end + def item_zone_partial_fit?(appearances_in_zone, all_appearances) + appearances_in_zone.size < all_appearances.size + end + + def item_zone_species_list(appearances_in_zone) + appearances_in_zone.map(&:species).uniq.map(&:human_name).sort.join(", ") + end + private def pet_type_image(pet_type, emotion, size) diff --git a/app/models/item.rb b/app/models/item.rb index 4b141da8..8f74aa10 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -276,7 +276,7 @@ class Item < ApplicationRecord end @restricted_zone_ids end - + def occupied_zone_ids occupied_zones.map(&:id) end @@ -502,11 +502,16 @@ class Item < ApplicationRecord Appearance = Struct.new(:item, :body, :swf_assets) do include ActiveModel::Serializers::JSON delegate :present?, :empty?, to: :swf_assets + delegate :species, to: :body def attributes {item:, body:, swf_assets:} end + def occupied_zone_ids + swf_assets.map(&:zone_id).uniq.sort + end + def restricted_zone_ids return [] if empty? ([item] + swf_assets).map(&:restricted_zone_ids).flatten.uniq.sort @@ -550,6 +555,22 @@ class Item < ApplicationRecord Item.appearances_for([self], target, ...)[id] end + def appearances_by_occupied_zone_id + {}.tap do |h| + appearances.each do |appearance| + appearance.occupied_zone_ids.each do |zone_id| + h[zone_id] ||= [] + h[zone_id] << appearance + end + end + end + end + + def appearances_by_occupied_zone + zones_by_id = occupied_zones.to_h { |z| [z.id, z] } + appearances_by_occupied_zone_id.transform_keys { |zid| zones_by_id[zid] } + end + # Given a list of items, return how they look on the given target (either a # pet type or an alt style). def self.appearances_for(items, target, swf_asset_includes: []) diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index bf40971c..db2f3483 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -36,10 +36,16 @@ .item-zones-info %section %h3 Occupies - - if @item.occupied_zones.present? + - if @appearances_by_occupied_zone.present? %ul - - @item.occupied_zones.sort_by(&:label).each do |zone| - %li= zone.label + - @appearances_by_occupied_zone.each do |zone, appearances_in_zone| + %li + = zone.label + - if item_zone_partial_fit? appearances_in_zone, @all_appearances + %span.zone-species-info{ + title: item_zone_species_list(appearances_in_zone) + } + (#{appearances_in_zone.size} species) - else %span.no-zones (None)