From 4e03fa58abcfa0b0a6b8f907578a0e3af6c3c5df Mon Sep 17 00:00:00 2001 From: Emiliano Frascaro Date: Tue, 18 Aug 2026 23:03:35 +0200 Subject: [PATCH] Aggiorna lo stato dell'invio email senza ricaricare la pagina. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Così la lista destinatari si aggiorna in corso d'opera senza riportare lo scroll in cima. Co-authored-by: Cursor --- .../controllers/auto_reload_controller.js | 45 +++++++++++++++---- app/views/mailings/dashboard.html.erb | 2 + app/views/mailings/show.html.erb | 2 + test/controllers/mailings_controller_test.rb | 13 ++++++ 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/app/javascript/controllers/auto_reload_controller.js b/app/javascript/controllers/auto_reload_controller.js index 5b05c0c..47a275f 100644 --- a/app/javascript/controllers/auto_reload_controller.js +++ b/app/javascript/controllers/auto_reload_controller.js @@ -4,17 +4,46 @@ export default class extends Controller { static values = { interval: { type: Number, default: 10000 } } connect() { - this.timer = setInterval(() => { - if (document.hidden) return - if (window.Turbo?.visit) { - window.Turbo.visit(window.location.href, { action: "replace" }) - } else { - window.location.reload() - } - }, this.intervalValue) + this.timer = setInterval(() => this.refresh(), this.intervalValue) } disconnect() { clearInterval(this.timer) } + + refresh() { + if (document.hidden) return + + const frame = this.element.closest("turbo-frame") + if (frame && typeof frame.reload === "function") { + this.reloadFrame(frame) + return + } + + this.refreshPreservingScroll() + } + + reloadFrame(frame) { + if (frame.hasAttribute("busy")) return + + const url = window.location.href + if (frame.getAttribute("src") === url) { + frame.reload() + } else { + frame.setAttribute("src", url) + } + } + + refreshPreservingScroll() { + const { scrollX, scrollY } = window + const restore = () => window.scrollTo(scrollX, scrollY) + document.addEventListener("turbo:render", restore, { once: true }) + document.addEventListener("turbo:load", restore, { once: true }) + + if (window.Turbo?.visit) { + window.Turbo.visit(window.location.href, { action: "replace" }) + } else { + window.location.reload() + } + } } diff --git a/app/views/mailings/dashboard.html.erb b/app/views/mailings/dashboard.html.erb index f5e46dc..479f760 100644 --- a/app/views/mailings/dashboard.html.erb +++ b/app/views/mailings/dashboard.html.erb @@ -1,4 +1,5 @@ <% refresh = @active_mailings.any? %> +<%= turbo_frame_tag "mailings_dashboard_live", target: "_top", refresh: "morph" do %> <%= tag.div class: "space-y-6", data: (refresh ? { controller: "auto-reload", auto_reload_interval_value: 10_000 } : {}) do %>
@@ -135,3 +136,4 @@ <% end %>
<% end %> +<% end %> diff --git a/app/views/mailings/show.html.erb b/app/views/mailings/show.html.erb index 0b4dba6..f74afdd 100644 --- a/app/views/mailings/show.html.erb +++ b/app/views/mailings/show.html.erb @@ -1,3 +1,4 @@ +<%= turbo_frame_tag "mailing_live", target: "_top", refresh: "morph" do %> <%= tag.div class: "space-y-6", data: (@mailing.sending? ? { controller: "auto-reload", auto_reload_interval_value: 10_000 } : {}) do %>
@@ -280,3 +281,4 @@
<% end %> +<% end %> diff --git a/test/controllers/mailings_controller_test.rb b/test/controllers/mailings_controller_test.rb index 1e6a59c..cbd3edc 100644 --- a/test/controllers/mailings_controller_test.rb +++ b/test/controllers/mailings_controller_test.rb @@ -205,4 +205,17 @@ class MailingsControllerTest < ActionDispatch::IntegrationTest assert_equal "invio annullato", recipients.second.skip_reason assert mailing.mailing_recipients.pending.none? end + + test "sending mailing show updates inside a turbo frame" do + login_as users(:admin) + follow_redirect! if response.redirect? + mailing = create_mailing(identity: @identity, audience: "to_send") + mailing.rebuild_recipients! + mailing.update!(status: "sending", queued_at: Time.current, test_sent_at: Time.current, test_sent_to: "test@example.com") + + get mailing_path(mailing, project_code: @project.code) + assert_response :success + assert_select "turbo-frame#mailing_live[target=_top]" + assert_select "[data-controller='auto-reload']" + end end