Aggiunge il rilevamento di invio e apertura delle email di campagna.
CI / scan_ruby (push) Failing after 12m56s
CI / scan_js (push) Successful in 12m23s
CI / lint (push) Failing after 12m15s

Ogni destinatario mostra se la mail è partita e se è stata aperta, con conteggi in dashboard.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-20 12:26:14 +02:00
co-authored by Cursor
parent ab57309f5c
commit 2db7504629
18 changed files with 332 additions and 5 deletions
@@ -17,6 +17,7 @@
<div class="mt-4"><%= progress_bar(mailing.progress_percentage, color: mailing.failed_count.positive? ? "bg-amber-500" : "bg-emerald-500") %></div>
<div class="mt-2 flex flex-wrap gap-3 text-sm text-zinc-600 dark:text-zinc-300">
<span><strong class="tabular-nums"><%= mailing.sent_count %></strong> inviate</span>
<span><strong class="tabular-nums"><%= mailing.opened_count %></strong> aperte</span>
<span><strong class="tabular-nums"><%= mailing.pending_count %></strong> in coda</span>
<span><strong class="tabular-nums"><%= mailing.skipped_count %></strong> escluse</span>
<% if mailing.failed_count.positive? %>
+2 -1
View File
@@ -73,7 +73,7 @@
</div>
<div class="mt-3"><%= progress_bar(mailing.progress_percentage) %></div>
<div class="mt-2 text-xs text-zinc-500">
<%= mailing.sent_count %> inviate · <%= mailing.pending_count %> in coda
<%= mailing.sent_count %> inviate · <%= mailing.opened_count %> aperte · <%= mailing.pending_count %> in coda
<% if mailing.sending? && mailing.next_send_at.present? && mailing.next_send_at > Time.current %>
· Riparte <%= l(mailing.next_send_at, format: :short) %>
<% end %>
@@ -106,6 +106,7 @@
<%= progress_bar(mailing.progress_percentage) %>
<div class="mt-1 text-xs text-zinc-500">
<%= mailing.sent_count %> inviate
· <%= mailing.opened_count %> aperte
· <%= mailing.pending_count %> in coda
<% if mailing.failed_count.positive? %>
· <span class="text-rose-700"><%= mailing.failed_count %> errori</span>
+52 -2
View File
@@ -62,6 +62,21 @@
</div>
</div>
<% if @mailing.sending? || @mailing.sent? || @mailing.cancelled? %>
<div class="grid grid-cols-2 gap-3">
<div class="<%= card_class %> p-4">
<div class="text-xs uppercase tracking-wide text-zinc-500">Aperte</div>
<div class="mt-1 text-2xl font-semibold"><%= @mailing.opened_count %></div>
<p class="mt-1 text-xs text-zinc-500">su <%= @mailing.sent_count %> inviate</p>
</div>
<div class="<%= card_class %> p-4">
<div class="text-xs uppercase tracking-wide text-zinc-500">Tasso apertura</div>
<div class="mt-1 text-2xl font-semibold tabular-nums"><%= @mailing.open_rate %>%</div>
<p class="mt-1 text-xs text-zinc-500">Si rileva quando il client carica le immagini.</p>
</div>
</div>
<% end %>
<% if @mailing.ab_test? %>
<div class="grid gap-4 sm:grid-cols-2">
<div class="<%= card_class %> p-4">
@@ -70,7 +85,11 @@
<%= ab_variant_badge("A") %>
</div>
<div class="mt-1 text-2xl font-semibold"><%= @mailing.variant_sent_count("A") %> inviate</div>
<p class="mt-1 text-xs text-zinc-500"><%= @mailing.variant_pending_count("A") %> in coda · <%= @mailing.subject %></p>
<p class="mt-1 text-xs text-zinc-500">
<%= @mailing.variant_opened_count("A") %> aperte
· <%= @mailing.variant_pending_count("A") %> in coda
· <%= @mailing.subject %>
</p>
</div>
<div class="<%= card_class %> p-4">
<div class="flex items-center justify-between">
@@ -78,7 +97,11 @@
<%= ab_variant_badge("B") %>
</div>
<div class="mt-1 text-2xl font-semibold"><%= @mailing.variant_sent_count("B") %> inviate</div>
<p class="mt-1 text-xs text-zinc-500"><%= @mailing.variant_pending_count("B") %> in coda · <%= @mailing.subject_b %></p>
<p class="mt-1 text-xs text-zinc-500">
<%= @mailing.variant_opened_count("B") %> aperte
· <%= @mailing.variant_pending_count("B") %> in coda
· <%= @mailing.subject_b %>
</p>
</div>
</div>
<% end %>
@@ -131,6 +154,7 @@
<div class="flex flex-wrap items-center gap-2">
<%= link_to recipient.organization.name, recipient.organization, class: "font-medium hover:underline" %>
<%= mailing_recipient_status_badge(recipient.status) %>
<%= mailing_open_badge(recipient) %>
<% if @mailing.ab_test? %><%= ab_variant_badge(recipient.ab_variant) %><% end %>
</div>
<div class="mt-1 text-sm break-anywhere text-zinc-600 dark:text-zinc-300">
@@ -148,6 +172,17 @@
<% if recipient.error_message.present? %>
<div class="mt-1 text-xs text-rose-700"><%= recipient.error_message %></div>
<% end %>
<% if recipient.sent_at.present? %>
<div class="mt-1 text-xs text-zinc-500">
Inviata <%= format_dt(recipient.sent_at) %>
<% if recipient.opened? %>
· aperta <%= format_dt(recipient.opened_at) %>
<% if recipient.open_count > 1 %>
· <%= recipient.open_count %> rilevamenti
<% end %>
<% end %>
</div>
<% end %>
<% if recipient.email_ok? %>
<%= link_to "Anteprima", mailing_path(@mailing, recipient_id: recipient.id, variant: recipient.ab_variant), class: "mt-2 inline-block text-sm text-zinc-700 hover:underline dark:text-zinc-300" %>
<% end %>
@@ -167,6 +202,7 @@
<th class="px-4 py-3">Test</th>
<% end %>
<th class="px-4 py-3">Stato</th>
<th class="px-4 py-3">Apertura</th>
<th class="px-4 py-3"></th>
</tr>
</thead>
@@ -195,11 +231,25 @@
<% if recipient.error_message.present? %>
<div class="text-xs text-rose-700"><%= recipient.error_message %></div>
<% end %>
<% if recipient.sent_at.present? %>
<div class="text-xs text-zinc-500">Inviata <%= format_dt(recipient.sent_at) %></div>
<% end %>
</td>
<% if @mailing.ab_test? %>
<td class="px-4 py-3"><%= ab_variant_badge(recipient.ab_variant) || "—" %></td>
<% end %>
<td class="px-4 py-3"><%= mailing_recipient_status_badge(recipient.status) %></td>
<td class="px-4 py-3">
<%= mailing_open_badge(recipient) || "—" %>
<% if recipient.opened? %>
<div class="mt-1 text-xs text-zinc-500">
<%= format_dt(recipient.opened_at) %>
<% if recipient.open_count > 1 %>
· <%= recipient.open_count %>×
<% end %>
</div>
<% end %>
</td>
<td class="px-4 py-3 text-right text-sm">
<% if recipient.email_ok? %>
<%= link_to "Anteprima", mailing_path(@mailing, recipient_id: recipient.id, variant: recipient.ab_variant), class: "text-zinc-700 hover:underline dark:text-zinc-300" %>