From b396c129d9941ec6531df1e0a68aafe5da9bc612 Mon Sep 17 00:00:00 2001 From: Paul Bob <69730720+Paul-Bob@users.noreply.github.com> Date: Fri, 12 Jul 2024 16:30:35 +0300 Subject: [PATCH] feature: allow actions to render turbo streams (#2796) * feature: allow actions to render turbo streams * lint * fix & test * rename & drop turbo_stream keyword * lint * fix tests * lint --- app/controllers/avo/actions_controller.rb | 22 +++++++++++++------ lib/avo/base_action.rb | 5 +++++ .../dummy/app/avo/actions/test/close_modal.rb | 4 ++++ spec/system/avo/actions_spec.rb | 4 +++- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/controllers/avo/actions_controller.rb b/app/controllers/avo/actions_controller.rb index b719b0fe5a..f7f6bedc3a 100644 --- a/app/controllers/avo/actions_controller.rb +++ b/app/controllers/avo/actions_controller.rb @@ -89,13 +89,13 @@ def respond respond_to do |format| format.turbo_stream do - case @response[:type] + turbo_response = case @response[:type] when :keep_modal_open # Only render the flash messages if the action keeps the modal open - render turbo_stream: turbo_stream.flash_alerts + turbo_stream.flash_alerts when :download # Trigger download, removes modal and flash the messages - render turbo_stream: [ + [ turbo_stream.download(content: Base64.encode64(@response[:path]), filename: @response[:filename]), turbo_stream.close_action_modal, turbo_stream.flash_alerts @@ -104,16 +104,16 @@ def respond frame_id = Avo::ACTIONS_TURBO_FRAME_ID src, _ = @response[:action].link_arguments(resource: @action.resource, **@response[:navigate_to_action_args]) - render turbo_stream: turbo_stream.turbo_frame_set_src(frame_id, src) + turbo_stream.turbo_frame_set_src(frame_id, src) when :redirect - render turbo_stream: turbo_stream.redirect_to( + turbo_stream.redirect_to( Avo::ExecutionContext.new(target: @response[:path]).handle, turbo_frame: @response[:redirect_args][:turbo_frame], **@response[:redirect_args].except(:turbo_frame) ) when :close_modal # Close the modal and flash the messages - render turbo_stream: [ + [ turbo_stream.close_action_modal, turbo_stream.flash_alerts ] @@ -121,8 +121,16 @@ def respond # Reload the page back_path = request.referer || params[:referrer].presence || resources_path(resource: @resource) - render turbo_stream: turbo_stream.redirect_to(back_path) + turbo_stream.redirect_to(back_path) end + + responses = if @action.appended_turbo_streams.present? + Array(turbo_response) + Array(instance_exec(&@action.appended_turbo_streams)) + else + Array(turbo_response) + end + + render turbo_stream: responses end end end diff --git a/lib/avo/base_action.rb b/lib/avo/base_action.rb index 17ab2e5d37..702080d718 100644 --- a/lib/avo/base_action.rb +++ b/lib/avo/base_action.rb @@ -21,6 +21,7 @@ class BaseAction attr_accessor :user attr_reader :arguments attr_reader :icon + attr_reader :appended_turbo_streams # TODO: find a differnet way to delegate this to the uninitialized Current variable delegate :context, to: Avo::Current @@ -291,6 +292,10 @@ def authorized? ).handle end + def append_to_response(turbo_stream) + @appended_turbo_streams = turbo_stream + end + private def add_message(body, type = :info) diff --git a/spec/dummy/app/avo/actions/test/close_modal.rb b/spec/dummy/app/avo/actions/test/close_modal.rb index 7f4e3bf1fa..5a28fc98e0 100644 --- a/spec/dummy/app/avo/actions/test/close_modal.rb +++ b/spec/dummy/app/avo/actions/test/close_modal.rb @@ -9,5 +9,9 @@ def handle(**args) TestBuddy.hi "Hello from Avo::Actions::Test::CloseModal handle method" succeed "Modal closed!!" close_modal + + append_to_response -> { + turbo_stream.set_title("Cool title") + } end end diff --git a/spec/system/avo/actions_spec.rb b/spec/system/avo/actions_spec.rb index 18a5cbb872..700a01dc6a 100644 --- a/spec/system/avo/actions_spec.rb +++ b/spec/system/avo/actions_spec.rb @@ -210,6 +210,7 @@ fill_in "user_first_name", with: "First name should persist after action." + expect(page).to have_title("Create new user — Avocadelicious") click_on "Actions" click_on "Close modal" @@ -218,7 +219,8 @@ click_on "Run" expect(page).not_to have_selector(modal) expect(page).to have_text "Modal closed!!" - expect(page).to have_field('user_first_name', with: 'First name should persist after action.') + expect(page).to have_title("Cool title") + expect(page).to have_field("user_first_name", with: "First name should persist after action.") end end