diff --git a/admin/app/components/solidus_admin/layout/flashes/alerts/component.html.erb b/admin/app/components/solidus_admin/layout/flashes/alerts/component.html.erb new file mode 100644 index 00000000000..816626a867f --- /dev/null +++ b/admin/app/components/solidus_admin/layout/flashes/alerts/component.html.erb @@ -0,0 +1,7 @@ +
+ +
diff --git a/admin/app/components/solidus_admin/layout/flashes/alerts/component.rb b/admin/app/components/solidus_admin/layout/flashes/alerts/component.rb new file mode 100644 index 00000000000..7fbdb102c79 --- /dev/null +++ b/admin/app/components/solidus_admin/layout/flashes/alerts/component.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class SolidusAdmin::Layout::Flashes::Alerts::Component < SolidusAdmin::BaseComponent + attr_reader :alerts + + # Construct alert flashes like: + # flash[:alert] = { : { title: "", message: "" } } + # See +SolidusAdmin::UI::Alert::Component::SCHEMES+ for available alert types. + # + # If a string is passed to flash[:alert], we treat it is a body of the alert message and fall back to +danger+ type + # and default title (see +SolidusAdmin::UI::Alert::Component+). + def initialize(alerts:) + if alerts.is_a?(String) + alerts = { danger: { message: alerts } } + end + + @alerts = alerts.slice(*SolidusAdmin::UI::Alert::Component::SCHEMES.keys) + end +end diff --git a/admin/app/components/solidus_admin/layout/flashes/toasts/component.html.erb b/admin/app/components/solidus_admin/layout/flashes/toasts/component.html.erb new file mode 100644 index 00000000000..14ea6c06657 --- /dev/null +++ b/admin/app/components/solidus_admin/layout/flashes/toasts/component.html.erb @@ -0,0 +1,5 @@ + diff --git a/admin/app/components/solidus_admin/layout/flashes/toasts/component.rb b/admin/app/components/solidus_admin/layout/flashes/toasts/component.rb new file mode 100644 index 00000000000..3aecd62d0a0 --- /dev/null +++ b/admin/app/components/solidus_admin/layout/flashes/toasts/component.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class SolidusAdmin::Layout::Flashes::Toasts::Component < SolidusAdmin::BaseComponent + attr_reader :toasts + + def initialize(toasts:) + @toasts = toasts + end +end diff --git a/admin/app/components/solidus_admin/ui/alert/component.html.erb b/admin/app/components/solidus_admin/ui/alert/component.html.erb index a6a892fd2ae..60a7dae1591 100644 --- a/admin/app/components/solidus_admin/ui/alert/component.html.erb +++ b/admin/app/components/solidus_admin/ui/alert/component.html.erb @@ -18,7 +18,7 @@

<%= @title %>

-

<%= @description.html_safe %>

+

<%= @message.html_safe %>

diff --git a/admin/app/components/solidus_admin/ui/alert/component.rb b/admin/app/components/solidus_admin/ui/alert/component.rb index c183eaf8659..5605ce4b596 100644 --- a/admin/app/components/solidus_admin/ui/alert/component.rb +++ b/admin/app/components/solidus_admin/ui/alert/component.rb @@ -35,12 +35,16 @@ class SolidusAdmin::UI::Alert::Component < SolidusAdmin::BaseComponent }, } - def initialize(title:, description:, scheme: :success) + def initialize(title:, message:, scheme: :success) @title = title - @description = description + @message = message @scheme = scheme end + def before_render + @title = @title.presence || t(".defaults.titles")[@scheme.to_sym] + end + def icon icon_tag(ICONS.dig(@scheme.to_sym, :name), class: "w-5 h-5 #{ICONS.dig(@scheme.to_sym, :class)}") end diff --git a/admin/app/components/solidus_admin/ui/alert/component.yml b/admin/app/components/solidus_admin/ui/alert/component.yml index a97e4c40196..79f02ceb5e3 100644 --- a/admin/app/components/solidus_admin/ui/alert/component.yml +++ b/admin/app/components/solidus_admin/ui/alert/component.yml @@ -1,2 +1,8 @@ en: - close: Close + close: "Close" + defaults: + titles: + danger: "Caution" + info: "Info" + success: "Success" + warning: "Warning" diff --git a/admin/app/controllers/solidus_admin/adjustments_controller.rb b/admin/app/controllers/solidus_admin/adjustments_controller.rb index 350bc3dee5d..f085652211e 100644 --- a/admin/app/controllers/solidus_admin/adjustments_controller.rb +++ b/admin/app/controllers/solidus_admin/adjustments_controller.rb @@ -20,7 +20,7 @@ def index def lock @adjustments = @order.all_adjustments.not_finalized.where(id: params[:id]) @adjustments.each(&:finalize!) - flash[:success] = t('.success') + flash[:notice] = t('.success') redirect_to order_adjustments_path(@order), status: :see_other end @@ -28,7 +28,7 @@ def lock def unlock @adjustments = @order.all_adjustments.finalized.where(id: params[:id]) @adjustments.each(&:unfinalize!) - flash[:success] = t('.success') + flash[:notice] = t('.success') redirect_to order_adjustments_path(@order), status: :see_other end @@ -36,7 +36,7 @@ def unlock def destroy @adjustments = @order.all_adjustments.where(id: params[:id]) @adjustments.destroy_all - flash[:success] = t('.success') + flash[:notice] = t('.success') redirect_to order_adjustments_path(@order), status: :see_other end diff --git a/admin/app/controllers/solidus_admin/base_controller.rb b/admin/app/controllers/solidus_admin/base_controller.rb index bd7442f4eee..8854547389a 100644 --- a/admin/app/controllers/solidus_admin/base_controller.rb +++ b/admin/app/controllers/solidus_admin/base_controller.rb @@ -19,6 +19,7 @@ class BaseController < ApplicationController helper 'solidus_admin/components' helper 'solidus_admin/layout' + helper 'solidus_admin/flash' private diff --git a/admin/app/controllers/solidus_admin/customers_controller.rb b/admin/app/controllers/solidus_admin/customers_controller.rb index af79d4d483a..b86ef95c1e6 100644 --- a/admin/app/controllers/solidus_admin/customers_controller.rb +++ b/admin/app/controllers/solidus_admin/customers_controller.rb @@ -13,7 +13,7 @@ def show def destroy if @order.update(user: nil) - flash[:success] = t('.success') + flash[:notice] = t('.success') else flash[:error] = t('.error') end diff --git a/admin/app/controllers/solidus_admin/products_controller.rb b/admin/app/controllers/solidus_admin/products_controller.rb index e5f22336ed3..4475d11cb47 100644 --- a/admin/app/controllers/solidus_admin/products_controller.rb +++ b/admin/app/controllers/solidus_admin/products_controller.rb @@ -43,7 +43,7 @@ def update @product = Spree::Product.friendly.find(params[:id]) if @product.update(product_params) - flash[:success] = t('spree.successfully_updated', resource: [ + flash[:notice] = t('spree.successfully_updated', resource: [ Spree::Product.model_name.human, @product.name.inspect, ].join(' ')) diff --git a/admin/app/controllers/solidus_admin/users_controller.rb b/admin/app/controllers/solidus_admin/users_controller.rb index 7e7d181a1bd..04eaa09ac1e 100644 --- a/admin/app/controllers/solidus_admin/users_controller.rb +++ b/admin/app/controllers/solidus_admin/users_controller.rb @@ -37,7 +37,7 @@ def update_addresses set_address_from_params if @address.valid? && @user.update(user_params) - flash[:success] = t(".#{@type}.success") + flash[:notice] = t(".#{@type}.success") respond_to do |format| format.turbo_stream { render turbo_stream: '' } diff --git a/admin/app/helpers/solidus_admin/flash_helper.rb b/admin/app/helpers/solidus_admin/flash_helper.rb new file mode 100644 index 00000000000..81e35651f4b --- /dev/null +++ b/admin/app/helpers/solidus_admin/flash_helper.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Reserve :alert for messages that should go in UI alert component. Everything else will be shown in UI toast. +module SolidusAdmin + module FlashHelper + def toasts + flash.to_hash.with_indifferent_access.except(:alert) + end + + def alerts + flash.to_hash.with_indifferent_access.fetch(:alert, {}) + 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 6755eea3c1d..5508ea9da15 100644 --- a/admin/app/views/layouts/solidus_admin/application.html.erb +++ b/admin/app/views/layouts/solidus_admin/application.html.erb @@ -31,10 +31,7 @@
- + <%= render component("layout/flashes/alerts").new(alerts:) %> + <%= render component("layout/flashes/toasts").new(toasts:) %> diff --git a/admin/docs/index_pages.md b/admin/docs/index_pages.md index a17379d5529..d18c4b93592 100644 --- a/admin/docs/index_pages.md +++ b/admin/docs/index_pages.md @@ -94,7 +94,7 @@ end def delete @users = Spree.user_class.where(id: params[:id]) @users.destroy_all - flash[:success] = "Admin users deleted" + flash[:notice] = "Admin users deleted" redirect_to solidus_admin.users_path, status: :see_other end ``` diff --git a/admin/spec/components/previews/solidus_admin/ui/alert/component_preview/overview.html.erb b/admin/spec/components/previews/solidus_admin/ui/alert/component_preview/overview.html.erb index 6bdd3b2389c..ae0f5764dff 100644 --- a/admin/spec/components/previews/solidus_admin/ui/alert/component_preview/overview.html.erb +++ b/admin/spec/components/previews/solidus_admin/ui/alert/component_preview/overview.html.erb @@ -5,7 +5,7 @@
- <%= render current_component.new(scheme: :success, title: "Added Solidus T-Shirt", description: "Add another product or view product in a new window".html_safe) %> + <%= render current_component.new(scheme: :success, title: "Added Solidus T-Shirt", message: "Add another product or view product in a new window".html_safe) %>
@@ -15,7 +15,7 @@
- <%= render current_component.new(scheme: :warning, title: "No active stock locations left", description: "You can assign new active stock location here".html_safe) %> + <%= render current_component.new(scheme: :warning, title: "No active stock locations left", message: "You can assign new active stock location here".html_safe) %>
@@ -25,7 +25,7 @@
- <%= render current_component.new(scheme: :danger, title: "Request was not completed", description: "Cannot destroy default store") %> + <%= render current_component.new(scheme: :danger, title: "Request was not completed", message: "Cannot destroy default store") %>
@@ -35,7 +35,7 @@
- <%= render current_component.new(scheme: :info, title: "Locales available", description: "Did you know you can update storefront locales here?".html_safe) %> + <%= render current_component.new(scheme: :info, title: "Locales available", message: "Did you know you can update storefront locales here?".html_safe) %>
diff --git a/admin/spec/components/solidus_admin/layout/flashes/alerts/component_spec.rb b/admin/spec/components/solidus_admin/layout/flashes/alerts/component_spec.rb new file mode 100644 index 00000000000..046f737bcd5 --- /dev/null +++ b/admin/spec/components/solidus_admin/layout/flashes/alerts/component_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe SolidusAdmin::Layout::Flashes::Alerts::Component, type: :component do + let(:component) { described_class.new(alerts:) } + + context "when alerts passed as Hash" do + let(:alerts) do + { warning: { title: "Be careful", message: "Something fishy going on" } } + end + + it "renders correctly" do + render_inline(component) + + aggregate_failures do + expect(page).to have_content("Be careful") + expect(page).to have_content("Something fishy going on") + end + end + end + + context "when alerts passed as String" do + let(:alerts) { "Something fishy going on" } + + it "renders correctly" do + render_inline(component) + + aggregate_failures do + expect(page).to have_content("Caution") + expect(page).to have_content("Something fishy going on") + end + end + end + + describe "multiple alerts" do + let(:alerts) do + { + warning: { title: "Be careful", message: "Something fishy going on" }, + success: { title: "It worked", message: "Nothing to worry about!" } + } + end + + it "renders correctly" do + render_inline(component) + + aggregate_failures do + expect(page).to have_content("Be careful") + expect(page).to have_content("Something fishy going on") + expect(page).to have_content("It worked") + expect(page).to have_content("Nothing to worry about!") + end + end + end +end diff --git a/admin/spec/components/solidus_admin/layout/flashes/toasts/component_spec.rb b/admin/spec/components/solidus_admin/layout/flashes/toasts/component_spec.rb new file mode 100644 index 00000000000..1161a3cbb48 --- /dev/null +++ b/admin/spec/components/solidus_admin/layout/flashes/toasts/component_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe SolidusAdmin::Layout::Flashes::Toasts::Component, type: :component do + let(:component) { described_class.new(toasts:) } + + describe "error toast" do + let(:toasts) { { error: "Some error" } } + + it "renders correctly" do + render_inline(component) + + aggregate_failures do + expect(page).to have_content("Some error") + expect(page).to have_css(".bg-red-500") + end + end + end + + describe "default toast" do + let(:toasts) { { notice: "All good" } } + + it "renders correctly" do + render_inline(component) + + aggregate_failures do + expect(page).to have_content("All good") + expect(page).to have_css(".bg-full-black") + end + end + end +end diff --git a/admin/spec/components/solidus_admin/ui/alert/component_spec.rb b/admin/spec/components/solidus_admin/ui/alert/component_spec.rb index 0927fefcb34..4c284925c18 100644 --- a/admin/spec/components/solidus_admin/ui/alert/component_spec.rb +++ b/admin/spec/components/solidus_admin/ui/alert/component_spec.rb @@ -6,4 +6,29 @@ it "renders the overview preview" do render_preview(:overview) end + + describe "defaults" do + let(:component) { described_class.new(title:, message:, scheme:) } + let(:title) { "Title" } + let(:message) { "Message" } + let(:scheme) { :success } + + context "when title is not present" do + let(:title) { nil } + + shared_examples_for "with default title" do |scheme, expected_title| + let(:scheme) { scheme } + + it "renders default title for scheme #{scheme}" do + render_inline(component) + expect(page).to have_content(expected_title) + end + end + + it_behaves_like "with default title", :success, "Success" + it_behaves_like "with default title", :warning, "Warning" + it_behaves_like "with default title", :danger, "Caution" + it_behaves_like "with default title", :info, "Info" + end + end end