Merge pull request #6275 from chaimann/admin-ui-checkbox-refactor
[Admin][UI] checkbox refactor
This commit is contained in:
commit
ffa13fcbaa
@ -4,16 +4,10 @@
|
||||
<div class="flex flex-col gap-6 pb-4">
|
||||
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
|
||||
<%= render component("ui/forms/field").text_field(f, :code, class: "required") %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= hidden_field_tag "#{f.object_name}[active]", "0" %>
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[active]",
|
||||
value: "1",
|
||||
checked: f.object.active
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::AdjustmentReason.human_attribute_name :active %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :active, checked: f.object.active) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::AdjustmentReason.human_attribute_name(:active), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.active")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -4,16 +4,10 @@
|
||||
<div class="flex flex-col gap-6 pb-4">
|
||||
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
|
||||
<%= render component("ui/forms/field").text_field(f, :code, class: "required") %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= hidden_field_tag "#{f.object_name}[active]", "0" %>
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[active]",
|
||||
value: "1",
|
||||
checked: f.object.active
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::AdjustmentReason.human_attribute_name :active %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :active, checked: f.object.active) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::AdjustmentReason.human_attribute_name(:active), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.active")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -32,19 +32,13 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= form.hidden_field use_attribute, value: '0', id: false %>
|
||||
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{form.object_name}[#{use_attribute}]",
|
||||
checked: @address == (@type == 'ship' ? @order.bill_address : @order.ship_address),
|
||||
value: '1'
|
||||
) %>
|
||||
|
||||
<span class="font-normal text-xs">
|
||||
<%= t(".use_this_address.#{@type}") %>
|
||||
</span>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
object_name: form.object_name,
|
||||
method: use_attribute,
|
||||
checked: @address == (@type == 'ship' ? @order.bill_address : @order.ship_address)
|
||||
) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: t(".use_this_address.#{@type}"), size: :xs) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
|
@ -117,14 +117,10 @@
|
||||
type: :date,
|
||||
value: f.object.discontinue_on&.to_date
|
||||
) %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[promotionable]",
|
||||
checked: f.object.promotionable
|
||||
) %>
|
||||
<span class="font-normal text-xs"><%= Spree::Product.human_attribute_name :promotionable %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.promotionable_html")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :promotionable, checked: f.object.promotionable) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::Product.human_attribute_name(:promotionable), size: :xs) %>
|
||||
<%= checkbox.with_hint(text: t(".hints.promotionable_html")) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= render component("ui/panel").new(title: t(".product_organization")) do %>
|
||||
|
@ -4,16 +4,10 @@
|
||||
<div class="flex flex-col gap-6 pb-4">
|
||||
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
|
||||
<%= render component("ui/forms/field").text_field(f, :code, class: "required") %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= hidden_field_tag "#{f.object_name}[active]", "0" %>
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[active]",
|
||||
value: "1",
|
||||
checked: f.object.active
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::RefundReason.human_attribute_name :active %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :active, checked: f.object.active) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::RefundReason.human_attribute_name(:active), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.active")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -4,15 +4,10 @@
|
||||
<div class="flex flex-col gap-6 pb-4">
|
||||
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
|
||||
<%= render component("ui/forms/field").text_field(f, :code, class: "required") %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[active]",
|
||||
value: "1",
|
||||
checked: f.object.active
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::RefundReason.human_attribute_name :active %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :active, checked: f.object.active) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::RefundReason.human_attribute_name(:active), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.active")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -3,16 +3,10 @@
|
||||
<%= form_for @return_reason, url: form_url, html: { id: form_id } do |f| %>
|
||||
<div class="flex flex-col gap-6 pb-4">
|
||||
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= hidden_field_tag "#{f.object_name}[active]", "0" %>
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[active]",
|
||||
value: "1",
|
||||
checked: f.object.active
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::ReturnReason.human_attribute_name :active %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :active, checked: f.object.active) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::ReturnReason.human_attribute_name(:active), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.active")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -3,16 +3,10 @@
|
||||
<%= form_for @return_reason, url: form_url, html: { id: form_id } do |f| %>
|
||||
<div class="flex flex-col gap-6 pb-4">
|
||||
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= hidden_field_tag "#{f.object_name}[active]", "0" %>
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[active]",
|
||||
value: "1",
|
||||
checked: f.object.active
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::ReturnReason.human_attribute_name :active %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :active, checked: f.object.active) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::ReturnReason.human_attribute_name(:active), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.active")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -3,16 +3,10 @@
|
||||
<%= form_for @store_credit_reason, url: form_url, html: { id: form_id } do |f| %>
|
||||
<div class="flex flex-col gap-6 pb-4">
|
||||
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= hidden_field_tag "#{f.object_name}[active]", "0" %>
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[active]",
|
||||
value: "1",
|
||||
checked: f.object.active
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::StoreCreditReason.human_attribute_name :active %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :active, checked: f.object.active) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::StoreCreditReason.human_attribute_name(:active), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.active")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -3,16 +3,10 @@
|
||||
<%= form_for @store_credit_reason, url: form_url, html: { id: form_id } do |f| %>
|
||||
<div class="flex flex-col gap-6 pb-4">
|
||||
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= hidden_field_tag "#{f.object_name}[active]", "0" %>
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[active]",
|
||||
value: "1",
|
||||
checked: f.object.active
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::StoreCreditReason.human_attribute_name :active %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :active, checked: f.object.active) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::StoreCreditReason.human_attribute_name(:active), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.active")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -5,15 +5,10 @@
|
||||
<%= render component("ui/forms/field").text_field(f, :name) %>
|
||||
<%= render component("ui/forms/field").text_field(f, :tax_code) %>
|
||||
<%= render component("ui/forms/field").text_field(f, :description) %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[is_default]",
|
||||
value: "1",
|
||||
checked: f.object.is_default
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::TaxCategory.human_attribute_name :is_default %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.is_default")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :is_default, checked: f.object.is_default) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::TaxCategory.human_attribute_name(:is_default), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.is_default")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
@ -5,15 +5,10 @@
|
||||
<%= render component("ui/forms/field").text_field(f, :name) %>
|
||||
<%= render component("ui/forms/field").text_field(f, :tax_code) %>
|
||||
<%= render component("ui/forms/field").text_field(f, :description) %>
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= render component("ui/forms/checkbox").new(
|
||||
name: "#{f.object_name}[is_default]",
|
||||
value: "1",
|
||||
checked: f.object.is_default
|
||||
) %>
|
||||
<span class="font-semibold text-xs ml-2"><%= Spree::TaxCategory.human_attribute_name :is_default %></span>
|
||||
<%= render component("ui/toggletip").new(text: t(".hints.is_default")) %>
|
||||
</label>
|
||||
<%= render component("ui/forms/checkbox").new(object_name: f.object_name, method: :is_default, checked: f.object.is_default) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: Spree::TaxCategory.human_attribute_name(:is_default), weight: :semibold, size: :xs, classes: 'ml-2') %>
|
||||
<%= checkbox.with_hint(text: t(".hints.is_default")) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% modal.with_actions do %>
|
||||
<form method="dialog">
|
||||
|
42
admin/app/components/solidus_admin/ui/checkbox/component.rb
Normal file
42
admin/app/components/solidus_admin/ui/checkbox/component.rb
Normal file
@ -0,0 +1,42 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SolidusAdmin::UI::Checkbox::Component < SolidusAdmin::BaseComponent
|
||||
SIZES = {
|
||||
s: 'w-4 h-4',
|
||||
m: 'w-5 h-5',
|
||||
}.freeze
|
||||
|
||||
def initialize(size: :m, **attributes)
|
||||
@size = size
|
||||
@attributes = attributes
|
||||
end
|
||||
|
||||
def call
|
||||
tag.input(
|
||||
type: 'checkbox',
|
||||
class: "
|
||||
#{SIZES.fetch(@size)}
|
||||
form-checkbox
|
||||
cursor-pointer
|
||||
disabled:cursor-not-allowed
|
||||
|
||||
bg-white rounded border border-2 border-gray-300
|
||||
hover:border-gray-700
|
||||
focus:ring focus:ring-gray-300 focus:ring-0.5 focus:bg-white focus:ring-offset-0
|
||||
active:ring active:ring-gray-300 active:ring-0.5
|
||||
disabled:border-gray-300
|
||||
|
||||
indeterminate:border-gray-700 indeterminate:bg-gray-700 indeterminate:text-white
|
||||
indeterminate:hover:border-gray-500 indeterminate:hover:bg-gray-500
|
||||
indeterminate:focus:bg-gray-700
|
||||
indeterminate:disabled:border-gray-300 indeterminate:disabled:bg-gray-300
|
||||
|
||||
checked:border-gray-700 checked:bg-gray-700 checked:text-white
|
||||
checked:hover:border-gray-500 checked:hover:bg-gray-500
|
||||
checked:focus:bg-gray-700
|
||||
checked:disabled:border-gray-300 checked:disabled:bg-gray-300
|
||||
",
|
||||
**@attributes,
|
||||
)
|
||||
end
|
||||
end
|
@ -0,0 +1,14 @@
|
||||
<div class="flex gap-2 items-center">
|
||||
<label class="flex gap-2 items-center">
|
||||
<%= hidden_field_tag @name, "0" %>
|
||||
<%= render component("ui/checkbox").new(
|
||||
name: @name,
|
||||
value: "1",
|
||||
checked: @checked,
|
||||
**@attributes
|
||||
) %>
|
||||
<%= label %>
|
||||
</label>
|
||||
|
||||
<%= hint if hint? %>
|
||||
</div>
|
@ -1,42 +1,35 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SolidusAdmin::UI::Forms::Checkbox::Component < SolidusAdmin::BaseComponent
|
||||
SIZES = {
|
||||
s: 'w-4 h-4',
|
||||
m: 'w-5 h-5',
|
||||
FONT_WEIGHTS = {
|
||||
normal: 'font-normal',
|
||||
semibold: 'font-semibold',
|
||||
}.freeze
|
||||
|
||||
def initialize(size: :m, **attributes)
|
||||
@size = size
|
||||
@attributes = attributes
|
||||
end
|
||||
FONT_SIZES = {
|
||||
xs: 'text-xs',
|
||||
s: 'text-sm',
|
||||
}.freeze
|
||||
|
||||
def call
|
||||
tag.input(
|
||||
type: 'checkbox',
|
||||
renders_one :label, ->(text:, weight: :normal, size: :s, **options) do
|
||||
tag.span(
|
||||
text,
|
||||
class: "
|
||||
#{SIZES.fetch(@size)}
|
||||
form-checkbox
|
||||
cursor-pointer
|
||||
disabled:cursor-not-allowed
|
||||
|
||||
bg-white rounded border border-2 border-gray-300
|
||||
hover:border-gray-700
|
||||
focus:ring focus:ring-gray-300 focus:ring-0.5 focus:bg-white focus:ring-offset-0
|
||||
active:ring active:ring-gray-300 active:ring-0.5
|
||||
disabled:border-gray-300
|
||||
|
||||
indeterminate:border-gray-700 indeterminate:bg-gray-700 indeterminate:text-white
|
||||
indeterminate:hover:border-gray-500 indeterminate:hover:bg-gray-500
|
||||
indeterminate:focus:bg-gray-700
|
||||
indeterminate:disabled:border-gray-300 indeterminate:disabled:bg-gray-300
|
||||
|
||||
checked:border-gray-700 checked:bg-gray-700 checked:text-white
|
||||
checked:hover:border-gray-500 checked:hover:bg-gray-500
|
||||
checked:focus:bg-gray-700
|
||||
checked:disabled:border-gray-300 checked:disabled:bg-gray-300
|
||||
#{FONT_WEIGHTS.fetch(weight)}
|
||||
#{FONT_SIZES.fetch(size)}
|
||||
#{options.delete(:classes)}
|
||||
",
|
||||
**@attributes,
|
||||
**options
|
||||
)
|
||||
end
|
||||
|
||||
renders_one :hint, ->(text:, position: :above) do
|
||||
render component("ui/toggletip").new(text:, position:)
|
||||
end
|
||||
|
||||
def initialize(object_name:, method:, checked:, **attributes)
|
||||
@name = "#{object_name}[#{method}]"
|
||||
@checked = !!checked
|
||||
@attributes = attributes
|
||||
end
|
||||
end
|
||||
|
@ -71,7 +71,7 @@ class SolidusAdmin::UI::Table::Component < SolidusAdmin::BaseComponent
|
||||
def selectable_column
|
||||
@selectable_column ||= Column.new(
|
||||
header: -> {
|
||||
component("ui/forms/checkbox").new(
|
||||
component("ui/checkbox").new(
|
||||
form: batch_actions_form_id,
|
||||
"data-action": "#{stimulus_id}#selectAllRows",
|
||||
"data-#{stimulus_id}-target": "headerCheckbox",
|
||||
@ -79,7 +79,7 @@ class SolidusAdmin::UI::Table::Component < SolidusAdmin::BaseComponent
|
||||
)
|
||||
},
|
||||
data: ->(data) {
|
||||
component("ui/forms/checkbox").new(
|
||||
component("ui/checkbox").new(
|
||||
name: "id[]",
|
||||
form: batch_actions_form_id,
|
||||
value: data.id,
|
||||
|
@ -46,7 +46,7 @@
|
||||
name="<%= selection.predicate.name %>"
|
||||
value="<%= selection.predicate.value %>">
|
||||
|
||||
<%= render component('ui/forms/checkbox').new(
|
||||
<%= render component('ui/checkbox').new(
|
||||
id: selection.id,
|
||||
name: selection.option.name,
|
||||
value: selection.option.value,
|
||||
|
@ -51,6 +51,16 @@ module SolidusAdmin
|
||||
expect(control).to have_text(val)
|
||||
end
|
||||
end
|
||||
|
||||
def checkbox(locator)
|
||||
find(:checkbox, locator)
|
||||
end
|
||||
|
||||
def clear_search
|
||||
within('div[role="search"]') do
|
||||
find('button[aria-label="Clear"]').click
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,58 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# @component "ui/checkbox"
|
||||
class SolidusAdmin::UI::Checkbox::ComponentPreview < ViewComponent::Preview
|
||||
include SolidusAdmin::Preview
|
||||
|
||||
# **With a form builder**
|
||||
#
|
||||
# The checkbox component is used to render a checkbox input.
|
||||
# It can be used with a Rails form builder by setting the `name` attribute
|
||||
# with `forom.object_name`.
|
||||
#
|
||||
# ```erb
|
||||
# <%= form_for @product do |form| %>
|
||||
# ...
|
||||
# <%= render component('ui/checkbox').new(
|
||||
# name: "#{form.object_name}[accept_tos]",
|
||||
# checked: form.object.accept_tos,
|
||||
# ) %>
|
||||
# ...
|
||||
# <% end %>
|
||||
# ```
|
||||
#
|
||||
# **With stimulus**
|
||||
#
|
||||
# The checkbox component can be used with stimulus to toggle the `indeterminate`
|
||||
# state of the checkbox.
|
||||
#
|
||||
# ```erb
|
||||
# <%= render component('ui/checkbox').new(
|
||||
# "data-action": "click->#{stimulus_id}#toggleIndeterminate",
|
||||
# "data-#{stimulus_id}-target": "checkbox",
|
||||
# ) %>
|
||||
# ```
|
||||
#
|
||||
# ```js
|
||||
# import { Controller } from "stimulus"
|
||||
#
|
||||
# export default class extends Controller {
|
||||
# static targets = ["checkbox"]
|
||||
#
|
||||
# toggleIndeterminate() {
|
||||
# this.checkboxTarget.indeterminate = !this.checkboxTarget.indeterminate
|
||||
# }
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
def overview
|
||||
render_with_template
|
||||
end
|
||||
|
||||
# @param size select { choices: [s, m] }
|
||||
# @param checked toggle
|
||||
# @param disabled toggle
|
||||
def playground(size: :m, checked: false, disabled: false)
|
||||
render current_component.new(size: size.to_sym, checked:, disabled:)
|
||||
end
|
||||
end
|
@ -0,0 +1,32 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
<% current_component::SIZES.keys.each do |size| %>
|
||||
<td class="px-3 py-1 text-gray-500 text-center text-[16px]" colspan="2"><%= size.to_s.humanize %></td>
|
||||
<% end %>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<% current_component::SIZES.keys.each do |size| %>
|
||||
<% %i[default disabled].each do |state| %>
|
||||
<td class="px-3 py-1 text-gray-500 text-center"><%= state.to_s.humanize %></td>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% %i[off on intermediate].each do |checked| %>
|
||||
<tr>
|
||||
<td class="font-bold px-3 py-1"><%= checked.to_s.humanize %></td>
|
||||
<% current_component::SIZES.keys.each do |size| %>
|
||||
<% %i[default disabled].each do |state| %>
|
||||
<% cell_id = SecureRandom.uuid %>
|
||||
<td class="px-3 py-1 text-center" id="<%= cell_id %>">
|
||||
<%= render current_component.new(size: size, checked: checked == :on, disabled: state == :disabled) %>
|
||||
<script>
|
||||
document.getElementById("<%= cell_id %>").querySelector("input").indeterminate = <%= checked == :intermediate %>
|
||||
</script>
|
||||
</td>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
@ -4,55 +4,39 @@
|
||||
class SolidusAdmin::UI::Forms::Checkbox::ComponentPreview < ViewComponent::Preview
|
||||
include SolidusAdmin::Preview
|
||||
|
||||
# **With a form builder**
|
||||
# Forms checkbox component utilises regular checkbox component and encapsulates some functionality
|
||||
# that is shared between admin forms checkboxes:
|
||||
# - adds `hidden_field_tag` to function properly
|
||||
# - provides a way to customise label (font size/weight, custom styles)
|
||||
# - optionally include a toggletip hint
|
||||
#
|
||||
# The checkbox component is used to render a checkbox input.
|
||||
# It can be used with a Rails form builder by setting the `name` attribute
|
||||
# with `forom.object_name`.
|
||||
# Requires `object_name` and `method` parameters that will form a name of the hidden input and checkbox input fields.
|
||||
#
|
||||
# Requires `checked` boolean parameter that will be passed directly to `ui/checkbox` component.
|
||||
#
|
||||
# Accepts and passes along to `ui/checkbox` component every other attribute that is accepted by it, e.g. `size`.
|
||||
#
|
||||
# ```erb
|
||||
# <%= form_for @product do |form| %>
|
||||
# ...
|
||||
# <%= render component('ui/forms/checkbox').new(
|
||||
# name: "#{form.object_name}[accept_tos]",
|
||||
# checked: form.object.accept_tos,
|
||||
# ) %>
|
||||
# ...
|
||||
# <%= render component('ui/forms/checkbox').new(object_name: 'stock_location', method: :default, checked: true) do |checkbox| %>
|
||||
# <%= checkbox.with_label(text: "Default") %>
|
||||
# <%= checkbox.with_hint(text: "Will be used by default") %>
|
||||
# <% end %>
|
||||
# ```
|
||||
#
|
||||
# **With stimulus**
|
||||
#
|
||||
# The checkbox component can be used with stimulus to toggle the `indeterminate`
|
||||
# state of the checkbox.
|
||||
#
|
||||
# ```erb
|
||||
# <%= render component('ui/forms/checkbox').new(
|
||||
# "data-action": "click->#{stimulus_id}#toggleIndeterminate",
|
||||
# "data-#{stimulus_id}-target": "checkbox",
|
||||
# ) %>
|
||||
# ```
|
||||
#
|
||||
# ```js
|
||||
# import { Controller } from "stimulus"
|
||||
#
|
||||
# export default class extends Controller {
|
||||
# static targets = ["checkbox"]
|
||||
#
|
||||
# toggleIndeterminate() {
|
||||
# this.checkboxTarget.indeterminate = !this.checkboxTarget.indeterminate
|
||||
# }
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
|
||||
def overview
|
||||
render_with_template
|
||||
end
|
||||
|
||||
# @param size select { choices: [s, m] }
|
||||
# @param checked toggle
|
||||
# @param disabled toggle
|
||||
def playground(size: :m, checked: false, disabled: false)
|
||||
render current_component.new(size: size.to_sym, checked:, disabled:)
|
||||
# @param caption_size select { choices: [xs, s] }
|
||||
# @param caption_weight select { choices: [normal, semibold] }
|
||||
# @param caption_classes text
|
||||
# @param hint toggle
|
||||
# @param hint_text text
|
||||
# @param hint_position select { choices: [above, below] }
|
||||
def playground(caption_size: :s, caption_weight: :normal, caption_classes: '', hint: true, hint_text: "This will be helpful", hint_position: :above)
|
||||
render current_component.new(object_name: "store", method: :active, checked: true) do |component|
|
||||
component.with_label(text: "Active", size: caption_size, weight: caption_weight, classes: caption_classes)
|
||||
component.with_hint(text: hint_text, position: hint_position) if hint
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,32 +1,56 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
<% current_component::SIZES.keys.each do |size| %>
|
||||
<td class="px-3 py-1 text-gray-500 text-center text-[16px]" colspan="2"><%= size.to_s.humanize %></td>
|
||||
<% end %>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<% current_component::SIZES.keys.each do |size| %>
|
||||
<% %i[default disabled].each do |state| %>
|
||||
<td class="px-3 py-1 text-gray-500 text-center"><%= state.to_s.humanize %></td>
|
||||
<div class="flex gap-6">
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-8">
|
||||
<h6 class="text-gray-500 mb-3 mt-0">
|
||||
Regular label
|
||||
</h6>
|
||||
<%= render current_component.new(object_name: 'store', method: :active, checked: true) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: 'Active') %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% %i[off on intermediate].each do |checked| %>
|
||||
<tr>
|
||||
<td class="font-bold px-3 py-1"><%= checked.to_s.humanize %></td>
|
||||
<% current_component::SIZES.keys.each do |size| %>
|
||||
<% %i[default disabled].each do |state| %>
|
||||
<% cell_id = SecureRandom.uuid %>
|
||||
<td class="px-3 py-1 text-center" id="<%= cell_id %>">
|
||||
<%= render current_component.new(size: size, checked: checked == :on, disabled: state == :disabled) %>
|
||||
<script>
|
||||
document.getElementById("<%= cell_id %>").querySelector("input").indeterminate = <%= checked == :intermediate %>
|
||||
</script>
|
||||
</td>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<h6 class="text-gray-500 mb-3 mt-0">
|
||||
Smaller label
|
||||
</h6>
|
||||
<%= render current_component.new(object_name: 'store', method: :active, checked: true) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: 'Active', size: :xs) %>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<h6 class="text-gray-500 mb-3 mt-0">
|
||||
Semibold label
|
||||
</h6>
|
||||
<%= render current_component.new(object_name: 'store', method: :active, checked: true) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: 'Active', weight: :semibold) %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-8">
|
||||
<h6 class="text-gray-500 mb-3 mt-0">
|
||||
Label with custom styles applied
|
||||
</h6>
|
||||
<%= render current_component.new(object_name: 'store', method: :active, checked: true) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: 'Active', classes: 'text-gray-500') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<h6 class="text-gray-500 mb-3 mt-0">
|
||||
With label and hint above
|
||||
</h6>
|
||||
<%= render current_component.new(object_name: 'store', method: :active, checked: true) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: 'Active') %>
|
||||
<%= checkbox.with_hint(text: 'This means something') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<h6 class="text-gray-500 mb-3 mt-0">
|
||||
With label and hint below
|
||||
</h6>
|
||||
<%= render current_component.new(object_name: 'store', method: :active, checked: true) do |checkbox| %>
|
||||
<%= checkbox.with_label(text: 'Active') %>
|
||||
<%= checkbox.with_hint(text: 'This means something', position: :below) %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe SolidusAdmin::UI::Checkbox::Component, type: :component do
|
||||
it "renders the overview preview" do
|
||||
render_preview(:overview)
|
||||
end
|
||||
end
|
@ -40,9 +40,12 @@ describe "Product", type: :feature do
|
||||
visit "/admin/products/just-a-prod"
|
||||
|
||||
fill_in "Name", with: "Just a product (updated)"
|
||||
uncheck 'Promotable'
|
||||
within('header') { click_button "Save" }
|
||||
|
||||
expect(page).to have_content("Just a product (updated)")
|
||||
expect(checkbox("Promotable")).not_to be_checked
|
||||
|
||||
fill_in "Name", with: ""
|
||||
within('header') { click_button "Save" }
|
||||
|
||||
|
@ -22,7 +22,7 @@ describe "Refund Reasons", type: :feature do
|
||||
end
|
||||
|
||||
context "when creating a new refund reason" do
|
||||
let(:query) { "?page=1&q%5Bname_or_description_cont%5D=Ret" }
|
||||
let(:query) { "?page=1&q%5Bname_or_code_cont%5D=Ret" }
|
||||
|
||||
before do
|
||||
visit "/admin/refund_reasons/#{query}"
|
||||
@ -44,10 +44,13 @@ describe "Refund Reasons", type: :feature do
|
||||
context "with valid data" do
|
||||
it "successfully creates a new refund reason, keeping page and q params" do
|
||||
fill_in "Name", with: "Return process"
|
||||
uncheck "Active"
|
||||
|
||||
click_on "Add Refund Reason"
|
||||
|
||||
expect(page).to have_content("Refund reason was successfully created.")
|
||||
click_on "Return process"
|
||||
expect(checkbox("Active")).not_to be_checked
|
||||
expect(Spree::RefundReason.find_by(name: "Return process")).to be_present
|
||||
expect(page.current_url).to include(query)
|
||||
end
|
||||
@ -64,10 +67,10 @@ describe "Refund Reasons", type: :feature do
|
||||
end
|
||||
|
||||
context "when editing an existing refund reason" do
|
||||
let(:query) { "?page=1&q%5Bname_or_description_cont%5D=Ret" }
|
||||
let(:query) { "?page=1&q%5Bname_or_code_cont%5D=Ret" }
|
||||
|
||||
before do
|
||||
Spree::RefundReason.create(name: "Return process")
|
||||
Spree::RefundReason.create(name: "Return process", active: false)
|
||||
visit "/admin/refund_reasons#{query}"
|
||||
click_on "Return process"
|
||||
expect(page).to have_css("dialog")
|
||||
@ -84,15 +87,22 @@ describe "Refund Reasons", type: :feature do
|
||||
expect(page.current_url).to include(query)
|
||||
end
|
||||
|
||||
it "successfully updates the existing refund reason" do
|
||||
it "successfully updates the existing refund reason", :js do
|
||||
fill_in "Name", with: "Customer complaint"
|
||||
|
||||
check "Active"
|
||||
click_on "Update Refund Reason"
|
||||
|
||||
expect(page.current_url).to include(query)
|
||||
expect(page).to have_content("Refund reason was successfully updated.")
|
||||
expect(page).to have_content("No Refund Reasons found") # search query still applied, filters out updated name
|
||||
clear_search
|
||||
|
||||
expect(page).to have_content("Customer complaint")
|
||||
expect(page).not_to have_content("Return process")
|
||||
|
||||
click_on "Customer complaint"
|
||||
expect(checkbox("Active")).to be_checked
|
||||
expect(Spree::RefundReason.find_by(name: "Customer complaint")).to be_present
|
||||
expect(page.current_url).to include(query)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -46,10 +46,13 @@ describe "Tax categories", type: :feature do
|
||||
context "with valid data" do
|
||||
it "successfully creates a new tax category, keeping page and q params" do
|
||||
fill_in "Name", with: "Clothing"
|
||||
check "Default"
|
||||
|
||||
click_on "Add Tax Category"
|
||||
|
||||
expect(page).to have_content("Tax category was successfully created.")
|
||||
click_on "Clothing"
|
||||
expect(checkbox("Default")).to be_checked
|
||||
expect(Spree::TaxCategory.find_by(name: "Clothing")).to be_present
|
||||
expect(page.current_url).to include(query)
|
||||
end
|
||||
@ -64,4 +67,39 @@ describe "Tax categories", type: :feature do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when editing an existing tax category" do
|
||||
let(:query) { "?page=1&q%5Bname_or_description_cont%5D=Cloth" }
|
||||
|
||||
before do
|
||||
Spree::TaxCategory.create(name: "Clothing", is_default: true)
|
||||
visit "/admin/tax_categories#{query}"
|
||||
click_on "Clothing"
|
||||
expect(page).to have_css("dialog")
|
||||
expect(page).to have_content("Edit Tax Category")
|
||||
expect(page).to be_axe_clean
|
||||
end
|
||||
|
||||
it "closing the modal keeps query params", :js do
|
||||
within("dialog") { click_on "Cancel" }
|
||||
expect(page).not_to have_selector("dialog")
|
||||
expect(page.current_url).to include(query)
|
||||
end
|
||||
|
||||
it "successfully updates the existing tax category", :js do
|
||||
fill_in "Name", with: "Other"
|
||||
uncheck "Default"
|
||||
click_on "Update Tax Category"
|
||||
|
||||
expect(page.current_url).to include(query)
|
||||
expect(page).to have_content("Tax category was successfully updated.")
|
||||
expect(page).to have_content("No Tax Categories found") # search query still applied, filters out updated name
|
||||
clear_search
|
||||
|
||||
expect(page).to have_content("Other")
|
||||
expect(page).not_to have_content("Clothing")
|
||||
click_on "Other"
|
||||
expect(checkbox("Default")).not_to be_checked
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user