nuntius 1.4.9 → 1.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ccc43faba64c7face2decf37a6c33b775ea9d6c13dd36cc08ec86da58da0bbd
4
- data.tar.gz: f43c4cf84c238bd62956151a468a0adc62c1e798589e02b70ffe85be899a1ad8
3
+ metadata.gz: 5a1dcbc1e10bce99c94c7537d5091e32bcaa588b51d92a884a001978a1dd24fa
4
+ data.tar.gz: '09cb3a5e7da66b49c8e755ab3f4956d1933d3197749de506e7693649f480141a'
5
5
  SHA512:
6
- metadata.gz: db7b5cd54668c544ad6ca9494b350ec2585e3f504bdeb68aa4ce2b8f56a344ee36d2d09b9802d8d3dbd8ecc9df5f8e2d59648ee30f577b65e64e14170a84e21a
7
- data.tar.gz: 96dbae515949cf5c24d9936712ac8d0068283fce076314943eacb6439b98e0f36329a8e0a5a95f75e2b19322a4c9891117100d2dda90b9186f10e991391abb84
6
+ metadata.gz: 9ac1da3a93afccd8b1da9f79b652e8749081daa4394bf468c902f700445257ca5e722a43b30ea874372eeb15c5f40f45c393a4de07e47223f72984c6b6148a70
7
+ data.tar.gz: 402bd584c757524017bcd83d5773737711fe5542b0359cf6546a3addcf0c99c789e811581a1f058371a1cdd9a072560f1765079933ae167a04b449e172084720
data/README.md CHANGED
@@ -230,6 +230,8 @@ In the layout you can add `<a href="{{message_url}}">Link to mail</a>` to provid
230
230
  Nuntius supports email tracking, to enable this, you need to enable tracking for a template.
231
231
  Nuntius will then inject a tracking pixel and track clicks on links.
232
232
 
233
+ Per link you can disable tracking by adding `data-nuntius-tracking="false"` to the link.
234
+
233
235
  #### AWS SES
234
236
 
235
237
  In case you use AWS SES, you can use the SNS Feedback Notifications to automatically mark messages as read, or deal with complaints and bounces. Create a AWS SNS topic, with a HTTPS subscription with the following URL (pattern):
@@ -38,7 +38,7 @@ module Nuntius
38
38
  private
39
39
 
40
40
  def subscriber_params
41
- params.require(:subscriber).permit(:first_name, :last_name, :email, :phone_number, tags: [])
41
+ params.require(:subscriber).permit(:first_name, :last_name, :email, :phone_number, :metadata_yaml, tags: [])
42
42
  end
43
43
 
44
44
  def set_objects
@@ -13,9 +13,7 @@ module Nuntius
13
13
 
14
14
  # GET /messages/:message_id/pixel.gif
15
15
  def pixel
16
- return if request.env["HTTP_REFERER"].to_s.include?(Nuntius.config.host(@message))
17
-
18
- if @message&.open_tracking_enabled?
16
+ if external? && @message&.open_tracking_enabled?
19
17
  # Record the first open time
20
18
  @message.opened_at ||= Time.current
21
19
  @message.open_count = (@message.open_count || 0) + 1
@@ -28,11 +26,9 @@ module Nuntius
28
26
 
29
27
  # GET /messages/:message_id/link?url=...
30
28
  def link
31
- return if request.env["HTTP_REFERER"].to_s.include?(Nuntius.config.host(@message))
32
-
33
29
  url = params[:url]
34
30
 
35
- if @message&.link_tracking_enabled? && url.present?
31
+ if external? && @message&.link_tracking_enabled? && url.present?
36
32
  # Record the first click time
37
33
  @message.clicked_at ||= Time.current
38
34
  @message.click_count = (@message.click_count || 0) + 1
@@ -53,6 +49,10 @@ module Nuntius
53
49
 
54
50
  private
55
51
 
52
+ def external?
53
+ request.env["HTTP_REFERER"].to_s.include?(Nuntius.config.host(@message))
54
+ end
55
+
56
56
  def set_objects
57
57
  @message = Nuntius::Message.find(params[:id])
58
58
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Nuntius
4
4
  class SubscriberDrop < ApplicationDrop
5
- delegate :id, :first_name, :last_name, :name, :list, to: :@object
5
+ delegate :id, :first_name, :last_name, :name, :list, :metadata, to: :@object
6
6
  end
7
7
  end
@@ -2,11 +2,15 @@
2
2
 
3
3
  module Nuntius
4
4
  class Subscriber < ApplicationRecord
5
+ include Nuntius::Concerns::Yamlify
6
+
5
7
  belongs_to :list, counter_cache: :subscribers_count
6
8
  belongs_to :nuntiable, polymorphic: true, optional: true
7
9
 
8
10
  scope :subscribed, -> { where(unsubscribed_at: nil) }
9
11
 
12
+ yamlify :metadata
13
+
10
14
  def name
11
15
  [first_name, last_name].compact.join(" ").presence || email
12
16
  end
@@ -22,13 +22,16 @@ module Nuntius
22
22
  end
23
23
 
24
24
  def new_message(subscriber, assigns = {})
25
+ message = Nuntius::Message.create!(transport: campaign.transport, campaign: campaign, nuntiable: subscriber.nuntiable, metadata: campaign.metadata)
26
+
25
27
  assigns["campaign"] = context.campaign
26
28
  assigns["subscriber"] = subscriber
29
+ assigns["subscriber_link"] = subscriber_link(subscriber, message)
30
+
27
31
  if subscriber.nuntiable
28
32
  name = Nuntius::BaseMessenger.liquid_variable_name_for(subscriber.nuntiable)
29
33
  assigns[name] = subscriber.nuntiable
30
34
  end
31
- message = Nuntius::Message.new(transport: campaign.transport, campaign: campaign, nuntiable: subscriber.nuntiable, metadata: campaign.metadata)
32
35
 
33
36
  locale = nil
34
37
  if subscriber.nuntiable
@@ -49,6 +52,7 @@ module Nuntius
49
52
  message.subject = render(:subject, assigns, locale)
50
53
  message.html = render(:html, assigns, locale, layout: campaign.layout&.data)
51
54
 
55
+ message.save!
52
56
  message
53
57
  end
54
58
 
@@ -58,6 +62,11 @@ module Nuntius
58
62
  scope.join(".")
59
63
  end
60
64
 
65
+ def subscriber_link(subscriber, message)
66
+ url = Nuntius::Engine.routes.url_helpers.subscriber_url(subscriber, host: Nuntius.config.host(message))
67
+ "<a href=\"#{url}\" data-nuntius-tracking=\"false\">#{t("subscriber_url_text")}</a>"
68
+ end
69
+
61
70
  private
62
71
 
63
72
  def render(attr, assigns, locale, options = {})
@@ -41,6 +41,8 @@ module Nuntius
41
41
  doc = Nokogiri::HTML.fragment(html)
42
42
 
43
43
  doc.css("a[href]").each do |link|
44
+ next if link["data-nuntius-tracking"] == "false"
45
+
44
46
  original_url = link["href"]
45
47
 
46
48
  # Skip if it's a mailto, tel, anchor link or liquid variable
@@ -15,7 +15,7 @@
15
15
  .col-span-4
16
16
  = f.association :layout, collection: @layouts
17
17
  .col-span-4
18
- = f.association :list, collection: @lists
18
+ = f.association :list, collection: @lists, hint: t(".list_hint")
19
19
 
20
20
  .col-span-12
21
21
  = f.input :from, hint: t(".from_hint")
@@ -39,5 +39,31 @@
39
39
  .col-span-12
40
40
  = f.input :text, as: :editor, mode: 'text/plain'
41
41
  - else
42
- = sts.card :nuntius_admin_campaigns, title: @campaign.name, description: 'We are sending or have sent this campaign, you can no longer make any changes.', icon: 'fal fa-megaphone', content_padding: false do |card|
43
- = sts.table :"nuntius/campaign_messages", params: { campaign_id: @campaign.id }
42
+ = sts.card :nuntius_admin_campaigns, title: @campaign.name, icon: 'fal fa-megaphone', content_padding: false do |card|
43
+ - card.with_tab :statistics, padding: true do |tab|
44
+ .grid.grid-cols-4.gap-4
45
+ .col-span-4
46
+ dl.grid.grid-cols-4.gap-1.overflow-hidden.rounded-2xl.text-center.sm:grid-cols-4.lg:grid-cols-4
47
+ .flex.flex-col.bg-gray-200.p-8
48
+ dt.text-sm.font-semibold.leading-6.text-gray-600
49
+ = t(".messages_sent")
50
+ dd.order-first.text-3xl.font-semibold.tracking-tight.text-gray-900
51
+ = @campaign.messages.where(status: "sent").count
52
+ .flex.flex-col.bg-gray-200.p-8
53
+ dt.text-sm.font-semibold.leading-6.text-gray-600
54
+ = t(".messages_not_sent")
55
+ dd.order-first.text-3xl.font-semibold.tracking-tight.text-gray-900
56
+ = @campaign.messages.where.not(status: "sent").count
57
+ .flex.flex-col.bg-gray-200.p-8
58
+ dt.text-sm.font-semibold.leading-6.text-gray-600
59
+ = t(".messages_opened")
60
+ dd.order-first.text-3xl.font-semibold.tracking-tight.text-gray-900
61
+ = @campaign.messages.where("open_count >= 1").count
62
+ .flex.flex-col.bg-gray-200.p-8
63
+ dt.text-sm.font-semibold.leading-6.text-gray-600
64
+ = t(".messages_clicked")
65
+ dd.order-first.text-3xl.font-semibold.tracking-tight.text-gray-900
66
+ = @campaign.messages.where("click_count >= 1").count
67
+
68
+ - card.with_tab :messages, padding: false do |tab|
69
+ = sts.table :"nuntius/campaign_messages", params: { campaign_id: @campaign.id }
@@ -25,4 +25,4 @@
25
25
 
26
26
  - if @layout.templates.exists?
27
27
  - card.with_tab :templates, padding: false
28
- = sts.table :"nuntius/templates", filters: { layout_id: @layout.id }
28
+ = sts.table :"nuntius/templates", params: { layout_id: @layout.id }
@@ -1,2 +1,2 @@
1
1
  = sts.card :nuntius_admin_layouts, icon: 'fad fa-table-layout', content_padding: false, menu: nuntius_layouts_menu do |card|
2
- = sts.table :"nuntius/layouts", custom_views: true
2
+ = sts.table :"nuntius/layouts"
@@ -19,4 +19,4 @@
19
19
 
20
20
  - if @list.subscribers.exists?
21
21
  - card.with_tab :subscribers, padding: false
22
- = sts.table :"nuntius/subscribers", filters: { list_id: @list.id }
22
+ = sts.table :"nuntius/subscribers", params: { list_id: @list.id }
@@ -12,3 +12,5 @@
12
12
  = f.input :phone_number
13
13
  .col-span-12
14
14
  = f.input :email
15
+ .col-span-12
16
+ = f.input :metadata_yaml, as: :editor, mode: 'application/yaml', label: t('.metadata')
@@ -1,4 +1,4 @@
1
- = sts.card :nuntius_admin_messages, title: [t('.message'), @message.template&.description], icon: 'fad fa-envelope' do |card|
1
+ = sts.card :nuntius_admin_messages, title: [t('.message'), @message.template&.description||@message.campaign&.name], icon: 'fad fa-envelope' do |card|
2
2
  - card.with_action
3
3
  = button_to(t('nuntius.context_menu.resend'), resend_admin_message_path(@message), class: 'button')
4
4
 
@@ -85,4 +85,4 @@
85
85
 
86
86
  - if @template.messages.exists?
87
87
  - card.with_tab :messages, padding: false
88
- = sts.table :"nuntius/messages", filters: { template_id: @template.id }
88
+ = sts.table :"nuntius/messages", params: { template_id: @template.id }
@@ -1,2 +1,2 @@
1
1
  = sts.card :nuntius_admin_templates, icon: 'fad fa-file', content_padding: false, menu: nuntius_templates_menu do |card|
2
- = sts.table :"nuntius/templates", custom_views: true
2
+ = sts.table :"nuntius/templates"
@@ -1,4 +1,5 @@
1
1
  en:
2
+ subscriber_url_text: "Click here to unsubscribe"
2
3
  choose_files: Choose files
3
4
  activerecord:
4
5
  attributes:
@@ -57,7 +58,17 @@ en:
57
58
  nuntius_admin_campaigns:
58
59
  title: Campaigns
59
60
  from_hint: "You can leave this blank, only fill this in if you want to override the default"
61
+ list_hint: "You can re-use a list from a previous campaign, for the same purpose. Unsubscribes happen against the list."
60
62
  metadata: Metadata
63
+ tabs:
64
+ main:
65
+ tab:
66
+ statistics: Statistics
67
+ messages: Messages
68
+ messages_sent: Messages sent
69
+ messages_not_sent: Messages not sent
70
+ messages_opened: Messages opened
71
+ messages_clicked: Messages clicked
61
72
  index:
62
73
  card:
63
74
  nuntius_admin_campaigns:
@@ -99,6 +110,7 @@ en:
99
110
  title: Lists
100
111
  subscribers:
101
112
  edit:
113
+ metadata: Metadata
102
114
  subscribers: Subscribers
103
115
  locales:
104
116
  edit:
@@ -1,11 +1,13 @@
1
1
  nl:
2
+ subscriber_url_text: "Klik hier om uit te schrijven"
2
3
  choose_files: Kies bestanden
3
4
  activerecord:
4
5
  attributes:
5
6
  nuntius/campaign:
6
7
  from: Van
7
- layout: Layout
8
- list: Lijst
8
+ layout_id: Layout
9
+ list_id: Lijst
10
+ list_name: Lijst naam
9
11
  name: Naam
10
12
  state: Staat
11
13
  subject: Onderwerp
@@ -28,6 +30,17 @@ nl:
28
30
  subject: Onderwerp
29
31
  to: Aan
30
32
  transport: Transport
33
+ messages_count: Aantal berichten
34
+ nuntius/message:
35
+ to: Aan
36
+ from: Van
37
+ subject: Onderwerp
38
+ transport: Transport
39
+ last_sent_at: Laatste keer verzonden
40
+ open_count: Aantal geopend
41
+ click_count: Aantal geklikt
42
+ campaign_id: Campagne
43
+ created_at: Aangemaakt om
31
44
  models:
32
45
  campaign: Campagne
33
46
  layout: Layout
@@ -58,6 +71,16 @@ nl:
58
71
  title: Campagne
59
72
  metadata: Metadata
60
73
  from_hint: "Je kunt dit leeg laten, vul dit alleen in als je de standaard wilt overschrijven"
74
+ list_hint: "Je kunt een lijst hergebruiken van een vorige campagne, voor hetzelfde doel. Uitschrijvingen gebeuren tegen de lijst."
75
+ tabs:
76
+ main:
77
+ tab:
78
+ statistics: Statistieken
79
+ messages: Berichten
80
+ messages_sent: Berichten verzonden
81
+ messages_not_sent: Berichten niet verzonden
82
+ messages_opened: Berichten geopend
83
+ messages_clicked: Berichten geklikt
61
84
  index:
62
85
  card:
63
86
  nuntius_admin_campaigns:
@@ -100,6 +123,7 @@ nl:
100
123
  title: Lijsten
101
124
  subscribers:
102
125
  edit:
126
+ metadata: Metadata
103
127
  subscribers: Abonnees
104
128
  locales:
105
129
  edit:
@@ -0,0 +1,5 @@
1
+ class AddMetadataToSubscriber < ActiveRecord::Migration[8.1]
2
+ def change
3
+ add_column :nuntius_subscribers, :metadata, :jsonb, default: {}
4
+ end
5
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nuntius
4
- VERSION = "1.4.9"
4
+ VERSION = "1.4.10"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nuntius
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.9
4
+ version: 1.4.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom de Grunt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-24 00:00:00.000000000 Z
11
+ date: 2026-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: apnotic
@@ -566,6 +566,7 @@ files:
566
566
  - db/migrate/20250521132554_update_nuntius_events_index.rb
567
567
  - db/migrate/20260123160443_change_nuntius_events_id.rb
568
568
  - db/migrate/20260210122500_add_tracking_to_nuntius_messages.rb
569
+ - db/migrate/20260225123822_add_metadata_to_subscriber.rb
569
570
  - lib/generators/nuntius/install_generator.rb
570
571
  - lib/generators/nuntius/tailwind_config_generator.rb
571
572
  - lib/generators/nuntius/templates/config/initializers/nuntius.rb