From 78899b4565c3437f7e32016181b72037269b876e Mon Sep 17 00:00:00 2001 From: Sam Pohlenz Date: Mon, 5 Aug 2024 21:28:26 +0930 Subject: [PATCH] Allow resource toolbar builder to accept custom label and attributes --- lib/trestle/resource/toolbar.rb | 26 ++++++++++----- lib/trestle/toolbar/context.rb | 2 +- spec/trestle/resource/toolbar_spec.rb | 47 ++++++++++++++++++++++----- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/lib/trestle/resource/toolbar.rb b/lib/trestle/resource/toolbar.rb index c5aa539b..1984da37 100644 --- a/lib/trestle/resource/toolbar.rb +++ b/lib/trestle/resource/toolbar.rb @@ -5,20 +5,30 @@ class Builder < Trestle::Toolbar::Builder delegate :admin, :instance, to: :@template delegate :translate, :t, to: :admin - def new - link(t("buttons.new", default: "New %{model_name}"), action: :new, style: :light, icon: "fa fa-plus", class: "btn-new-resource") if action?(:new) + def new(label: t("buttons.new", default: "New %{model_name}"), **attrs) + return unless action?(:new) + + defaults = { action: :new, style: :light, icon: "fa fa-plus", class: "btn-new-resource" } + link(label, defaults.merge(attrs)) end - def save - button(t("buttons.save", default: "Save %{model_name}"), style: :success) + def save(label: t("buttons.save", default: "Save %{model_name}"), **attrs) + defaults = { style: :success } + button(label, defaults.merge(attrs)) end - def delete - link(t("buttons.delete", default: "Delete %{model_name}"), instance, action: :destroy, style: :danger, icon: "fa fa-trash", data: { turbo_method: "delete", controller: "confirm-delete", confirm_delete_placement_value: "bottom" }) if action?(:destroy) + def delete(label: t("buttons.delete", default: "Delete %{model_name}"), **attrs) + return unless action?(:destroy) + + defaults = Trestle::Options.new(action: :destroy, style: :danger, icon: "fa fa-trash", data: { turbo_method: "delete", controller: "confirm-delete", confirm_delete_placement_value: "bottom" }) + link(label, instance, defaults.merge(attrs)) end - def dismiss - button(t("buttons.ok", default: "OK"), type: :button, style: :light, data: { bs_dismiss: "modal" }) if @template.modal_request? + def dismiss(label: t("buttons.ok", default: "OK"), **attrs) + return unless @template.modal_request? + + defaults = Trestle::Options.new(type: :button, style: :light, data: { bs_dismiss: "modal" }) + button(label, defaults.merge(attrs)) end alias ok dismiss diff --git a/lib/trestle/toolbar/context.rb b/lib/trestle/toolbar/context.rb index 916c265e..3133dc23 100644 --- a/lib/trestle/toolbar/context.rb +++ b/lib/trestle/toolbar/context.rb @@ -25,7 +25,7 @@ def respond_to_missing?(name, include_all=false) builder.respond_to?(name) || super end - def method_missing(name, *args, &block) + ruby2_keywords def method_missing(name, *args, &block) result = builder.send(name, *args, &block) if builder.builder_methods.include?(name) diff --git a/spec/trestle/resource/toolbar_spec.rb b/spec/trestle/resource/toolbar_spec.rb index 69dcd6b3..4371b270 100644 --- a/spec/trestle/resource/toolbar_spec.rb +++ b/spec/trestle/resource/toolbar_spec.rb @@ -8,6 +8,13 @@ subject(:builder) { Trestle::Resource::Toolbar::Builder.new(template) } + before(:each) do + allow(admin).to receive(:t).with("buttons.new", default: "New %{model_name}").and_return("New Resource") + allow(admin).to receive(:t).with("buttons.save", default: "Save %{model_name}").and_return("Save Resource") + allow(admin).to receive(:t).with("buttons.delete", default: "Delete %{model_name}").and_return("Delete Resource") + allow(admin).to receive(:t).with("buttons.ok", default: "OK").and_return("OK") + end + it "has a list of registered builder methods" do expect(builder.builder_methods).to include(:button, :link, :new, :save, :delete, :dismiss, :ok) end @@ -17,9 +24,16 @@ let(:actions) { [:new] } it "returns a new link" do - expect(admin).to receive(:t).with("buttons.new", default: "New %{model_name}").and_return("New Resource") expect(builder.new).to eq(Trestle::Toolbar::Link.new(template, "New Resource", action: :new, style: :light, icon: "fa fa-plus", class: "btn-new-resource")) end + + it "accepts a custom label" do + expect(builder.new(label: "Create")).to eq(Trestle::Toolbar::Link.new(template, "Create", action: :new, style: :light, icon: "fa fa-plus", class: "btn-new-resource")) + end + + it "accepts custom options" do + expect(builder.new(style: :success, icon: nil)).to eq(Trestle::Toolbar::Link.new(template, "New Resource", action: :new, style: :success, class: "btn-new-resource")) + end end context "when the admin actions does not include :new" do @@ -33,9 +47,16 @@ describe "#save" do it "returns a save button" do - expect(admin).to receive(:t).with("buttons.save", default: "Save %{model_name}").and_return("Save Resource") expect(builder.save).to eq(Trestle::Toolbar::Button.new(template, "Save Resource", style: :success)) end + + it "accepts a custom label" do + expect(builder.save(label: "Save Changes")).to eq(Trestle::Toolbar::Button.new(template, "Save Changes", style: :success)) + end + + it "accepts custom options" do + expect(builder.save(style: :light, icon: "fas fa-cloud")).to eq(Trestle::Toolbar::Button.new(template, "Save Resource", style: :light, icon: "fas fa-cloud")) + end end describe "#delete" do @@ -48,9 +69,16 @@ end it "returns a delete link" do - expect(admin).to receive(:t).with("buttons.delete", default: "Delete %{model_name}").and_return("Delete Resource") expect(builder.delete).to eq(Trestle::Toolbar::Link.new(template, "Delete Resource", instance, action: :destroy, style: :danger, icon: "fa fa-trash", data: { turbo_method: "delete", controller: "confirm-delete", confirm_delete_placement_value: "bottom" })) end + + it "accepts a custom label" do + expect(builder.delete(label: "Delete Me")).to eq(Trestle::Toolbar::Link.new(template, "Delete Me", instance, action: :destroy, style: :danger, icon: "fa fa-trash", data: { turbo_method: "delete", controller: "confirm-delete", confirm_delete_placement_value: "bottom" })) + end + + it "accepts custom options" do + expect(builder.delete(style: :warning, icon: "fas fa-bomb")).to eq(Trestle::Toolbar::Link.new(template, "Delete Resource", instance, action: :destroy, style: :warning, icon: "fas fa-bomb", data: { turbo_method: "delete", controller: "confirm-delete", confirm_delete_placement_value: "bottom" })) + end end context "when the admin actions does not include :destroy" do @@ -69,14 +97,20 @@ end it "returns a dismiss modal button" do - expect(admin).to receive(:t).with("buttons.ok", default: "OK").and_return("OK") expect(builder.dismiss).to eq(Trestle::Toolbar::Button.new(template, "OK", type: "button", style: :light, data: { bs_dismiss: "modal" })) end it "is aliased as #ok" do - expect(admin).to receive(:t).with("buttons.ok", default: "OK").and_return("OK").twice expect(builder.ok).to eq(builder.dismiss) end + + it "accepts a custom label" do + expect(builder.dismiss(label: "Cancel")).to eq(Trestle::Toolbar::Button.new(template, "Cancel", type: "button", style: :light, data: { bs_dismiss: "modal" })) + end + + it "accepts custom options" do + expect(builder.dismiss(style: :warning, data: { controller: "cancel" })).to eq(Trestle::Toolbar::Button.new(template, "OK", type: "button", style: :warning, data: { bs_dismiss: "modal", controller: "cancel" })) + end end context "from a non-modal request" do @@ -95,7 +129,6 @@ let(:actions) { [:update] } it "returns a save button" do - expect(admin).to receive(:t).with("buttons.save", default: "Save %{model_name}").and_return("Save Resource") expect(builder.save_or_dismiss).to eq(Trestle::Toolbar::Button.new(template, "Save Resource", style: :success)) end end @@ -109,7 +142,6 @@ end it "returns a dismiss modal button" do - expect(admin).to receive(:t).with("buttons.ok", default: "OK").and_return("OK") expect(builder.save_or_dismiss).to eq(Trestle::Toolbar::Button.new(template, "OK", type: "button", style: :light, data: { bs_dismiss: "modal" })) end end @@ -129,7 +161,6 @@ let(:actions) { [:create] } it "uses the given action to check whether to show a save button" do - expect(admin).to receive(:t).with("buttons.save", default: "Save %{model_name}").and_return("Save Resource") expect(builder.save_or_dismiss(:create)).to eq(Trestle::Toolbar::Button.new(template, "Save Resource", style: :success)) end end