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
|
||||
|
||||
# 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
|
||||
gem 'bootsnap', '~> 1.16', require: false
|
||||
|
|
|
|||
|
|
@ -134,6 +134,9 @@ GEM
|
|||
crass (1.0.6)
|
||||
csv (3.3.0)
|
||||
date (3.3.4)
|
||||
debug (1.9.2)
|
||||
irb (~> 1.10)
|
||||
reline (>= 0.3.8)
|
||||
devise (4.9.4)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
|
|
@ -521,6 +524,7 @@ DEPENDENCIES
|
|||
async (~> 2.17)
|
||||
async-http (~> 0.75.0)
|
||||
bootsnap (~> 1.16)
|
||||
debug (~> 1.9.2)
|
||||
devise (~> 4.9, >= 4.9.2)
|
||||
devise-encryptable (~> 0.2.0)
|
||||
dotenv-rails (~> 2.8, >= 2.8.1)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@
|
|||
grid-template-columns: repeat(var(--num-columns, 1), 1fr)
|
||||
gap: .25em
|
||||
|
||||
li
|
||||
display: flex
|
||||
align-items: stretch // Give the bubbles equal heights!
|
||||
|
||||
label
|
||||
display: flex
|
||||
align-items: center
|
||||
|
|
@ -51,6 +55,7 @@
|
|||
padding: .5em 1em
|
||||
border: 1px solid $soft-border-color
|
||||
border-radius: 1em
|
||||
flex: 1 1 auto
|
||||
|
||||
input
|
||||
margin: 0
|
||||
|
|
@ -89,9 +94,9 @@
|
|||
align-items: center
|
||||
gap: 1em
|
||||
|
||||
label
|
||||
display: flex
|
||||
align-items: center
|
||||
gap: .25em
|
||||
font-size: .85em
|
||||
font-style: italic
|
||||
.go-to-next
|
||||
display: flex
|
||||
align-items: center
|
||||
gap: .25em
|
||||
font-size: .85em
|
||||
font-style: italic
|
||||
|
|
|
|||
|
|
@ -3,3 +3,13 @@ outfit-viewer
|
|||
|
||||
.fields li[data-type=radio-grid]
|
||||
--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
|
||||
if @pet_state.update(pet_state_params)
|
||||
flash[:notice] = "Pet appearance \##{@pet_state.id} successfully saved!"
|
||||
redirect_to @pet_type
|
||||
redirect_to destination_after_save
|
||||
else
|
||||
render action: :edit, status: :bad_request
|
||||
end
|
||||
|
|
@ -19,9 +19,35 @@ class PetStatesController < ApplicationController
|
|||
def find_pet_state
|
||||
@pet_type = PetType.find_by_param!(params[:pet_type_name])
|
||||
@pet_state = @pet_type.pet_states.find(params[:id])
|
||||
@reference_pet_type = @pet_type.reference
|
||||
end
|
||||
|
||||
def pet_state_params
|
||||
params.require(:pet_state).permit(:pose, :glitched)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,44 +1,29 @@
|
|||
module SupportFormHelper
|
||||
class SupportFormBuilder < ActionView::Helpers::FormBuilder
|
||||
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
|
||||
return nil if object.errors.empty?
|
||||
|
||||
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
|
||||
render partial: "application/support_form/errors", locals: {form: self}
|
||||
end
|
||||
|
||||
def fields(&block)
|
||||
content_tag(:ul, class: "fields", &block)
|
||||
end
|
||||
|
||||
def field(**kwargs, &block)
|
||||
content_tag(:li, **kwargs, &block)
|
||||
def field(**options, &block)
|
||||
content_tag(:li, **options, &block)
|
||||
end
|
||||
|
||||
def radio_fieldset(legend, **kwargs, &block)
|
||||
kwargs.reverse_merge!("data-type": "radio")
|
||||
field(**kwargs) do
|
||||
content_tag(:fieldset) do
|
||||
concat content_tag(:legend, legend)
|
||||
concat content_tag(:ul, &block)
|
||||
end
|
||||
end
|
||||
def radio_fieldset(legend, **options, &block)
|
||||
render partial: "application/support_form/radio_fieldset",
|
||||
locals: {form: self, legend:, options:, content: capture(&block)}
|
||||
end
|
||||
|
||||
def radio_field(**kwargs, &block)
|
||||
def radio_field(**options, &block)
|
||||
content_tag(:li) do
|
||||
content_tag(:label, **kwargs, &block)
|
||||
content_tag(:label, **options, &block)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -47,19 +32,29 @@ module SupportFormHelper
|
|||
end
|
||||
|
||||
def thumbnail_input(method)
|
||||
url = object.send(method)
|
||||
content_tag(:div, class: "thumbnail-input") do
|
||||
concat image_tag(url, alt: "Thumbnail") if url.present?
|
||||
concat url_field(method)
|
||||
end
|
||||
render partial: "application/support_form/thumbnail_input",
|
||||
locals: {form: self, method:}
|
||||
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
|
||||
|
||||
def support_form_with(**kwargs, &block)
|
||||
kwargs.merge!(
|
||||
def support_form_with(**options, &block)
|
||||
form_with(
|
||||
builder: SupportFormBuilder,
|
||||
class: ["support-form", kwargs[:class]],
|
||||
**options,
|
||||
class: ["support-form", options[:class]],
|
||||
&block
|
||||
)
|
||||
form_with(**kwargs, &block)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ class PetState < ApplicationRecord
|
|||
|
||||
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.
|
||||
scope :emotion_order, -> {
|
||||
order(Arel.sql(
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class PetType < ApplicationRecord
|
|||
species = Species.find_by_name!(species_name)
|
||||
where(color_id: color.id, species_id: species.id)
|
||||
}
|
||||
scope :newest, -> { order(created_at: :desc) }
|
||||
scope :preferring_species, ->(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" }
|
||||
end
|
||||
|
||||
def reference
|
||||
PetType.where(species_id: species).basic.merge(Color.alphabetical).first
|
||||
end
|
||||
|
||||
def self.find_by_param!(param)
|
||||
raise ActiveRecord::RecordNotFound unless param.include?("-")
|
||||
color_param, _, species_param = param.rpartition("-")
|
||||
|
|
|
|||
|
|
@ -26,11 +26,10 @@
|
|||
= f.label :thumbnail_url, "Thumbnail"
|
||||
= f.thumbnail_input :thumbnail_url
|
||||
|
||||
.actions
|
||||
= f.actions do
|
||||
= f.submit "Save changes"
|
||||
%label{title: "If checked, takes you to the next unlabeled pet style, if any. Useful for labeling in bulk!"}
|
||||
= check_box_tag "next", "unlabeled-style",
|
||||
checked: params[:next] == "unlabeled-style"
|
||||
= f.go_to_next_field title: "If checked, takes you to the next unlabeled pet style, if any. Useful for labeling in bulk!" do
|
||||
= f.go_to_next_check_box "unlabeled-style"
|
||||
Then: Go to unlabeled style
|
||||
|
||||
- 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
|
||||
Body-specific: Fits all species differently
|
||||
|
||||
.actions
|
||||
= f.actions do
|
||||
= f.submit "Save changes"
|
||||
|
||||
- content_for :stylesheets do
|
||||
|
|
|
|||
|
|
@ -26,14 +26,22 @@
|
|||
= f.radio_field do
|
||||
= f.radio_button :pose, 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.label :glitched, "Gliched?"
|
||||
= f.select :glitched, [["✅ Not marked as Glitched", false],
|
||||
["👾 Yes, it's bad news bonko'd", true]]
|
||||
|
||||
.actions
|
||||
= f.actions do
|
||||
= 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
|
||||
= 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