diff --git a/admin/app/components/solidus_admin/tax_categories/index/component.rb b/admin/app/components/solidus_admin/tax_categories/index/component.rb
index 47ff3fb60bf..c435fb1da7c 100644
--- a/admin/app/components/solidus_admin/tax_categories/index/component.rb
+++ b/admin/app/components/solidus_admin/tax_categories/index/component.rb
@@ -13,16 +13,20 @@ def search_url
solidus_admin.tax_categories_path
end
- def actions
+ def page_actions
render component("ui/button").new(
tag: :a,
text: t('.add'),
- href: spree.new_admin_tax_category_path,
+ href: solidus_admin.new_tax_category_path, data: { turbo_frame: :new_tax_category_modal },
icon: "add-line",
class: "align-self-end w-full",
)
end
+ def turbo_frames
+ %w[new_tax_category_modal]
+ end
+
def search_key
:name_or_description_cont
end
diff --git a/admin/app/components/solidus_admin/tax_categories/new/component.html.erb b/admin/app/components/solidus_admin/tax_categories/new/component.html.erb
new file mode 100644
index 00000000000..b1a97dcc9be
--- /dev/null
+++ b/admin/app/components/solidus_admin/tax_categories/new/component.html.erb
@@ -0,0 +1,28 @@
+<%= turbo_frame_tag :new_tax_category_modal do %>
+ <%= render component("ui/modal").new(title: t(".title")) do |modal| %>
+ <%= form_for @tax_category, url: solidus_admin.tax_categories_path(page: params[:page], q: params[:q]), html: { id: form_id } do |f| %>
+
+ <%= 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) %>
+
+
+ <% modal.with_actions do %>
+
+ <%= render component("ui/button").new(form: form_id, type: :submit, text: t('.submit')) %>
+ <% end %>
+ <% end %>
+ <% end %>
+<% end %>
+
+<%= render component("tax_categories/index").new(page: @page) %>
diff --git a/admin/app/components/solidus_admin/tax_categories/new/component.rb b/admin/app/components/solidus_admin/tax_categories/new/component.rb
new file mode 100644
index 00000000000..d61ef1e3dd5
--- /dev/null
+++ b/admin/app/components/solidus_admin/tax_categories/new/component.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class SolidusAdmin::TaxCategories::New::Component < SolidusAdmin::TaxCategories::Index::Component
+ def initialize(page:, tax_category:)
+ @page = page
+ @tax_category = tax_category
+ end
+
+ def form_id
+ dom_id(@tax_category, "#{stimulus_id}_new_tax_category_form")
+ end
+end
diff --git a/admin/app/components/solidus_admin/tax_categories/new/component.yml b/admin/app/components/solidus_admin/tax_categories/new/component.yml
new file mode 100644
index 00000000000..24706db9edf
--- /dev/null
+++ b/admin/app/components/solidus_admin/tax_categories/new/component.yml
@@ -0,0 +1,8 @@
+# Add your component translations here.
+# Use the translation in the example in your template with `t(".hello")`.
+en:
+ title: "New Tax Category"
+ cancel: "Cancel"
+ submit: "Add Tax Category"
+ hints:
+ is_default: "When checked, this tax category will be selected by default when creating new products or variants."
diff --git a/admin/app/components/solidus_admin/ui/modal/component.html.erb b/admin/app/components/solidus_admin/ui/modal/component.html.erb
index c9ce14bbf80..8b408161258 100644
--- a/admin/app/components/solidus_admin/ui/modal/component.html.erb
+++ b/admin/app/components/solidus_admin/ui/modal/component.html.erb
@@ -14,13 +14,13 @@
<%= @title %>
- <%= render component('ui/button').new(
- tag: :a,
- href: @close_path,
- icon: 'close-line',
- scheme: :ghost,
- title: t('.close'),
- ) %>
+
diff --git a/admin/app/components/solidus_admin/ui/modal/component.js b/admin/app/components/solidus_admin/ui/modal/component.js
new file mode 100644
index 00000000000..3d9ec5c408e
--- /dev/null
+++ b/admin/app/components/solidus_admin/ui/modal/component.js
@@ -0,0 +1,7 @@
+import { Controller } from "@hotwired/stimulus";
+
+export default class extends Controller {
+ connect() {
+ this.element.showModal();
+ }
+}
diff --git a/admin/app/components/solidus_admin/ui/modal/component.rb b/admin/app/components/solidus_admin/ui/modal/component.rb
index 86f2401c04c..7dae58a192d 100644
--- a/admin/app/components/solidus_admin/ui/modal/component.rb
+++ b/admin/app/components/solidus_admin/ui/modal/component.rb
@@ -3,7 +3,7 @@
class SolidusAdmin::UI::Modal::Component < SolidusAdmin::BaseComponent
renders_one :actions
- def initialize(title:, close_path: nil, open: true, **attributes)
+ def initialize(title:, close_path: nil, open: false, **attributes)
@title = title
@close_path = close_path
@attributes = attributes
diff --git a/admin/app/components/solidus_admin/ui/pages/index/component.html.erb b/admin/app/components/solidus_admin/ui/pages/index/component.html.erb
index e9774650a8c..69916f08dd4 100644
--- a/admin/app/components/solidus_admin/ui/pages/index/component.html.erb
+++ b/admin/app/components/solidus_admin/ui/pages/index/component.html.erb
@@ -37,4 +37,8 @@
<% end %>
<% end %>
<% end %>
+
+ <% turbo_frames.each do |frame| %>
+ <%= turbo_frame_tag frame %>
+ <% end %>
<% end %>
diff --git a/admin/app/components/solidus_admin/ui/pages/index/component.rb b/admin/app/components/solidus_admin/ui/pages/index/component.rb
index 15d31a4089e..6ee519537bb 100644
--- a/admin/app/components/solidus_admin/ui/pages/index/component.rb
+++ b/admin/app/components/solidus_admin/ui/pages/index/component.rb
@@ -98,4 +98,8 @@ def render_sidebar
page_with_sidebar_aside { sidebar } if sidebar
end
+
+ def turbo_frames
+ []
+ end
end
diff --git a/admin/app/controllers/solidus_admin/tax_categories_controller.rb b/admin/app/controllers/solidus_admin/tax_categories_controller.rb
index f5f0bc1378e..cc9e833a2ba 100644
--- a/admin/app/controllers/solidus_admin/tax_categories_controller.rb
+++ b/admin/app/controllers/solidus_admin/tax_categories_controller.rb
@@ -4,13 +4,47 @@ module SolidusAdmin
class TaxCategoriesController < SolidusAdmin::BaseController
include SolidusAdmin::ControllerHelpers::Search
- def index
- tax_categories = apply_search_to(
- Spree::TaxCategory.order(created_at: :desc, id: :desc),
- param: :q,
- )
+ def new
+ @tax_category = Spree::TaxCategory.new
- set_page_and_extract_portion_from(tax_categories)
+ set_index_page
+
+ respond_to do |format|
+ format.html { render component('tax_categories/new').new(page: @page, tax_category: @tax_category) }
+ end
+ end
+
+ def create
+ @tax_category = Spree::TaxCategory.new(tax_category_params)
+
+ if @tax_category.save
+ respond_to do |format|
+ flash[:notice] = t('.success')
+
+ format.html do
+ redirect_to solidus_admin.tax_categories_path, status: :see_other
+ end
+
+ format.turbo_stream do
+ # we need to explicitly write the refresh tag for now.
+ # See https://github.com/hotwired/turbo-rails/issues/579
+ render turbo_stream: ''
+ end
+ end
+ else
+ set_index_page
+
+ respond_to do |format|
+ format.html do
+ page_component = component('tax_categories/new').new(page: @page, tax_category: @tax_category)
+ render page_component, status: :unprocessable_entity
+ end
+ end
+ end
+ end
+
+ def index
+ set_index_page
respond_to do |format|
format.html { render component('tax_categories/index').new(page: @page) }
@@ -34,7 +68,16 @@ def load_tax_category
end
def tax_category_params
- params.require(:tax_category).permit(:tax_category_id, permitted_tax_category_attributes)
+ params.require(:tax_category).permit(:name, :description, :is_default, :tax_code)
+ end
+
+ def set_index_page
+ tax_categories = apply_search_to(
+ Spree::TaxCategory.order(created_at: :desc, id: :desc),
+ param: :q,
+ )
+
+ set_page_and_extract_portion_from(tax_categories)
end
end
end
diff --git a/admin/app/views/layouts/solidus_admin/application.html.erb b/admin/app/views/layouts/solidus_admin/application.html.erb
index 4fa30ebdfd8..246051776a2 100644
--- a/admin/app/views/layouts/solidus_admin/application.html.erb
+++ b/admin/app/views/layouts/solidus_admin/application.html.erb
@@ -11,6 +11,7 @@
<%= stylesheet_link_tag SolidusAdmin::Config.theme_path(session[:admin_light_theme]), media: '(prefers-color-scheme: light)', "data-turbo-track": "reload" %>
<%= stylesheet_link_tag SolidusAdmin::Config.theme_path(session[:admin_dark_theme]), media: '(prefers-color-scheme: dark)', "data-turbo-track": "reload" %>
<%= javascript_importmap_tags "solidus_admin/application", shim: false, importmap: SolidusAdmin.importmap %>
+
diff --git a/admin/config/locales/tax_categories.en.yml b/admin/config/locales/tax_categories.en.yml
index 9162bb44069..c86f9400f42 100644
--- a/admin/config/locales/tax_categories.en.yml
+++ b/admin/config/locales/tax_categories.en.yml
@@ -4,3 +4,5 @@ en:
title: "Tax Categories"
destroy:
success: "Tax categories were successfully removed."
+ create:
+ success: "Tax category was successfully created."
diff --git a/admin/config/routes.rb b/admin/config/routes.rb
index c938ea27de6..37003949356 100644
--- a/admin/config/routes.rb
+++ b/admin/config/routes.rb
@@ -51,7 +51,7 @@
admin_resources :option_types, only: [:index, :destroy], sortable: true
admin_resources :taxonomies, only: [:index, :destroy], sortable: true
admin_resources :promotion_categories, only: [:index, :destroy]
- admin_resources :tax_categories, only: [:index, :destroy]
+ admin_resources :tax_categories, only: [:new, :index, :create, :destroy]
admin_resources :tax_rates, only: [:index, :destroy]
admin_resources :payment_methods, only: [:index, :destroy], sortable: true
admin_resources :stock_items, only: [:index, :edit, :update]
diff --git a/admin/solidus_admin.gemspec b/admin/solidus_admin.gemspec
index 5878002997a..41867f53963 100644
--- a/admin/solidus_admin.gemspec
+++ b/admin/solidus_admin.gemspec
@@ -33,6 +33,6 @@ Gem::Specification.new do |s|
s.add_dependency 'solidus_backend'
s.add_dependency 'solidus_core', '> 4.2'
s.add_dependency 'stimulus-rails', '~> 1.2'
- s.add_dependency 'turbo-rails', '~> 1.4'
+ s.add_dependency 'turbo-rails', '~> 2.0'
s.add_dependency 'view_component', '~> 3.9'
end
diff --git a/admin/spec/features/tax_categories_spec.rb b/admin/spec/features/tax_categories_spec.rb
index cbc15b436c9..b91a24256dc 100644
--- a/admin/spec/features/tax_categories_spec.rb
+++ b/admin/spec/features/tax_categories_spec.rb
@@ -21,4 +21,43 @@
expect(Spree::TaxCategory.count).to eq(1)
expect(page).to be_axe_clean
end
+
+ context "when creating a new tax category" do
+ let(:query) { "?page=1&q%5Bname_or_description_cont%5D=Cloth" }
+
+ before do
+ visit "/admin/tax_categories#{query}"
+ click_on "Add new"
+ expect(page).to have_content("New Tax Category")
+ expect(page).to be_axe_clean
+ end
+
+ it "opens a modal" do
+ expect(page).to have_selector("dialog")
+ within("dialog") { click_on "Cancel" }
+ expect(page).not_to have_selector("dialog")
+ expect(page.current_url).to include(query)
+ end
+
+ context "with valid data" do
+ it "successfully creates a new tax category, keeping page and q params" do
+ fill_in "Name", with: "Clothing"
+
+ click_on "Add Tax Category"
+
+ expect(page).to have_content("Tax category was successfully created.")
+ expect(Spree::TaxCategory.find_by(name: "Clothing")).to be_present
+ expect(page.current_url).to include(query)
+ end
+ end
+
+ context "with invalid data" do
+ it "fails to create a new tax category, keeping page and q params" do
+ click_on "Add Tax Category"
+
+ expect(page).to have_content "can't be blank"
+ expect(page.current_url).to include(query)
+ end
+ end
+ end
end
diff --git a/core/app/models/spree/tax_category.rb b/core/app/models/spree/tax_category.rb
index f1d75da1910..d4dc8f857ff 100644
--- a/core/app/models/spree/tax_category.rb
+++ b/core/app/models/spree/tax_category.rb
@@ -4,6 +4,8 @@ module Spree
class TaxCategory < Spree::Base
include Spree::SoftDeletable
+ self.allowed_ransackable_attributes = %w[name description]
+
after_discard do
self.tax_rate_tax_categories = []
end