Skip to content

Commit 9bb1242

Browse files
committed
feat: implement Oban worker for sending campaign emails with bulk enqueueing from the admin interface
1 parent 6aa80ed commit 9bb1242

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
defmodule Algora.Activities.Jobs.SendCampaignEmail do
2+
@moduledoc """
3+
Oban worker for sending campaign emails with duplicate prevention.
4+
"""
5+
use Oban.Worker, queue: :campaign_emails, unique: [period: :infinity, fields: [:args]]
6+
7+
alias AlgoraWeb.Admin.CampaignLive
8+
9+
@impl Oban.Worker
10+
def perform(%Oban.Job{args: %{"recipient" => recipient, "subject" => subject, "template_params" => template_params}}) do
11+
recipient = for {key, val} <- recipient, into: %{}, do: {String.to_atom(key), val}
12+
template_params = for {key, val} <- template_params, into: [], do: {String.to_atom(key), val}
13+
14+
CampaignLive.deliver_email(recipient, subject, template_params)
15+
end
16+
end

lib/algora_web/live/admin/campaign_live.ex

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ defmodule AlgoraWeb.Admin.CampaignLive do
55

66
import Ecto.Changeset
77

8+
alias Algora.Activities.Jobs.SendCampaignEmail
89
alias Algora.Mailer
910
alias AlgoraWeb.LocalStore
1011
alias Swoosh.Email
@@ -87,6 +88,29 @@ defmodule AlgoraWeb.Admin.CampaignLive do
8788
end
8889
end
8990

91+
@impl true
92+
def handle_event("send_all", _params, socket) do
93+
subject = get_change(socket.assigns.form.source, :subject)
94+
template = get_change(socket.assigns.form.source, :template)
95+
96+
jobs =
97+
Enum.map(socket.assigns.csv_data, fn recipient ->
98+
%{
99+
recipient: recipient,
100+
subject: subject,
101+
template_params: [markdown: render_preview(template, recipient), img: "#{recipient["repo_owner"]}.png"]
102+
}
103+
end)
104+
105+
case Oban.insert_all(SendCampaignEmail, jobs) do
106+
{:ok, _jobs} ->
107+
{:noreply, put_flash(socket, :info, "Enqueued #{length(jobs)} emails for sending")}
108+
109+
{:error, _} ->
110+
{:noreply, put_flash(socket, :error, "Failed to enqueue emails")}
111+
end
112+
end
113+
90114
@impl true
91115
def render(assigns) do
92116
~H"""
@@ -143,6 +167,11 @@ defmodule AlgoraWeb.Admin.CampaignLive do
143167
144168
<div>
145169
<div class="-mx-4 overflow-x-auto">
170+
<div class="flex justify-end mb-4">
171+
<.button type="button" phx-click="send_all">
172+
Send to {length(@csv_data)} Recipients
173+
</.button>
174+
</div>
146175
<.table id="csv-data" rows={@csv_data}>
147176
<:col :let={row} :for={key <- Map.keys(List.first(@csv_data) || %{})} label={key}>
148177
{row[key]}

0 commit comments

Comments
 (0)