From fe3ef3700eff3e37c47bf7ba8763e97ba33474ae Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Fri, 2 Feb 2024 07:54:01 +0100 Subject: [PATCH] Use turbo frames for remote forms --- .../alchemy/alchemy.dialog.js.coffee | 23 +++++++++---------- .../alchemy/admin/base_controller.rb | 15 ++++++++---- .../alchemy/admin/pages_controller.rb | 15 +++++++----- app/helpers/alchemy/admin/form_helper.rb | 5 ++-- .../alchemy/admin/pages_controller_spec.rb | 8 +++---- 5 files changed, 37 insertions(+), 29 deletions(-) diff --git a/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee b/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee index e652690eba..ad030c2530 100644 --- a/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +++ b/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee @@ -98,21 +98,20 @@ class window.Alchemy.Dialog # Initializes the Dialog body init: -> Alchemy.GUI.init(@dialog_body) - @watch_remote_forms() + @watch_turbo_frames() # Watches ajax requests inside of dialog body and replaces the content accordingly - watch_remote_forms: -> - form = $('[data-remote="true"]', @dialog_body) - form.bind "ajax:success", (event) => - xhr = event.detail[2] - content_type = xhr.getResponseHeader('Content-Type') - if content_type.match(/javascript/) - return - else - @dialog_body.html(xhr.responseText) - @init() + watch_turbo_frames: -> + frame = $('turbo-frame[id="alchemy-form"]', @dialog_body) + frame.bind "turbo:before-fetch-response", (event) => + response = event.detail.fetchResponse.response + if response.redirected + event.preventDefault() + @options.closed = => Turbo.visit(response.url) + @close() return - form.bind "ajax:error", (event, b, c) => + return + frame.bind "turbo:fetch-request-error", (event, b, c) => statusText = event.detail[1] xhr = event.detail[2] @show_error(xhr, statusText) diff --git a/app/controllers/alchemy/admin/base_controller.rb b/app/controllers/alchemy/admin/base_controller.rb index e36f133e67..3e721c2216 100644 --- a/app/controllers/alchemy/admin/base_controller.rb +++ b/app/controllers/alchemy/admin/base_controller.rb @@ -31,9 +31,9 @@ def leave private - # Disable layout rendering for xhr requests. + # Disable layout rendering for xhr or turbo frame requests. def set_layout - request.xhr? ? false : "alchemy/admin" + (request.xhr? || turbo_frame_request?) ? false : "alchemy/admin" end # Handles exceptions @@ -108,11 +108,16 @@ def render_errors_or_redirect(object, redirect_url, flash_notice) # def do_redirect_to(url_or_path) respond_to do |format| - format.js { + format.js do @redirect_url = url_or_path render :redirect - } - format.html { redirect_to url_or_path } + end + format.turbo_stream do + redirect_to url_or_path + end + format.html do + redirect_to url_or_path + end end end diff --git a/app/controllers/alchemy/admin/pages_controller.rb b/app/controllers/alchemy/admin/pages_controller.rb index 4501715696..c3dae9e41d 100644 --- a/app/controllers/alchemy/admin/pages_controller.rb +++ b/app/controllers/alchemy/admin/pages_controller.rb @@ -149,16 +149,19 @@ def destroy flash[:warning] = @page.errors.full_messages.to_sentence end + @redirect_url = if @page.layoutpage? + alchemy.admin_layoutpages_path + else + alchemy.admin_pages_path + end + respond_to do |format| format.js do - @redirect_url = if @page.layoutpage? - alchemy.admin_layoutpages_path - else - alchemy.admin_pages_path - end - render :redirect end + format.turbo_stream do + redirect_to @redirect_url + end end end diff --git a/app/helpers/alchemy/admin/form_helper.rb b/app/helpers/alchemy/admin/form_helper.rb index 36710fa8e9..2b2c24edc5 100644 --- a/app/helpers/alchemy/admin/form_helper.rb +++ b/app/helpers/alchemy/admin/form_helper.rb @@ -16,12 +16,13 @@ module FormHelper def alchemy_form_for(object, *args, &block) options = args.extract_options! options[:builder] = Alchemy::Forms::Builder - options[:remote] = request.xhr? options[:html] = { id: options.delete(:id), class: ["alchemy", options.delete(:class)].compact.join(" ") } - simple_form_for(object, *(args << options), &block) + turbo_frame_tag("alchemy-form") do + simple_form_for(object, *(args << options), &block) + end end end end diff --git a/spec/controllers/alchemy/admin/pages_controller_spec.rb b/spec/controllers/alchemy/admin/pages_controller_spec.rb index cbb248ad44..561bf390e0 100644 --- a/spec/controllers/alchemy/admin/pages_controller_spec.rb +++ b/spec/controllers/alchemy/admin/pages_controller_spec.rb @@ -54,8 +54,8 @@ let!(:node) { create(:alchemy_node, page: page) } it "returns with error message" do - delete :destroy, params: {id: page.id, format: :js} - expect(response).to render_template(:redirect) + delete :destroy, params: {id: page.id}, as: :turbo_stream + expect(response).to redirect_to("/admin/pages") expect(flash[:warning]).to \ eq("Nodes are still attached to this page. Please remove them first.") end @@ -63,8 +63,8 @@ context "without nodes" do it "removes the page" do - delete :destroy, params: {id: page.id, format: :js} - expect(response).to render_template(:redirect) + delete :destroy, params: {id: page.id}, as: :turbo_stream + expect(response).to redirect_to("/admin/pages") expect(flash[:notice]).to eq Alchemy.t("Page deleted", name: page.name) end end