From ed2bcb56d778ae1872c2be783364ba0fd89005f8 Mon Sep 17 00:00:00 2001 From: Elia Schito Date: Wed, 29 Nov 2023 13:10:31 +0100 Subject: [PATCH 1/5] Move the feedback link to the bottom of the page --- .../layout/feedback/component.html.erb | 26 +++++++++++-------- .../layout/feedback/component.yml | 2 +- .../solidus_admin/layout/page_helpers.rb | 4 +-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/admin/app/components/solidus_admin/layout/feedback/component.html.erb b/admin/app/components/solidus_admin/layout/feedback/component.html.erb index a22267c44cd..4ce8d630bc4 100644 --- a/admin/app/components/solidus_admin/layout/feedback/component.html.erb +++ b/admin/app/components/solidus_admin/layout/feedback/component.html.erb @@ -1,11 +1,15 @@ - -<%= render component("ui/button").new( - tag: :a, - text: t(".give_feedback"), - href: "https://solidus.io/feedback?category=solidus-admin", - icon: "feedback-line", - scheme: :secondary, - target: :_blank, -) %> +<%= link_to( + "https://solidus.io/feedback?category=solidus-admin", + class: 'whitespace-nowrap flex flex-col items-center gap-2 text-gray-500 text-small hover:text-black', + target: '_blank', +) do %> + + + <%= render component("ui/badge").new(name: "beta", size: :s, color: :blue) %> + <%= t(".give_feedback") %> + + + + <%= t(".feedback_description_html") %> + +<% end %> diff --git a/admin/app/components/solidus_admin/layout/feedback/component.yml b/admin/app/components/solidus_admin/layout/feedback/component.yml index 7cea13f36b8..4a4bd690d0f 100644 --- a/admin/app/components/solidus_admin/layout/feedback/component.yml +++ b/admin/app/components/solidus_admin/layout/feedback/component.yml @@ -2,4 +2,4 @@ # Use the translation in the example in your template with `t(".hello")`. en: give_feedback: 'Give feedback' - feedback_description: 'We are constantly trying to improve. Please let us know what you think about this admin page.' + feedback_description_html: 'We are constantly trying to improve.
Please let us know what you think about this admin page.' diff --git a/admin/app/components/solidus_admin/layout/page_helpers.rb b/admin/app/components/solidus_admin/layout/page_helpers.rb index bd196e59b1d..8327aa668ed 100644 --- a/admin/app/components/solidus_admin/layout/page_helpers.rb +++ b/admin/app/components/solidus_admin/layout/page_helpers.rb @@ -2,12 +2,12 @@ module SolidusAdmin::Layout::PageHelpers def page(**attrs, &block) - tag.div(capture(&block), class: "px-4 relative", "data-controller": stimulus_id, **attrs) + tag.div(capture(&block), class: "px-4 relative", "data-controller": stimulus_id, **attrs) + + tag.div(render(component("layout/feedback").new), class: "flex justify-center py-10") end def page_header_actions(&block) tag.div(safe_join([ - render(component("layout/feedback").new), capture(&block), ]), class: "flex gap-2 items-center") end From a8662f97a5e996d74a74b81e40c5b8d4233820f1 Mon Sep 17 00:00:00 2001 From: Elia Schito Date: Mon, 27 Nov 2023 16:13:08 +0100 Subject: [PATCH 2/5] Allow `ui/table` to be in search mode by default if no scopes/filters are provided --- .../solidus_admin/ui/table/component.html.erb | 58 ++++++++++--------- .../solidus_admin/ui/table/component.js | 11 +++- .../solidus_admin/ui/table/component.rb | 7 ++- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/admin/app/components/solidus_admin/ui/table/component.html.erb b/admin/app/components/solidus_admin/ui/table/component.html.erb index 9cc1c93d653..8e71602dd4d 100644 --- a/admin/app/components/solidus_admin/ui/table/component.html.erb +++ b/admin/app/components/solidus_admin/ui/table/component.html.erb @@ -37,13 +37,15 @@ ) %> <% end %> -
- <%= render component("ui/button").new( - text: t('.cancel'), - scheme: :ghost, - "data-action": "#{stimulus_id}#cancelSearch", - ) %> -
+ <% if @search.scopes.any? %> +
+ <%= render component("ui/button").new( + text: t('.cancel'), + scheme: :ghost, + "data-action": "#{stimulus_id}#cancelSearch", + ) %> +
+ <% end %> <% end %> <% if @search.filters.any? %> @@ -54,28 +56,30 @@ <% end %> <% end %> - <%= render component("ui/table/toolbar").new("data-#{stimulus_id}-target": "scopesToolbar", hidden: initial_mode != "scopes") do %> -
- <%= form_with(url: @search.url, method: :get) do %> - <% @search.scopes.each do |scope| %> - <%= render component("ui/tab").new( - tag: :button, - type: :submit, - text: scope.label, - current: scope == @search.current_scope, - name: @search.scope_param_name, - value: scope.name, - ) %> + <% if @search.scopes.any? %> + <%= render component("ui/table/toolbar").new("data-#{stimulus_id}-target": "scopesToolbar", hidden: initial_mode != "scopes") do %> +
+ <%= form_with(url: @search.url, method: :get) do %> + <% @search.scopes.each do |scope| %> + <%= render component("ui/tab").new( + tag: :button, + type: :submit, + text: scope.label, + current: scope == @search.current_scope, + name: @search.scope_param_name, + value: scope.name + ) %> + <% end %> <% end %> - <% end %> -
+
- <%= render component("ui/button").new( - 'aria-label': t('.filter'), - icon: "filter-3-line", - scheme: :secondary, - "data-action": "#{stimulus_id}#showSearch", - ) %> + <%= render component("ui/button").new( + "aria-label": t(".filter"), + icon: "filter-3-line", + scheme: :secondary, + "data-action": "#{stimulus_id}#showSearch" + ) %> + <% end %> <% end %> diff --git a/admin/app/components/solidus_admin/ui/table/component.js b/admin/app/components/solidus_admin/ui/table/component.js index d6a5b196f9e..1b634fb2066 100644 --- a/admin/app/components/solidus_admin/ui/table/component.js +++ b/admin/app/components/solidus_admin/ui/table/component.js @@ -64,8 +64,10 @@ export default class extends Controller { this.modeValue = "batch" } else if (this.searchFieldTarget.value !== '') { this.modeValue = "search" - } else { + } else if (this.hasScopesToolbarTarget) { this.modeValue = "scopes" + } else { + this.modeValue = "search" } this.render() @@ -76,8 +78,10 @@ export default class extends Controller { this.modeValue = "batch" } else if (this.searchFieldTarget.value !== '') { this.modeValue = "search" - } else { + } else if (this.hasScopesToolbarTarget) { this.modeValue = "scopes" + } else { + this.modeValue = "search" } this.checkboxTargets.forEach((checkbox) => (checkbox.checked = event.target.checked)) @@ -118,7 +122,8 @@ export default class extends Controller { this.batchHeaderTarget.toggleAttribute("hidden", this.modeValue !== "batch") this.defaultHeaderTarget.toggleAttribute("hidden", this.modeValue === "batch") - this.scopesToolbarTarget.toggleAttribute("hidden", this.modeValue !== "scopes") + if (this.hasScopesToolbarTarget) + this.scopesToolbarTarget.toggleAttribute("hidden", this.modeValue !== "scopes") // Update the rows background color this.checkboxTargets.filter((checkbox) => diff --git a/admin/app/components/solidus_admin/ui/table/component.rb b/admin/app/components/solidus_admin/ui/table/component.rb index fbc7edda4f9..88546843299 100644 --- a/admin/app/components/solidus_admin/ui/table/component.rb +++ b/admin/app/components/solidus_admin/ui/table/component.rb @@ -152,6 +152,11 @@ def current_scope_name end def initial_mode - @initial_mode ||= @search.value[@search.searchbar_key] ? "search" : "scopes" + @initial_mode ||= + if @search.value[@search.searchbar_key] || @search.scopes.none? + "search" + else + "scopes" + end end end From 0004821afbacd91fa746f19ed9d8fbe16fe53b01 Mon Sep 17 00:00:00 2001 From: Elia Schito Date: Mon, 27 Nov 2023 16:14:02 +0100 Subject: [PATCH 3/5] Allow columns to be defined as simple symbols When both the header and the data are defaulting to an AR attribute passing just the symbol should suffice. --- admin/app/components/solidus_admin/ui/table/component.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/admin/app/components/solidus_admin/ui/table/component.rb b/admin/app/components/solidus_admin/ui/table/component.rb index 88546843299..f25a4549f55 100644 --- a/admin/app/components/solidus_admin/ui/table/component.rb +++ b/admin/app/components/solidus_admin/ui/table/component.rb @@ -11,7 +11,9 @@ class Data < Struct.new(:rows, :class, :url, :prev, :next, :columns, :fade, :bat def initialize(**args) super - self.columns = columns.map { |column| Column.new(wrap: false, **column) } + self.columns = columns.map do |column| + column.is_a?(Symbol) ? Column.new(wrap: false, header: column, data: column) : Column.new(wrap: false, **column) + end self.batch_actions = batch_actions.to_a.map { |action| BatchAction.new(**action) } end From 515a7ddba44bdf0601bffa0337de007bbe9acbf8 Mon Sep 17 00:00:00 2001 From: Elia Schito Date: Wed, 29 Nov 2023 17:07:29 +0100 Subject: [PATCH 4/5] Add support for "aria-current" to `ui/button` --- .../components/solidus_admin/ui/button/component.rb | 8 ++++---- .../ui/button/component_preview/overview.html.erb | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/admin/app/components/solidus_admin/ui/button/component.rb b/admin/app/components/solidus_admin/ui/button/component.rb index dc3daae8097..1a1fd0433c2 100644 --- a/admin/app/components/solidus_admin/ui/button/component.rb +++ b/admin/app/components/solidus_admin/ui/button/component.rb @@ -32,7 +32,7 @@ class SolidusAdmin::UI::Button::Component < SolidusAdmin::BaseComponent primary: %{ text-white bg-black hover:text-white hover:bg-gray-600 - active:text-white active:bg-gray-800 + active:text-white active:bg-gray-800 aria-current:text-white aria-current:bg-gray-800 focus:text-white focus:bg-gray-700 disabled:text-gray-400 disabled:bg-gray-100 aria-disabled:text-gray-400 aria-disabled:bg-gray-100 @@ -40,7 +40,7 @@ class SolidusAdmin::UI::Button::Component < SolidusAdmin::BaseComponent secondary: %{ text-gray-700 bg-white border border-1 border-gray-200 hover:bg-gray-50 - active:bg-gray-100 + active:bg-gray-100 aria-current:bg-gray-100 focus:bg-gray-50 disabled:text-gray-300 disabled:bg-white aria-disabled:text-gray-300 aria-disabled:bg-white @@ -48,7 +48,7 @@ class SolidusAdmin::UI::Button::Component < SolidusAdmin::BaseComponent danger: %{ text-red-500 bg-white border border-1 border-red-500 hover:bg-red-500 hover:border-red-600 hover:text-white - active:bg-red-600 active:border-red-700 active:text-white + active:bg-red-600 active:border-red-700 active:text-white aria-current:bg-red-600 aria-current:border-red-700 aria-current:text-white focus:bg-red-50 focus:bg-red-500 focus:border-red-600 focus:text-white disabled:text-red-300 disabled:bg-white disabled:border-red-200 aria-disabled:text-red-300 aria-disabled:bg-white aria-disabled:border-red-200 @@ -56,7 +56,7 @@ class SolidusAdmin::UI::Button::Component < SolidusAdmin::BaseComponent ghost: %{ text-gray-700 bg-transparent hover:bg-gray-50 - active:bg-gray-100 + active:bg-gray-100 aria-current:bg-gray-100 focus:bg-gray-50 focus:ring-gray-300 focus:ring-2 disabled:text-gray-300 disabled:bg-transparent disabled:border-gray-300 aria-disabled:text-gray-300 aria-disabled:bg-transparent aria-disabled:border-gray-300 diff --git a/admin/spec/components/previews/solidus_admin/ui/button/component_preview/overview.html.erb b/admin/spec/components/previews/solidus_admin/ui/button/component_preview/overview.html.erb index e75311a40f2..6a18306c9eb 100644 --- a/admin/spec/components/previews/solidus_admin/ui/button/component_preview/overview.html.erb +++ b/admin/spec/components/previews/solidus_admin/ui/button/component_preview/overview.html.erb @@ -11,7 +11,7 @@ <%= size.to_s.humanize %> <% end %> - <% %i[default disabled].each do |state| %> + <% %i[default disabled current].each do |state| %> <%= state.to_s.humanize %> <% current_component::SIZES.keys.each do |size| %> @@ -21,13 +21,14 @@ scheme: scheme, text: text, icon: ('search-line' if show_icon), - disabled: state == :disabled + disabled: state == :disabled, + "aria-current": state == :current ? true : nil, ) %> <% end %> <% end %> - <% %i[default disabled].each do |state| %> + <% %i[default disabled current].each do |state| %> <%= state.to_s.humanize %> <% current_component::SIZES.keys.each do |size| %> @@ -36,7 +37,8 @@ size: size, scheme: scheme, icon: ('filter-3-line' if show_icon), - disabled: state == :disabled + disabled: state == :disabled, + "aria-current": state == :current ? true : nil, ) %> <% end %> From 4881c399575640bf3f99dea8a4ebd181fbf817ab Mon Sep 17 00:00:00 2001 From: Elia Schito Date: Mon, 27 Nov 2023 16:29:10 +0100 Subject: [PATCH 5/5] Add a tax categories index with scopes and batch deletion --- .../tax_categories/index/component.html.erb | 32 ++++++++++ .../tax_categories/index/component.rb | 58 +++++++++++++++++++ .../tax_categories/index/component.yml | 6 ++ .../solidus_admin/taxes/component.html.erb | 23 ++++++++ .../solidus_admin/taxes/component.rb | 6 ++ .../solidus_admin/taxes/component.yml | 3 + .../tax_categories_controller.rb | 40 +++++++++++++ admin/config/locales/tax_categories.en.yml | 6 ++ admin/config/routes.rb | 6 ++ admin/spec/features/tax_categories_spec.rb | 24 ++++++++ 10 files changed, 204 insertions(+) create mode 100644 admin/app/components/solidus_admin/tax_categories/index/component.html.erb create mode 100644 admin/app/components/solidus_admin/tax_categories/index/component.rb create mode 100644 admin/app/components/solidus_admin/tax_categories/index/component.yml create mode 100644 admin/app/components/solidus_admin/taxes/component.html.erb create mode 100644 admin/app/components/solidus_admin/taxes/component.rb create mode 100644 admin/app/components/solidus_admin/taxes/component.yml create mode 100644 admin/app/controllers/solidus_admin/tax_categories_controller.rb create mode 100644 admin/config/locales/tax_categories.en.yml create mode 100644 admin/spec/features/tax_categories_spec.rb diff --git a/admin/app/components/solidus_admin/tax_categories/index/component.html.erb b/admin/app/components/solidus_admin/tax_categories/index/component.html.erb new file mode 100644 index 00000000000..deba4262bd7 --- /dev/null +++ b/admin/app/components/solidus_admin/tax_categories/index/component.html.erb @@ -0,0 +1,32 @@ +<%= render component('taxes').new do |layout| %> + <% layout.with_actions do %> + <%= render component("ui/button").new( + tag: :a, + text: t('.add'), + href: spree.new_admin_tax_category_path, + icon: "add-line", + class: "align-self-end w-full", + ) %> + <% end %> + + <%= render component('ui/table').new( + id: stimulus_id, + data: { + class: Spree::TaxCategory, + rows: @page.records, + url: ->(tax_category) { spree.edit_admin_tax_category_path(tax_category) }, + prev: prev_page_path, + next: next_page_path, + columns: columns, + batch_actions: batch_actions, + }, + search: { + name: :q, + value: params[:q], + url: solidus_admin.tax_categories_path, + searchbar_key: :name_or_description_cont, + filters: filters, + scopes: scopes, + }, + ) %> +<% end %> diff --git a/admin/app/components/solidus_admin/tax_categories/index/component.rb b/admin/app/components/solidus_admin/tax_categories/index/component.rb new file mode 100644 index 00000000000..252f146b01c --- /dev/null +++ b/admin/app/components/solidus_admin/tax_categories/index/component.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +class SolidusAdmin::TaxCategories::Index::Component < SolidusAdmin::BaseComponent + include SolidusAdmin::Layout::PageHelpers + + def initialize(page:) + @page = page + end + + def title + Spree::TaxCategory.model_name.human.pluralize + end + + def prev_page_path + solidus_admin.url_for(**request.params, page: @page.number - 1, only_path: true) unless @page.first? + end + + def next_page_path + solidus_admin.url_for(**request.params, page: @page.next_param, only_path: true) unless @page.last? + end + + def batch_actions + [ + { + display_name: t('.batch_actions.delete'), + action: solidus_admin.tax_categories_path, + method: :delete, + icon: 'delete-bin-7-line', + }, + ] + end + + def filters + [] + end + + def scopes + [] + end + + def columns + [ + :name, + :tax_code, + :description, + { + header: :is_default, + data: ->(tax_category) { + if tax_category.is_default? + component('ui/badge').new(name: t('.yes'), color: :green) + else + component('ui/badge').new(name: t('.no'), color: :graphite_light) + end + }, + }, + ] + end +end diff --git a/admin/app/components/solidus_admin/tax_categories/index/component.yml b/admin/app/components/solidus_admin/tax_categories/index/component.yml new file mode 100644 index 00000000000..faff41bc439 --- /dev/null +++ b/admin/app/components/solidus_admin/tax_categories/index/component.yml @@ -0,0 +1,6 @@ +en: + "yes": "Yes" + "no": "No" + add: 'Add new' + batch_actions: + delete: 'Delete' diff --git a/admin/app/components/solidus_admin/taxes/component.html.erb b/admin/app/components/solidus_admin/taxes/component.html.erb new file mode 100644 index 00000000000..c78b28ca5c1 --- /dev/null +++ b/admin/app/components/solidus_admin/taxes/component.html.erb @@ -0,0 +1,23 @@ +<%= page do %> + <%= page_header do %> + <%= page_header_title safe_join([ + tag.div(t(".title")), + tag.div(t(".subtitle"), class: "body-small text-gray-500"), + ]) %> + <% end %> + + <%= page_header do %> + <% title = capture do %> + <%= render(component('ui/button').new(tag: :a, scheme: :ghost, text: Spree::TaxCategory.model_name.human.pluralize, href: solidus_admin.tax_categories_path, "aria-current": true)) %> + <%= render(component('ui/button').new(tag: :a, scheme: :ghost, text: Spree::TaxRate.model_name.human.pluralize, href: spree.admin_tax_rates_path, current: false)) %> + <% end %> + + <%= page_header_title title %> + + <%= page_header_actions do %> + <%= actions %> + <% end %> + <% end %> + + <%= content %> +<% end %> diff --git a/admin/app/components/solidus_admin/taxes/component.rb b/admin/app/components/solidus_admin/taxes/component.rb new file mode 100644 index 00000000000..f0a4c0ddd84 --- /dev/null +++ b/admin/app/components/solidus_admin/taxes/component.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class SolidusAdmin::Taxes::Component < SolidusAdmin::BaseComponent + include SolidusAdmin::Layout::PageHelpers + renders_one :actions +end diff --git a/admin/app/components/solidus_admin/taxes/component.yml b/admin/app/components/solidus_admin/taxes/component.yml new file mode 100644 index 00000000000..ac34486a08a --- /dev/null +++ b/admin/app/components/solidus_admin/taxes/component.yml @@ -0,0 +1,3 @@ +en: + title: "Taxes" + subtitle: "Configure tax rates and tax categories for products and shipping in different markets." diff --git a/admin/app/controllers/solidus_admin/tax_categories_controller.rb b/admin/app/controllers/solidus_admin/tax_categories_controller.rb new file mode 100644 index 00000000000..f5f0bc1378e --- /dev/null +++ b/admin/app/controllers/solidus_admin/tax_categories_controller.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +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, + ) + + set_page_and_extract_portion_from(tax_categories) + + respond_to do |format| + format.html { render component('tax_categories/index').new(page: @page) } + end + end + + def destroy + @tax_categories = Spree::TaxCategory.where(id: params[:id]) + + Spree::TaxCategory.transaction { @tax_categories.destroy_all } + + flash[:notice] = t('.success') + redirect_back_or_to tax_categories_path, status: :see_other + end + + private + + def load_tax_category + @tax_category = Spree::TaxCategory.find_by!(number: params[:id]) + authorize! action_name, @tax_category + end + + def tax_category_params + params.require(:tax_category).permit(:tax_category_id, permitted_tax_category_attributes) + end + end +end diff --git a/admin/config/locales/tax_categories.en.yml b/admin/config/locales/tax_categories.en.yml new file mode 100644 index 00000000000..9162bb44069 --- /dev/null +++ b/admin/config/locales/tax_categories.en.yml @@ -0,0 +1,6 @@ +en: + solidus_admin: + tax_categories: + title: "Tax Categories" + destroy: + success: "Tax categories were successfully removed." diff --git a/admin/config/routes.rb b/admin/config/routes.rb index eeb32c0884e..ef9f5d1afa8 100644 --- a/admin/config/routes.rb +++ b/admin/config/routes.rb @@ -42,4 +42,10 @@ delete :destroy end end + + resources :tax_categories, only: [:index] do + collection do + delete :destroy + end + end end diff --git a/admin/spec/features/tax_categories_spec.rb b/admin/spec/features/tax_categories_spec.rb new file mode 100644 index 00000000000..8909ca5e74a --- /dev/null +++ b/admin/spec/features/tax_categories_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe "Tax categories", :js, type: :feature do + before { sign_in create(:admin_user, email: 'admin@example.com') } + + it "lists tax categories and allows deleting them" do + create(:tax_category, name: "Clothing") + create(:tax_category, name: "Food") + + visit "/admin/tax_categories" + expect(page).to have_content("Clothing") + expect(page).to have_content("Food") + expect(page).to be_axe_clean + + select_row("Clothing") + click_on "Delete" + expect(page).to have_content("Tax categories were successfully removed.") + expect(page).not_to have_content("Clothing") + expect(Spree.user_class.count).to eq(1) + expect(page).to be_axe_clean + end +end