Compare commits
9 commits
fdbfa3c03f
...
d9bf4f745b
| Author | SHA1 | Date | |
|---|---|---|---|
| d9bf4f745b | |||
| 407c4b38a5 | |||
| 6dc5aa28a4 | |||
| b656ccd982 | |||
| 02836494ae | |||
| b6e6f27fdf | |||
| aeb00f73cf | |||
| 06a301e6d7 | |||
| 1119bbb292 |
15 changed files with 124 additions and 48 deletions
5
Gemfile
5
Gemfile
|
|
@ -66,7 +66,10 @@ gem "async-http", "~> 0.75.0", require: false
|
||||||
gem "thread-local", "~> 1.1", require: false
|
gem "thread-local", "~> 1.1", require: false
|
||||||
|
|
||||||
# For debugging.
|
# For debugging.
|
||||||
gem 'web-console', '~> 4.2', group: :development
|
group :development do
|
||||||
|
gem 'debug', '~> 1.9.2'
|
||||||
|
gem 'web-console', '~> 4.2'
|
||||||
|
end
|
||||||
|
|
||||||
# Reduces boot times through caching; required in config/boot.rb
|
# Reduces boot times through caching; required in config/boot.rb
|
||||||
gem 'bootsnap', '~> 1.16', require: false
|
gem 'bootsnap', '~> 1.16', require: false
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,9 @@ GEM
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
csv (3.3.0)
|
csv (3.3.0)
|
||||||
date (3.3.4)
|
date (3.3.4)
|
||||||
|
debug (1.9.2)
|
||||||
|
irb (~> 1.10)
|
||||||
|
reline (>= 0.3.8)
|
||||||
devise (4.9.4)
|
devise (4.9.4)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
orm_adapter (~> 0.1)
|
orm_adapter (~> 0.1)
|
||||||
|
|
@ -521,6 +524,7 @@ DEPENDENCIES
|
||||||
async (~> 2.17)
|
async (~> 2.17)
|
||||||
async-http (~> 0.75.0)
|
async-http (~> 0.75.0)
|
||||||
bootsnap (~> 1.16)
|
bootsnap (~> 1.16)
|
||||||
|
debug (~> 1.9.2)
|
||||||
devise (~> 4.9, >= 4.9.2)
|
devise (~> 4.9, >= 4.9.2)
|
||||||
devise-encryptable (~> 0.2.0)
|
devise-encryptable (~> 0.2.0)
|
||||||
dotenv-rails (~> 2.8, >= 2.8.1)
|
dotenv-rails (~> 2.8, >= 2.8.1)
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,10 @@
|
||||||
grid-template-columns: repeat(var(--num-columns, 1), 1fr)
|
grid-template-columns: repeat(var(--num-columns, 1), 1fr)
|
||||||
gap: .25em
|
gap: .25em
|
||||||
|
|
||||||
|
li
|
||||||
|
display: flex
|
||||||
|
align-items: stretch // Give the bubbles equal heights!
|
||||||
|
|
||||||
label
|
label
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
|
|
@ -51,6 +55,7 @@
|
||||||
padding: .5em 1em
|
padding: .5em 1em
|
||||||
border: 1px solid $soft-border-color
|
border: 1px solid $soft-border-color
|
||||||
border-radius: 1em
|
border-radius: 1em
|
||||||
|
flex: 1 1 auto
|
||||||
|
|
||||||
input
|
input
|
||||||
margin: 0
|
margin: 0
|
||||||
|
|
@ -89,7 +94,7 @@
|
||||||
align-items: center
|
align-items: center
|
||||||
gap: 1em
|
gap: 1em
|
||||||
|
|
||||||
label
|
.go-to-next
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
gap: .25em
|
gap: .25em
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,13 @@ outfit-viewer
|
||||||
|
|
||||||
.fields li[data-type=radio-grid]
|
.fields li[data-type=radio-grid]
|
||||||
--num-columns: 3
|
--num-columns: 3
|
||||||
|
|
||||||
|
.reference-link
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
gap: .5em
|
||||||
|
padding-inline: .5em
|
||||||
|
|
||||||
|
img
|
||||||
|
height: 2em
|
||||||
|
width: auto
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ class PetStatesController < ApplicationController
|
||||||
def update
|
def update
|
||||||
if @pet_state.update(pet_state_params)
|
if @pet_state.update(pet_state_params)
|
||||||
flash[:notice] = "Pet appearance \##{@pet_state.id} successfully saved!"
|
flash[:notice] = "Pet appearance \##{@pet_state.id} successfully saved!"
|
||||||
redirect_to @pet_type
|
redirect_to destination_after_save
|
||||||
else
|
else
|
||||||
render action: :edit, status: :bad_request
|
render action: :edit, status: :bad_request
|
||||||
end
|
end
|
||||||
|
|
@ -19,9 +19,35 @@ class PetStatesController < ApplicationController
|
||||||
def find_pet_state
|
def find_pet_state
|
||||||
@pet_type = PetType.find_by_param!(params[:pet_type_name])
|
@pet_type = PetType.find_by_param!(params[:pet_type_name])
|
||||||
@pet_state = @pet_type.pet_states.find(params[:id])
|
@pet_state = @pet_type.pet_states.find(params[:id])
|
||||||
|
@reference_pet_type = @pet_type.reference
|
||||||
end
|
end
|
||||||
|
|
||||||
def pet_state_params
|
def pet_state_params
|
||||||
params.require(:pet_state).permit(:pose, :glitched)
|
params.require(:pet_state).permit(:pose, :glitched)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destination_after_save
|
||||||
|
if params[:next] == "unlabeled-appearance"
|
||||||
|
next_unlabeled_appearance_path
|
||||||
|
else
|
||||||
|
@pet_type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_unlabeled_appearance_path
|
||||||
|
# Rather than just getting the newest unlabeled pet state, prioritize the
|
||||||
|
# newest *pet type*. This better matches the user's perception of what the
|
||||||
|
# newest state is, because the Rainbow Pool UI is grouped by pet type!
|
||||||
|
unlabeled_appearance = PetState.needs_labeling.newest_pet_type.newest.first
|
||||||
|
|
||||||
|
if unlabeled_appearance
|
||||||
|
edit_pet_type_pet_state_path(
|
||||||
|
unlabeled_appearance.pet_type,
|
||||||
|
unlabeled_appearance,
|
||||||
|
next: "unlabeled-appearance"
|
||||||
|
)
|
||||||
|
else
|
||||||
|
@pet_type
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,29 @@
|
||||||
module SupportFormHelper
|
module SupportFormHelper
|
||||||
class SupportFormBuilder < ActionView::Helpers::FormBuilder
|
class SupportFormBuilder < ActionView::Helpers::FormBuilder
|
||||||
attr_reader :template
|
attr_reader :template
|
||||||
delegate :concat, :content_tag, :image_tag, to: :template, private: true
|
delegate :capture, :check_box_tag, :content_tag, :params, :render,
|
||||||
|
to: :template, private: true
|
||||||
|
|
||||||
def errors
|
def errors
|
||||||
return nil if object.errors.empty?
|
render partial: "application/support_form/errors", locals: {form: self}
|
||||||
|
|
||||||
error_list = content_tag(:ul) do
|
|
||||||
object.errors.each do |error|
|
|
||||||
concat content_tag(:li, error.full_message)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
content_tag(:p) do
|
|
||||||
concat "Could not save:"
|
|
||||||
concat error_list
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def fields(&block)
|
def fields(&block)
|
||||||
content_tag(:ul, class: "fields", &block)
|
content_tag(:ul, class: "fields", &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def field(**kwargs, &block)
|
def field(**options, &block)
|
||||||
content_tag(:li, **kwargs, &block)
|
content_tag(:li, **options, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def radio_fieldset(legend, **kwargs, &block)
|
def radio_fieldset(legend, **options, &block)
|
||||||
kwargs.reverse_merge!("data-type": "radio")
|
render partial: "application/support_form/radio_fieldset",
|
||||||
field(**kwargs) do
|
locals: {form: self, legend:, options:, content: capture(&block)}
|
||||||
content_tag(:fieldset) do
|
|
||||||
concat content_tag(:legend, legend)
|
|
||||||
concat content_tag(:ul, &block)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def radio_field(**kwargs, &block)
|
def radio_field(**options, &block)
|
||||||
content_tag(:li) do
|
content_tag(:li) do
|
||||||
content_tag(:label, **kwargs, &block)
|
content_tag(:label, **options, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -47,19 +32,29 @@ module SupportFormHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def thumbnail_input(method)
|
def thumbnail_input(method)
|
||||||
url = object.send(method)
|
render partial: "application/support_form/thumbnail_input",
|
||||||
content_tag(:div, class: "thumbnail-input") do
|
locals: {form: self, method:}
|
||||||
concat image_tag(url, alt: "Thumbnail") if url.present?
|
|
||||||
concat url_field(method)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def actions(&block)
|
||||||
|
content_tag(:section, class: "actions", &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def go_to_next_field(**options, &block)
|
||||||
|
content_tag(:label, class: "go-to-next", **options, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def go_to_next_check_box(value)
|
||||||
|
check_box_tag "next", value, checked: params[:next] == value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def support_form_with(**kwargs, &block)
|
def support_form_with(**options, &block)
|
||||||
kwargs.merge!(
|
form_with(
|
||||||
builder: SupportFormBuilder,
|
builder: SupportFormBuilder,
|
||||||
class: ["support-form", kwargs[:class]],
|
**options,
|
||||||
|
class: ["support-form", options[:class]],
|
||||||
|
&block
|
||||||
)
|
)
|
||||||
form_with(**kwargs, &block)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,11 @@ class PetState < ApplicationRecord
|
||||||
|
|
||||||
alias_method :swf_asset_ids_from_association, :swf_asset_ids
|
alias_method :swf_asset_ids_from_association, :swf_asset_ids
|
||||||
|
|
||||||
|
scope :newest, -> { order(created_at: :desc) }
|
||||||
|
scope :newest_pet_type, -> { joins(:pet_type).merge(PetType.newest) }
|
||||||
|
scope :unlabeled, -> { with_pose("UNKNOWN") }
|
||||||
|
scope :needs_labeling, -> { unlabeled.where(glitched: false) }
|
||||||
|
|
||||||
# A simple ordering that tries to bring reliable pet states to the front.
|
# A simple ordering that tries to bring reliable pet states to the front.
|
||||||
scope :emotion_order, -> {
|
scope :emotion_order, -> {
|
||||||
order(Arel.sql(
|
order(Arel.sql(
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ class PetType < ApplicationRecord
|
||||||
species = Species.find_by_name!(species_name)
|
species = Species.find_by_name!(species_name)
|
||||||
where(color_id: color.id, species_id: species.id)
|
where(color_id: color.id, species_id: species.id)
|
||||||
}
|
}
|
||||||
|
scope :newest, -> { order(created_at: :desc) }
|
||||||
scope :preferring_species, ->(species_id) {
|
scope :preferring_species, ->(species_id) {
|
||||||
joins(:species).order([Arel.sql("species_id = ? DESC"), species_id])
|
joins(:species).order([Arel.sql("species_id = ? DESC"), species_id])
|
||||||
}
|
}
|
||||||
|
|
@ -136,6 +137,10 @@ class PetType < ApplicationRecord
|
||||||
pet_states.count { |ps| ps.pose == "UNKNOWN" }
|
pet_states.count { |ps| ps.pose == "UNKNOWN" }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reference
|
||||||
|
PetType.where(species_id: species).basic.merge(Color.alphabetical).first
|
||||||
|
end
|
||||||
|
|
||||||
def self.find_by_param!(param)
|
def self.find_by_param!(param)
|
||||||
raise ActiveRecord::RecordNotFound unless param.include?("-")
|
raise ActiveRecord::RecordNotFound unless param.include?("-")
|
||||||
color_param, _, species_param = param.rpartition("-")
|
color_param, _, species_param = param.rpartition("-")
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,10 @@
|
||||||
= f.label :thumbnail_url, "Thumbnail"
|
= f.label :thumbnail_url, "Thumbnail"
|
||||||
= f.thumbnail_input :thumbnail_url
|
= f.thumbnail_input :thumbnail_url
|
||||||
|
|
||||||
.actions
|
= f.actions do
|
||||||
= f.submit "Save changes"
|
= f.submit "Save changes"
|
||||||
%label{title: "If checked, takes you to the next unlabeled pet style, if any. Useful for labeling in bulk!"}
|
= f.go_to_next_field title: "If checked, takes you to the next unlabeled pet style, if any. Useful for labeling in bulk!" do
|
||||||
= check_box_tag "next", "unlabeled-style",
|
= f.go_to_next_check_box "unlabeled-style"
|
||||||
checked: params[:next] == "unlabeled-style"
|
|
||||||
Then: Go to unlabeled style
|
Then: Go to unlabeled style
|
||||||
|
|
||||||
- content_for :stylesheets do
|
- content_for :stylesheets do
|
||||||
|
|
|
||||||
7
app/views/application/support_form/_errors.html.haml
Normal file
7
app/views/application/support_form/_errors.html.haml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
- if form.object.errors.any?
|
||||||
|
%section.errors
|
||||||
|
Could not save:
|
||||||
|
|
||||||
|
%ul
|
||||||
|
- form.object.errors.each do |error|
|
||||||
|
%li= error.full_message
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
= form.field("data-type": "radio", **options) do
|
||||||
|
%fieldset
|
||||||
|
%legend= legend
|
||||||
|
%ul= content
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
- url = form.object.send(method)
|
||||||
|
.thumbnail-input
|
||||||
|
- if url.present?
|
||||||
|
= image_tag url, alt: "Thumbnail"
|
||||||
|
= form.url_field method
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
= f.radio_button :explicitly_body_specific, true
|
= f.radio_button :explicitly_body_specific, true
|
||||||
Body-specific: Fits all species differently
|
Body-specific: Fits all species differently
|
||||||
|
|
||||||
.actions
|
= f.actions do
|
||||||
= f.submit "Save changes"
|
= f.submit "Save changes"
|
||||||
|
|
||||||
- content_for :stylesheets do
|
- content_for :stylesheets do
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,22 @@
|
||||||
= f.radio_field do
|
= f.radio_field do
|
||||||
= f.radio_button :pose, pose
|
= f.radio_button :pose, pose
|
||||||
= pose_name(pose)
|
= pose_name(pose)
|
||||||
|
- if @reference_pet_type
|
||||||
|
= link_to @reference_pet_type, target: "_blank", class: "reference-link" do
|
||||||
|
= pet_type_image @reference_pet_type, :happy, :face
|
||||||
|
%span Reference: #{@reference_pet_type.human_name}
|
||||||
|
= external_link_icon
|
||||||
|
|
||||||
= f.field do
|
= f.field do
|
||||||
= f.label :glitched, "Gliched?"
|
= f.label :glitched, "Gliched?"
|
||||||
= f.select :glitched, [["✅ Not marked as Glitched", false],
|
= f.select :glitched, [["✅ Not marked as Glitched", false],
|
||||||
["👾 Yes, it's bad news bonko'd", true]]
|
["👾 Yes, it's bad news bonko'd", true]]
|
||||||
|
|
||||||
.actions
|
= f.actions do
|
||||||
= f.submit "Save changes"
|
= f.submit "Save changes"
|
||||||
|
= f.go_to_next_field title: "If checked, takes you to the first unlabeled appearance in the database, if any. Useful for labeling in bulk!" do
|
||||||
|
= f.go_to_next_check_box "unlabeled-appearance"
|
||||||
|
Then: Go to unlabeled appearance
|
||||||
|
|
||||||
- content_for :stylesheets do
|
- content_for :stylesheets do
|
||||||
= stylesheet_link_tag "application/breadcrumbs"
|
= stylesheet_link_tag "application/breadcrumbs"
|
||||||
|
|
|
||||||
BIN
vendor/cache/debug-1.9.2.gem
vendored
Normal file
BIN
vendor/cache/debug-1.9.2.gem
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue