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(scheme: :secondary, text: t('.cancel')) %> +
+ <%= 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'), - ) %> +
+ <%= render component('ui/button').new( + 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