Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use turbo frames for remote forms #2712

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 14 additions & 16 deletions app/assets/javascripts/alchemy/alchemy.dialog.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,23 @@ 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()
return
form.bind "ajax:error", (event, b, c) =>
statusText = event.detail[1]
xhr = event.detail[2]
@show_error(xhr, statusText)
watch_turbo_frames: ->
frame = $('turbo-frame[id="alchemy-form"]', @dialog_body)
frame.bind "turbo:before-fetch-response", (event) =>
response = event.detail.fetchResponse.response
switch response.status
when 200
if response.redirected
event.preventDefault()
@options.closed = => Turbo.visit(response.url)
@close()
when 500
@show_error(response)
return
return

# Displays an error message
show_error: (xhr, status_message, $container = @dialog_body) ->
Expand Down
17 changes: 11 additions & 6 deletions app/controllers/alchemy/admin/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -100,19 +100,24 @@ def render_errors_or_redirect(object, redirect_url, flash_notice)
flash[:notice] = Alchemy.t(flash_notice)
do_redirect_to redirect_url
else
render action: ((params[:action] == "update") ? "edit" : "new")
render action: ((params[:action] == "update") ? "edit" : "new"), status: :unprocessable_entity
end
end

# Does redirects for html and js requests
#
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

Expand Down
15 changes: 9 additions & 6 deletions app/controllers/alchemy/admin/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 3 additions & 2 deletions app/helpers/alchemy/admin/form_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions app/javascript/alchemy_admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import "alchemy_admin/components/clipboard_button"
import "alchemy_admin/components/datepicker"
import "alchemy_admin/components/dialog_link"
import "alchemy_admin/components/element_editor"
import "alchemy_admin/components/growl"
import "alchemy_admin/components/ingredient_group"
import "alchemy_admin/components/link_buttons"
import "alchemy_admin/components/node_select"
Expand Down
10 changes: 10 additions & 0 deletions app/javascript/alchemy_admin/components/growl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Growl extends HTMLElement {
connectedCallback() {
Alchemy.growl(
this.getAttribute("message"),
this.getAttribute("type") || "notice"
)
}
}

customElements.define("alchemy-growl", Growl)
10 changes: 10 additions & 0 deletions app/views/alchemy/admin/pages/update.turbo_stream.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<alchemy-growl message="<%= @notice %>"></alchemy-growl>
<% if @page.layoutpage %>
<%= turbo_stream.replace @page do %>
<%= render "alchemy/admin/layoutpages/layoutpage", layoutpage: @page %>
<% end %>
<% else %>
<%= turbo_stream.replace @page do %>
<%= render "page", page: @page %>
<% end %>
<% end %>
8 changes: 4 additions & 4 deletions spec/controllers/alchemy/admin/pages_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@
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
end

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
Expand Down
Loading