From 95cba7b9b2b5e9109f4f7e027e888fc9498f8e18 Mon Sep 17 00:00:00 2001 From: T Floyd Wright Date: Mon, 11 May 2026 15:07:26 -0800 Subject: [PATCH] fix: avoid progress bar oscillation during bulk actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The action handler on the index page wrapped each record in try/rescue/after, so the `after` clause broadcast progress: 1 after every record — making the active jobs nav flash between the partial and complete states across iterations. Drop the after clause and rely on the per-iteration progress broadcast, indexing from 1 so it reaches 100% naturally on the last record. On a halted/crashed run, the nav already cleans up via the :DOWN monitor on the task pid. Also switch from Enum.each to Enum.reduce_while so the loop actually halts on a record-level error, matching the "encountered an error and stopped" message that gets announced. --- lib/live_admin/components/resource/index.ex | 41 ++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/live_admin/components/resource/index.ex b/lib/live_admin/components/resource/index.ex index 5623350..3ef93ac 100644 --- a/lib/live_admin/components/resource/index.ex +++ b/lib/live_admin/components/resource/index.ex @@ -393,9 +393,12 @@ defmodule LiveAdmin.Components.Container.Index do job = Task.Supervisor.async_nolink(LiveAdmin.Task.Supervisor, fn -> - socket.assigns.selected - |> Enum.with_index() - |> Enum.each(fn {id, idx} -> + selected = socket.assigns.selected + total = Enum.count(selected) + + selected + |> Enum.with_index(1) + |> Enum.reduce_while(:ok, fn {id, idx}, _ -> try do id |> Resource.find(resource, prefix, repo, config) @@ -405,28 +408,32 @@ defmodule LiveAdmin.Components.Container.Index do end LiveAdmin.PubSub.update_job(session.id, self(), - progress: idx / Enum.count(socket.assigns.selected), + progress: idx / total, label: name ) + + {:cont, :ok} rescue error -> Logger.error(inspect(error)) - - LiveAdmin.PubSub.announce( - session.id, - :error, - trans("%{name} encountered an error and stopped", inter: [name: name]) - ) - after - LiveAdmin.PubSub.update_job(session.id, self(), progress: 1) + {:halt, :error} end end) + |> case do + :ok -> + LiveAdmin.PubSub.announce( + session.id, + :info, + trans("%{name} complete", inter: [name: name]) + ) - LiveAdmin.PubSub.announce( - session.id, - :info, - trans("%{name} complete", inter: [name: name]) - ) + :error -> + LiveAdmin.PubSub.announce( + session.id, + :error, + trans("%{name} encountered an error and stopped", inter: [name: name]) + ) + end end) LiveAdmin.PubSub.update_job(session.id, job.pid, progress: 0, label: to_string(name))