Compare commits
No commits in common. "e4a640cceed4c1a33ed554f3faa10afcb6c96ef2" and "d66f81c96b73a1df5263abb4ed85923db70a41bc" have entirely different histories.
e4a640ccee
...
d66f81c96b
24 changed files with 111 additions and 662 deletions
|
@ -1,23 +0,0 @@
|
|||
#title:has(+ .breadcrumbs)
|
||||
margin-bottom: .125em
|
||||
|
||||
.breadcrumbs
|
||||
list-style-type: none
|
||||
display: flex
|
||||
flex-direction: row
|
||||
margin-block: .5em
|
||||
font-size: .85em
|
||||
|
||||
li
|
||||
display: flex
|
||||
|
||||
li:not(:first-child)
|
||||
&::before
|
||||
margin-inline: .35em
|
||||
content: "→"
|
||||
|
||||
&[data-relation-to-prev=sibling]::before
|
||||
content: "+"
|
||||
|
||||
&[data-relation-to-prev=menu]::before
|
||||
content: "-"
|
|
@ -1,110 +0,0 @@
|
|||
@import "../partials/clean/constants"
|
||||
|
||||
// When loading, fade in the loading spinner after a brief delay. We only apply
|
||||
// the delay here, not on the base styles, because fading *out* on load should
|
||||
// be instant.
|
||||
//
|
||||
// This is implemented as a mixin, so that the item page can leverage the same
|
||||
// loading state when loading a new preview altogether. Once CSS container
|
||||
// style queries gain wider support, maybe use that instead.
|
||||
=outfit-viewer-loading
|
||||
cursor: wait
|
||||
|
||||
.loading-indicator
|
||||
opacity: 1
|
||||
transition-delay: 2s
|
||||
|
||||
// If the outfit *starts* in loading state, still delay the fade-in.
|
||||
@starting-style
|
||||
opacity: 0
|
||||
|
||||
outfit-viewer
|
||||
display: block
|
||||
position: relative
|
||||
overflow: hidden
|
||||
|
||||
// These are default widths, expected to often be overridden.
|
||||
width: 300px
|
||||
height: 300px
|
||||
|
||||
// There's no useful text in here, but double-clicking the play/pause
|
||||
// button can cause a weird selection state. Disable text selection.
|
||||
user-select: none
|
||||
-webkit-user-select: none
|
||||
|
||||
outfit-layer
|
||||
display: block
|
||||
position: absolute
|
||||
inset: 0
|
||||
|
||||
// We disable pointer-events most importantly for the iframes, which
|
||||
// will ignore our `cursor: wait` and show a plain cursor for the
|
||||
// inside of its own document. But also, the context menus for these
|
||||
// elements are kinda actively misleading, too!
|
||||
pointer-events: none
|
||||
|
||||
img, iframe
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
.loading-indicator
|
||||
position: absolute
|
||||
z-index: 1000
|
||||
bottom: 0px
|
||||
right: 4px
|
||||
padding: 8px
|
||||
background: radial-gradient(circle closest-side, white 45%, #ffffff00)
|
||||
|
||||
opacity: 0
|
||||
|
||||
.play-pause-button
|
||||
position: absolute
|
||||
z-index: 1001
|
||||
left: 8px
|
||||
bottom: 8px
|
||||
display: none
|
||||
align-items: center
|
||||
justify-content: center
|
||||
color: white
|
||||
background: rgba(0, 0, 0, 0.64)
|
||||
width: 2.5em
|
||||
height: 2.5em
|
||||
border-radius: 100%
|
||||
border: 2px solid transparent
|
||||
transition: all .25s
|
||||
|
||||
.playing-label, .paused-label
|
||||
display: none
|
||||
width: 1em
|
||||
height: 1em
|
||||
|
||||
.play-pause-toggle
|
||||
// Visually hidden
|
||||
clip: rect(0 0 0 0)
|
||||
clip-path: inset(50%)
|
||||
height: 1px
|
||||
overflow: hidden
|
||||
position: absolute
|
||||
white-space: nowrap
|
||||
width: 1px
|
||||
|
||||
&:checked ~ .playing-label
|
||||
display: block
|
||||
|
||||
&:not(:checked) ~ .paused-label
|
||||
display: block
|
||||
|
||||
&:hover, &:has(.play-pause-toggle:focus)
|
||||
border: 2px solid $module-border-color
|
||||
background: $module-bg-color
|
||||
color: $text-color
|
||||
|
||||
&:has(.play-pause-toggle:active)
|
||||
transform: translateY(2px)
|
||||
|
||||
&:has(outfit-layer:state(has-animations))
|
||||
.play-pause-button
|
||||
display: flex
|
||||
|
||||
&:has(outfit-layer:state(loading))
|
||||
+outfit-viewer-loading
|
|
@ -2,8 +2,6 @@
|
|||
@import "../partials/clean/mixins"
|
||||
@import "../partials/item_header"
|
||||
|
||||
@import "../application/outfit-viewer"
|
||||
|
||||
#container
|
||||
width: 900px // A bit more generous to the preview area!
|
||||
|
||||
|
@ -80,10 +78,93 @@
|
|||
width: var(--natural-width)
|
||||
|
||||
outfit-viewer
|
||||
display: block
|
||||
position: relative
|
||||
width: 300px
|
||||
height: 300px
|
||||
border: 1px solid $module-border-color
|
||||
border-radius: 1em
|
||||
overflow: hidden
|
||||
|
||||
// There's no useful text in here, but double-clicking the play/pause
|
||||
// button can cause a weird selection state. Disable text selection.
|
||||
user-select: none
|
||||
-webkit-user-select: none
|
||||
|
||||
outfit-layer
|
||||
display: block
|
||||
position: absolute
|
||||
inset: 0
|
||||
|
||||
// We disable pointer-events most importantly for the iframes, which
|
||||
// will ignore our `cursor: wait` and show a plain cursor for the
|
||||
// inside of its own document. But also, the context menus for these
|
||||
// elements are kinda actively misleading, too!
|
||||
pointer-events: none
|
||||
|
||||
img, iframe
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
.loading-indicator
|
||||
position: absolute
|
||||
z-index: 1000
|
||||
bottom: 0px
|
||||
right: 4px
|
||||
padding: 8px
|
||||
background: radial-gradient(circle closest-side, white 45%, #ffffff00)
|
||||
|
||||
opacity: 0
|
||||
transition: opacity .5s
|
||||
|
||||
.play-pause-button
|
||||
position: absolute
|
||||
z-index: 1001
|
||||
left: 8px
|
||||
bottom: 8px
|
||||
display: none
|
||||
align-items: center
|
||||
justify-content: center
|
||||
color: white
|
||||
background: rgba(0, 0, 0, 0.64)
|
||||
width: 2.5em
|
||||
height: 2.5em
|
||||
border-radius: 100%
|
||||
border: 2px solid transparent
|
||||
transition: all .25s
|
||||
|
||||
.playing-label, .paused-label
|
||||
display: none
|
||||
width: 1em
|
||||
height: 1em
|
||||
|
||||
.play-pause-toggle
|
||||
// Visually hidden
|
||||
clip: rect(0 0 0 0)
|
||||
clip-path: inset(50%)
|
||||
height: 1px
|
||||
overflow: hidden
|
||||
position: absolute
|
||||
white-space: nowrap
|
||||
width: 1px
|
||||
|
||||
&:checked ~ .playing-label
|
||||
display: block
|
||||
|
||||
&:not(:checked) ~ .paused-label
|
||||
display: block
|
||||
|
||||
&:hover, &:has(.play-pause-toggle:focus)
|
||||
border: 2px solid $module-border-color
|
||||
background: $module-bg-color
|
||||
color: $text-color
|
||||
|
||||
&:has(.play-pause-toggle:active)
|
||||
transform: translateY(2px)
|
||||
|
||||
&:has(outfit-layer:state(has-animations))
|
||||
.play-pause-button
|
||||
display: flex
|
||||
|
||||
.error-indicator
|
||||
font-size: 85%
|
||||
|
@ -98,8 +179,16 @@ outfit-viewer
|
|||
//
|
||||
// We only apply the delay here, not on the base styles, because fading
|
||||
// *out* on load should be instant.
|
||||
#item-preview[busy] outfit-viewer
|
||||
+outfit-viewer-loading
|
||||
#item-preview[busy] outfit-viewer, outfit-viewer:has(outfit-layer:state(loading))
|
||||
cursor: wait
|
||||
|
||||
.loading-indicator
|
||||
opacity: 1
|
||||
transition-delay: 2s
|
||||
|
||||
// If the outfit *starts* in loading state, still delay the fade-in.
|
||||
@starting-style
|
||||
opacity: 0
|
||||
|
||||
#item-preview:has(outfit-layer:state(error))
|
||||
outfit-viewer
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
@import "../partials/clean/constants"
|
||||
|
||||
outfit-viewer
|
||||
margin: 0 auto
|
||||
|
||||
.pose-options
|
||||
list-style-type: none
|
||||
display: grid
|
||||
grid-template-columns: 1fr 1fr 1fr
|
||||
gap: .25em
|
||||
|
||||
label
|
||||
display: flex
|
||||
align-items: center
|
||||
gap: .5em
|
||||
padding: .5em 1em
|
||||
border: 1px solid $soft-border-color
|
||||
border-radius: 1em
|
||||
|
||||
input
|
||||
margin: 0
|
||||
|
||||
&:has(:checked)
|
||||
background: $module-bg-color
|
||||
border-color: $module-border-color
|
|
@ -1,5 +0,0 @@
|
|||
outfit-viewer
|
||||
margin: 0 auto
|
||||
|
||||
dt
|
||||
cursor: help
|
|
@ -1,55 +0,0 @@
|
|||
@import "../partials/clean/constants"
|
||||
|
||||
.pet-filters
|
||||
fieldset
|
||||
display: flex
|
||||
flex-direction: row
|
||||
align-items: center
|
||||
justify-content: center
|
||||
gap: .5em
|
||||
|
||||
legend
|
||||
display: contents
|
||||
font-weight: bold
|
||||
|
||||
[role=navigation]
|
||||
margin-block: .5em
|
||||
text-align: center
|
||||
|
||||
.pet-types
|
||||
list-style-type: none
|
||||
display: flex
|
||||
flex-wrap: wrap
|
||||
justify-content: center
|
||||
gap: .5em
|
||||
|
||||
> li
|
||||
width: 150px
|
||||
max-width: calc(50% - .25em)
|
||||
min-width: 150px
|
||||
box-sizing: border-box
|
||||
text-align: center
|
||||
|
||||
a
|
||||
display: block
|
||||
border-radius: 1em
|
||||
padding: .5em
|
||||
text-decoration: none
|
||||
background: white
|
||||
&:hover
|
||||
outline: 1px solid $module-border-color
|
||||
background: $module-bg-color
|
||||
|
||||
img
|
||||
width: 100%
|
||||
height: auto
|
||||
aspect-ratio: 1 / 1
|
||||
margin-bottom: -1em
|
||||
|
||||
.name
|
||||
background: inherit
|
||||
padding: .25em .5em
|
||||
border-radius: .5em
|
||||
margin: 0 auto
|
||||
position: relative
|
||||
z-index: 1
|
|
@ -1,43 +0,0 @@
|
|||
@import "../partials/clean/constants"
|
||||
|
||||
.pet-states
|
||||
list-style-type: none
|
||||
display: flex
|
||||
flex-wrap: wrap
|
||||
justify-content: center
|
||||
gap: .5em
|
||||
|
||||
> li
|
||||
width: 200px
|
||||
max-width: calc(50% - .25em)
|
||||
min-width: 150px
|
||||
box-sizing: border-box
|
||||
text-align: center
|
||||
|
||||
a
|
||||
display: block
|
||||
border-radius: 1em
|
||||
padding: .5em
|
||||
background: white
|
||||
text-decoration: none
|
||||
&:hover
|
||||
outline: 1px solid $module-border-color
|
||||
background: $module-bg-color
|
||||
|
||||
outfit-viewer
|
||||
width: 100%
|
||||
height: auto
|
||||
aspect-ratio: 1 / 1
|
||||
position: relative
|
||||
z-index: 0
|
||||
margin-bottom: -1em
|
||||
|
||||
.name
|
||||
background: inherit
|
||||
padding: .25em .5em
|
||||
border-radius: .5em
|
||||
position: relative
|
||||
z-index: 1
|
||||
|
||||
.glitched
|
||||
cursor: help
|
|
@ -110,11 +110,5 @@ class ApplicationController < ActionController::Base
|
|||
Rails.logger.debug "Using return_to path: #{return_to.inspect}"
|
||||
return_to || root_path
|
||||
end
|
||||
|
||||
def support_staff_only
|
||||
unless current_user&.support_staff?
|
||||
raise AccessDenied, "Support staff only"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
class PetStatesController < ApplicationController
|
||||
before_action :find_pet_state
|
||||
before_action :support_staff_only, except: [:show]
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
if @pet_state.update(pet_state_params)
|
||||
flash[:notice] = "Pet appearance \##{@pet_state.id} successfully saved!"
|
||||
redirect_to @pet_type
|
||||
else
|
||||
render action: :edit, status: :bad_request
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def find_pet_state
|
||||
@pet_type = PetType.matching_name_param(params[:pet_type_name]).first!
|
||||
@pet_state = @pet_type.pet_states.find(params[:id])
|
||||
end
|
||||
|
||||
def pet_state_params
|
||||
params.require(:pet_state).permit(:pose, :glitched)
|
||||
end
|
||||
end
|
|
@ -1,78 +1,10 @@
|
|||
class PetTypesController < ApplicationController
|
||||
def index
|
||||
@species_names = Species.order(:name).map(&:human_name)
|
||||
@color_names = Color.order(:name).map(&:human_name)
|
||||
|
||||
if params[:species].present?
|
||||
@selected_species = Species.find_by!(name: params[:species])
|
||||
@selected_species_name = @selected_species.human_name
|
||||
end
|
||||
if params[:color].present?
|
||||
@selected_color = Color.find_by!(name: params[:color])
|
||||
@selected_color_name = @selected_color.human_name
|
||||
end
|
||||
|
||||
@pet_types = PetType.
|
||||
includes(:color, :species).
|
||||
order(created_at: :desc).
|
||||
paginate(page: params[:page], per_page: 30)
|
||||
|
||||
if @selected_species
|
||||
@pet_types = @pet_types.where(species_id: @selected_species)
|
||||
end
|
||||
if @selected_color
|
||||
@pet_types = @pet_types.where(color_id: @selected_color)
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@pet_type = find_pet_type
|
||||
@pet_type = PetType.
|
||||
where(species_id: params[:species_id]).
|
||||
where(color_id: params[:color_id]).
|
||||
first
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
@pet_states = group_pet_states @pet_type.pet_states
|
||||
end
|
||||
format.json { render json: @pet_type }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# The API-ish route uses IDs, but the human-facing route uses names.
|
||||
def find_pet_type
|
||||
if params[:species_id] && params[:color_id]
|
||||
PetType.find_by!(
|
||||
species_id: params[:species_id],
|
||||
color_id: params[:color_id],
|
||||
)
|
||||
elsif params[:name]
|
||||
color_name, _, species_name = params[:name].rpartition("-")
|
||||
raise ActiveRecord::RecordNotFound if species_name.blank?
|
||||
PetType.matching_name(color_name, species_name).first!
|
||||
else
|
||||
raise "expected params: species_id and color_id, or name"
|
||||
end
|
||||
end
|
||||
|
||||
# The `canonical` pet states are the main ones we want to show: the most
|
||||
# canonical state for each pose. The `other` pet states are, the others!
|
||||
#
|
||||
# If no main poses are available, then we just make all the poses
|
||||
# "canonical", and show the whole mish-mash!
|
||||
MAIN_POSES = %w(HAPPY_FEM HAPPY_MASC SAD_FEM SAD_MASC SICK_FEM SICK_MASC)
|
||||
def group_pet_states(pet_states)
|
||||
pose_groups = pet_states.emotion_order.group_by(&:pose)
|
||||
main_groups = pose_groups.select { |k| MAIN_POSES.include?(k) }.values
|
||||
other_groups = pose_groups.reject { |k| MAIN_POSES.include?(k) }.values
|
||||
|
||||
if main_groups.empty?
|
||||
return {canonical: other_groups.flatten(1).sort_by(&:pose), other: []}
|
||||
end
|
||||
|
||||
canonical = main_groups.map(&:first).sort_by(&:pose)
|
||||
main_others = main_groups.map { |l| l.drop(1) }.flatten(1)
|
||||
other = (main_others + other_groups.flatten(1)).sort_by(&:pose)
|
||||
|
||||
{canonical:, other:}
|
||||
render json: @pet_type
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,30 +14,19 @@ module ItemsHelper
|
|||
}
|
||||
|
||||
Sizes = {
|
||||
face: 1, # 50x50
|
||||
face_3x: 6, # 150x150
|
||||
|
||||
thumb: 2, # 150x150
|
||||
full: 4, # 300x300
|
||||
large: 5, # 500x500
|
||||
xlarge: 7, # 640x640
|
||||
|
||||
zoom: 3, # 80x80
|
||||
autocrop: 9, # <varies>
|
||||
}
|
||||
|
||||
SizeUpgrades = {
|
||||
face: :face_3x,
|
||||
thumb: :full,
|
||||
full: :xlarge,
|
||||
face: 1,
|
||||
thumb: 2,
|
||||
zoom: 3,
|
||||
full: 4,
|
||||
face_2x: 6,
|
||||
}
|
||||
end
|
||||
|
||||
def pet_type_image_url(pet_type, emotion: :happy, size: :face)
|
||||
PetTypeImage::Template.expand(
|
||||
hash: pet_type.basic_image_hash || pet_type.image_hash,
|
||||
emotion: PetTypeImage::Emotions.fetch(emotion),
|
||||
size: PetTypeImage::Sizes.fetch(size),
|
||||
emotion: PetTypeImage::Emotions[emotion],
|
||||
size: PetTypeImage::Sizes[size],
|
||||
).to_s
|
||||
end
|
||||
|
||||
|
@ -257,10 +246,8 @@ module ItemsHelper
|
|||
|
||||
def pet_type_image(pet_type, emotion, size, **options)
|
||||
src = pet_type_image_url(pet_type, emotion:, size:)
|
||||
|
||||
size_2x = PetTypeImage::SizeUpgrades[size]
|
||||
srcset = if size_2x
|
||||
[[pet_type_image_url(pet_type, emotion:, size: size_2x), "2x"]]
|
||||
srcset = if size == :face
|
||||
[[pet_type_image_url(pet_type, emotion:, size: :face_2x), "2x"]]
|
||||
end
|
||||
|
||||
image_tag(src, srcset:, **options)
|
||||
|
|
|
@ -69,17 +69,5 @@ module OutfitsHelper
|
|||
options = {:spellcheck => false, :id => nil}.merge(options)
|
||||
text_field_tag 'name', nil, options
|
||||
end
|
||||
|
||||
def outfit_viewer(outfit_or_options)
|
||||
outfit = if outfit_or_options.is_a? Hash
|
||||
Outfit.new(outfit_or_options)
|
||||
elsif outfit_or_options.is_a? Outfit
|
||||
outfit_or_options
|
||||
else
|
||||
raise TypeError, "must be an outfit or hash of options to create one"
|
||||
end
|
||||
|
||||
render partial: "outfit_viewer", locals: {outfit:}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
module PetStatesHelper
|
||||
def pose_name(pose)
|
||||
case pose
|
||||
when "HAPPY_FEM"
|
||||
"Happy (Feminine)"
|
||||
when "HAPPY_MASC"
|
||||
"Happy (Masculine)"
|
||||
when "SAD_FEM"
|
||||
"Sad (Feminine)"
|
||||
when "SAD_MASC"
|
||||
"Sad (Masculine)"
|
||||
when "SICK_FEM"
|
||||
"Sick (Feminine)"
|
||||
when "SICK_MASC"
|
||||
"Sick (Masculine)"
|
||||
when "UNCONVERTED"
|
||||
"Unconverted"
|
||||
else
|
||||
"Not labeled yet"
|
||||
end
|
||||
end
|
||||
|
||||
POSE_OPTIONS = %w(HAPPY_FEM SAD_FEM SICK_FEM HAPPY_MASC SAD_MASC SICK_MASC
|
||||
UNCONVERTED UNKNOWN)
|
||||
def pose_options
|
||||
POSE_OPTIONS
|
||||
end
|
||||
|
||||
def useful_pet_state_path(...)
|
||||
if support_staff?
|
||||
edit_pet_type_pet_state_path(...)
|
||||
else
|
||||
pet_type_pet_state_path(...)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -71,28 +71,6 @@ class PetState < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: More and more, wanting to refactor poses…
|
||||
def pose=(pose)
|
||||
case pose
|
||||
when "UNKNOWN"
|
||||
label_pose nil, nil, unconverted: nil, labeled: false
|
||||
when "HAPPY_MASC"
|
||||
label_pose 1, false
|
||||
when "HAPPY_FEM"
|
||||
label_pose 1, true
|
||||
when "SAD_MASC"
|
||||
label_pose 2, false
|
||||
when "SAD_FEM"
|
||||
label_pose 2, true
|
||||
when "SICK_MASC"
|
||||
label_pose 4, false
|
||||
when "SICK_FEM"
|
||||
label_pose 4, true
|
||||
when "UNCONVERTED"
|
||||
label_pose nil, nil, unconverted: true
|
||||
end
|
||||
end
|
||||
|
||||
def reassign_children_to!(main_pet_state)
|
||||
self.contributions.each do |contribution|
|
||||
contribution.contributed = main_pet_state
|
||||
|
@ -132,7 +110,7 @@ class PetState < ApplicationRecord
|
|||
def swf_asset_ids=(ids)
|
||||
self['swf_asset_ids'] = ids
|
||||
end
|
||||
|
||||
|
||||
def handle_assets!
|
||||
@parent_swf_asset_relationships_to_update.each do |rel|
|
||||
rel.swf_asset.save!
|
||||
|
@ -140,10 +118,6 @@ class PetState < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def to_param
|
||||
"#{id}-#{pose.split('_').map(&:capitalize).join('-')}"
|
||||
end
|
||||
|
||||
def self.from_pet_type_and_biology_info(pet_type, info)
|
||||
swf_asset_ids = []
|
||||
info.each do |zone_id, asset_info|
|
||||
|
@ -197,15 +171,5 @@ class PetState < ApplicationRecord
|
|||
pet_state.parent_swf_asset_relationships_to_update = relationships
|
||||
pet_state
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# A helper for the `pose=` method.
|
||||
def label_pose(mood_id, female, unconverted: false, labeled: true)
|
||||
self.labeled = labeled
|
||||
self.mood_id = mood_id
|
||||
self.female = female
|
||||
self.unconverted = unconverted
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -15,10 +15,6 @@ class PetType < ApplicationRecord
|
|||
species = Species.find_by_name!(species_name)
|
||||
where(color_id: color.id, species_id: species.id)
|
||||
}
|
||||
scope :matching_name_param, ->(name_param) {
|
||||
color_name, _, species_name = name_param.rpartition("-")
|
||||
matching_name(color_name, species_name)
|
||||
}
|
||||
scope :preferring_species, ->(species_id) {
|
||||
joins(:species).order([Arel.sql("species_id = ? DESC"), species_id])
|
||||
}
|
||||
|
@ -112,10 +108,6 @@ class PetType < ApplicationRecord
|
|||
Item.appearances_for(item, self, ...)
|
||||
end
|
||||
|
||||
def to_param
|
||||
"#{color.human_name}-#{species.human_name}"
|
||||
end
|
||||
|
||||
def self.all_by_ids_or_children(ids, pet_states)
|
||||
pet_states_by_pet_type_id = {}
|
||||
pet_states.each do |pet_state|
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
- if swf_asset.canvas_movie?
|
||||
%iframe{src: swf_asset_path(swf_asset, playing: outfit_viewer_is_playing ? true : nil)}
|
||||
- elsif swf_asset.image_url.present?
|
||||
= image_tag swf_asset.image_url, alt: "", loading: "lazy"
|
||||
= image_tag swf_asset.image_url, alt: ""
|
||||
- else
|
||||
/ No movie or image available for SWF asset: #{swf_asset.url}
|
||||
/ No movie or image available for SWF asset: #{swf_asset.url}
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
= turbo_frame_tag "item-preview" do
|
||||
.preview-area
|
||||
= outfit_viewer @preview_outfit
|
||||
= render partial: "outfit_viewer", locals: {outfit: @preview_outfit}
|
||||
.error-indicator
|
||||
💥 We couldn't load all of this outfit. Try again?
|
||||
= link_to wardrobe_path(params: @preview_outfit.wardrobe_params),
|
||||
|
@ -122,8 +122,6 @@
|
|||
|
||||
- content_for :stylesheets do
|
||||
= stylesheet_link_tag "application/hanger-spinner"
|
||||
-# This is imported into items/show directly, to gain access to its mixins.
|
||||
-# = stylesheet_link_tag "application/outfit-viewer"
|
||||
= page_stylesheet_link_tag "layouts/items"
|
||||
= page_stylesheet_link_tag "items/show"
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
%li
|
||||
= link_to useful_pet_state_path(pet_state.pet_type, pet_state) do
|
||||
= outfit_viewer pet_state:
|
||||
.name= pose_name pet_state.pose
|
||||
- if pet_state.glitched?
|
||||
%span.glitched{title: "Glitched"} 👾
|
|
@ -1,50 +0,0 @@
|
|||
- title "#{@pet_type.human_name}: #{pose_name @pet_state.pose}"
|
||||
- use_responsive_design
|
||||
|
||||
%ol.breadcrumbs
|
||||
%li
|
||||
= link_to "Rainbow Pool", pet_types_path
|
||||
%li
|
||||
= link_to @pet_type.color.human_name,
|
||||
pet_types_path(color: @pet_type.color.human_name)
|
||||
%li{"data-relation-to-prev": "sibling"}
|
||||
= link_to @pet_type.species.human_name,
|
||||
pet_types_path(species: @pet_type.species.human_name)
|
||||
%li
|
||||
= link_to "Appearances", @pet_type
|
||||
%li
|
||||
= link_to "\##{@pet_state.id}", [@pet_type, @pet_state]
|
||||
%li
|
||||
Edit
|
||||
|
||||
= outfit_viewer pet_state: @pet_state
|
||||
|
||||
= form_with model: [@pet_type, @pet_state] do |f|
|
||||
- if @pet_state.errors.any?
|
||||
%p
|
||||
Could not save:
|
||||
%ul.errors
|
||||
- @pet_state.errors.each do |error|
|
||||
%li= error.full_message
|
||||
%dl
|
||||
%dt Pose
|
||||
%dd
|
||||
%ul.pose-options
|
||||
- pose_options.each do |pose|
|
||||
%li
|
||||
%label
|
||||
= f.radio_button :pose, pose
|
||||
= pose_name pose
|
||||
%dt Glitched?
|
||||
%dd
|
||||
= f.select :glitched, [["✅ Not marked as Glitched", false],
|
||||
["👾 Yes, it's bad news bonko'd", true]]
|
||||
= f.submit "Save"
|
||||
|
||||
- content_for :stylesheets do
|
||||
= stylesheet_link_tag "application/breadcrumbs"
|
||||
= stylesheet_link_tag "application/outfit-viewer"
|
||||
= page_stylesheet_link_tag "pet_states/edit"
|
||||
|
||||
- content_for :javascripts do
|
||||
= javascript_include_tag "outfit-viewer"
|
|
@ -1,54 +0,0 @@
|
|||
- title "#{@pet_type.human_name}: #{pose_name @pet_state.pose}"
|
||||
- use_responsive_design
|
||||
|
||||
%ol.breadcrumbs
|
||||
%li
|
||||
= link_to "Rainbow Pool", pet_types_path
|
||||
%li
|
||||
= link_to @pet_type.color.human_name,
|
||||
pet_types_path(color: @pet_type.color.human_name)
|
||||
%li{"data-relation-to-prev": "sibling"}
|
||||
= link_to @pet_type.species.human_name,
|
||||
pet_types_path(species: @pet_type.species.human_name)
|
||||
%li
|
||||
= link_to "Appearances", @pet_type
|
||||
%li
|
||||
\##{@pet_state.id}
|
||||
- if support_staff?
|
||||
%li{"data-relation-to-prev": "menu"}
|
||||
= link_to "Edit", edit_pet_type_pet_state_path(@pet_type, @pet_state)
|
||||
|
||||
= outfit_viewer pet_state: @pet_state
|
||||
|
||||
%dl
|
||||
%dt{title: "Pose usually affects just the eyes and mouth. Neopets " +
|
||||
"genders these as Male/Female, but I don't like those " +
|
||||
"terms for like… it's just eyelashes! Sheesh!"}
|
||||
Pose
|
||||
%dd
|
||||
= pose_name @pet_state.pose
|
||||
- if @pet_state.pose == "UNCONVERTED"
|
||||
(Retired, replaced by #{link_to "Alt Styles", alt_styles_path})
|
||||
|
||||
%dt{title: "This is our own internal ID number, nothing to do with " +
|
||||
"Neopets's official data."}
|
||||
DTI ID
|
||||
%dd= @pet_state.id
|
||||
|
||||
%dt{title: "When we notice a form looks wrong, we mark it Glitched, to " +
|
||||
"tell our systems to prefer other forms for this pose instead."}
|
||||
Glitched?
|
||||
%dd
|
||||
- if @pet_state.glitched?
|
||||
👾 Yes, it's bad news bonko'd
|
||||
- else
|
||||
✅ Not marked as Glitched
|
||||
|
||||
- content_for :stylesheets do
|
||||
= stylesheet_link_tag "application/breadcrumbs"
|
||||
= stylesheet_link_tag "application/hanger-spinner"
|
||||
= stylesheet_link_tag "application/outfit-viewer"
|
||||
= page_stylesheet_link_tag "pet_states/show"
|
||||
|
||||
- content_for :javascripts do
|
||||
= javascript_include_tag "outfit-viewer", async: true
|
|
@ -1,4 +0,0 @@
|
|||
%li
|
||||
= link_to pet_type do
|
||||
= pet_type_image pet_type, :happy, :thumb
|
||||
.name= pet_type.human_name
|
|
@ -1,18 +0,0 @@
|
|||
- title "Rainbow Pool"
|
||||
- use_responsive_design
|
||||
|
||||
= form_with method: :get, class: "pet-filters" do |form|
|
||||
%fieldset
|
||||
%legend Filter by:
|
||||
= form.select :color, @color_names, selected: @selected_color&.human_name, include_blank: "Color…"
|
||||
= form.select :species, @species_names, selected: @selected_species&.human_name, include_blank: "Species…"
|
||||
= form.submit "Go"
|
||||
|
||||
= will_paginate @pet_types
|
||||
|
||||
%ui.pet-types= render @pet_types
|
||||
|
||||
= will_paginate @pet_types
|
||||
|
||||
- content_for :stylesheets do
|
||||
= page_stylesheet_link_tag "pet_types/index"
|
|
@ -1,32 +0,0 @@
|
|||
- title "#{@pet_type.human_name}"
|
||||
- use_responsive_design
|
||||
|
||||
%ol.breadcrumbs
|
||||
%li
|
||||
= link_to "Rainbow Pool", pet_types_path
|
||||
%li
|
||||
= link_to @pet_type.color.human_name,
|
||||
pet_types_path(color: @pet_type.color.human_name)
|
||||
%li{"data-relation-to-prev": "sibling"}
|
||||
= link_to @pet_type.species.human_name,
|
||||
pet_types_path(species: @pet_type.species.human_name)
|
||||
%li
|
||||
Appearances
|
||||
|
||||
%ul.pet-states
|
||||
= render @pet_states[:canonical]
|
||||
|
||||
- if @pet_states[:other].present?
|
||||
%details
|
||||
%summary Other
|
||||
%ul.pet-states
|
||||
= render @pet_states[:other]
|
||||
|
||||
- content_for :stylesheets do
|
||||
= stylesheet_link_tag "application/breadcrumbs"
|
||||
= stylesheet_link_tag "application/hanger-spinner"
|
||||
= stylesheet_link_tag "application/outfit-viewer"
|
||||
= page_stylesheet_link_tag "pet_types/show"
|
||||
|
||||
- content_for :javascripts do
|
||||
= javascript_include_tag "outfit-viewer", async: true
|
|
@ -37,10 +37,6 @@ OpenneoImpressItems::Application.routes.draw do
|
|||
end
|
||||
resources :alt_styles, path: 'alt-styles', only: [:index]
|
||||
resources :swf_assets, path: 'swf-assets', only: [:show]
|
||||
resources :pet_types, path: 'rainbow-pool', param: "name",
|
||||
only: [:index, :show] do
|
||||
resources :pet_states, only: [:show, :edit, :update], path: "appearances"
|
||||
end
|
||||
|
||||
# Loading and modeling pets!
|
||||
post '/pets/load' => 'pets#load', :as => :load_pet
|
||||
|
|
Loading…
Reference in a new issue