effective_messaging 0.4.2 → 0.5.1

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: ee0fc8653681a36c4de9e9756c348c2438e376bff57409b584a5d7e514a1e596
4
- data.tar.gz: bf10b4a5f6641193eac7f0da6300d6851b3d51417fe72b36095e6702823936f9
3
+ metadata.gz: 1061a51a0950e3c322de72f007ce0380e2b9fa6d0089d85bbd905b1cad9a8acd
4
+ data.tar.gz: 5f1dcb71f399a6d94fb49ba3284bbec7f007c6f8f7494e05aa1bf8f4cde618cf
5
5
  SHA512:
6
- metadata.gz: 6fdbe70ef0e37d29dc8126ac9416361e4cfd87929f20975dcff60d4281d2804b96c3def8d0a2303be2210e98985310a1858beddaeeb332366ec33bb0bfe69fb6
7
- data.tar.gz: 22dafc2abd52b17461126ceafc84164c6d9446f8fe2ff8f997da2b29ff8db5cdc959a1c59123f75ad45499df19057cc04cfd98a03074f12ce6a4958a4406d77e
6
+ metadata.gz: e4facce29949bb6bfd8a56fcea0029c09da098da22aedcef8c018209c3091e87fcc8a53123cf56ea26b99735cb0d83119a135930428d672129125f3459e0debe
7
+ data.tar.gz: d97ffe863b7cb1d14829f49ddf012723d79a99b3c1b2038dbd48e99bf8caf1193388ff8fcd5813dad9b25168d9118d3c3abae5d790126d10ba916e6cb66fa278
@@ -5,8 +5,6 @@ module Admin
5
5
 
6
6
  include Effective::CrudController
7
7
 
8
- submit :send_now, 'Send Now'
9
-
10
8
  private
11
9
 
12
10
  def permitted_params
@@ -8,9 +8,10 @@ module Admin
8
8
 
9
9
  col :notification
10
10
  col :report, visible: !attributes[:inline]
11
- col :resource
12
- col :user
13
- col :email, visible: false
11
+ col :resource, search: :string
12
+ col :user, search: :string
13
+ col :email
14
+ col :skipped
14
15
 
15
16
  actions_col
16
17
  end
@@ -34,6 +34,8 @@ module Admin
34
34
 
35
35
  col :report, search: Effective::Report.notifiable.sorted, action: :show
36
36
 
37
+ col :notifiable_tomorrow_rows_count, label: 'Tomorrow'
38
+
37
39
  col(:rows_count) do |notification|
38
40
  notification.report.collection().count
39
41
  end
@@ -1,8 +1,8 @@
1
1
  module Effective
2
2
  class NotificationJob < ApplicationJob
3
3
 
4
- def perform(id)
5
- Notification.find(id).notify!
4
+ def perform(id, force:)
5
+ Notification.find(id).notify!(force: force)
6
6
  end
7
7
 
8
8
  end
@@ -11,6 +11,7 @@ module Effective
11
11
 
12
12
  # Attach report
13
13
  attach_report!(notification)
14
+ rendered.delete(:content_type) if notification.attach_report?
14
15
 
15
16
  # Works with effective_logging to associate this email with the notification
16
17
  headers = headers_for(notification, opts)
@@ -102,6 +102,10 @@ module Effective
102
102
  validates :immediate_times, presence: true, numericality: { greater_than_or_equal_to: 1 }
103
103
  end
104
104
 
105
+ validate(if: -> { immediate? && immediate_days.present? && immediate_times.present? }) do
106
+ self.errors.add(:immediate_times, "must be 1 when when using every 0 days") if immediate_days == 0 && immediate_times != 1
107
+ end
108
+
105
109
  # Scheduled
106
110
  validates :scheduled_method, presence: true, inclusion: { in: SCHEDULED_METHODS.map(&:last) }, if: -> { scheduled? }
107
111
 
@@ -154,6 +158,8 @@ module Effective
154
158
  end
155
159
  end
156
160
 
161
+ # This operates on each row of the resource.
162
+ # We track the number of notifications total to see if we should notify again or not
157
163
  def immediate?
158
164
  schedule_type == 'immediate'
159
165
  end
@@ -210,24 +216,63 @@ module Effective
210
216
  @rows_count ||= report.collection().count if report
211
217
  end
212
218
 
213
- # Button on the Admin interface. Enqueues the job to send right away.
219
+ def notifiable_rows_count
220
+ report.collection().select { |resource| notifiable?(resource) }.count if report
221
+ end
222
+
223
+ def notifiable_tomorrow_rows_count
224
+ report.collection().select { |resource| notifiable_tomorrow?(resource) }.count if report
225
+ end
226
+
227
+ def enable!
228
+ update!(enabled: true)
229
+ end
230
+
231
+ def disable!
232
+ update!(enabled: false)
233
+ end
234
+
235
+ # Enqueues this notification to send right away.
236
+ # Only applies to scheduled_email? notifications
214
237
  def send_now!
215
238
  raise('expected to be persisted') unless persisted?
216
- NotificationJob.perform_later(id)
239
+ NotificationJob.perform_later(id, force: true)
217
240
  true
218
241
  end
219
242
 
220
- # The main function
221
- def notify!
222
- scheduled_email? ? notify_by_schedule! : notify_by_resources!
243
+ # Only applies to immedate? notifications
244
+ # Skips over one notification on the immediate notifications
245
+ def skip_once!
246
+ notified = 0
247
+
248
+ report.collection().find_each do |resource|
249
+ print('.')
250
+
251
+ # For logging
252
+ assign_attributes(current_resource: resource)
253
+
254
+ # Send the resource email
255
+ build_notification_log(resource: resource, skipped: true).save!
256
+
257
+ notified += 1
258
+
259
+ GC.start if (notified % 250) == 0
260
+ end
261
+
262
+ touch
263
+ end
264
+
265
+ # The main function to send this thing
266
+ def notify!(force: false)
267
+ scheduled_email? ? notify_by_schedule!(force: force) : notify_by_resources!(force: force)
223
268
  end
224
269
 
225
270
  # Operates on every resource in the data source. Sends one email for each row
226
- def notify_by_resources!
271
+ def notify_by_resources!(force: false)
227
272
  notified = 0
228
273
 
229
274
  report.collection().find_each do |resource|
230
- next unless notifiable?(resource)
275
+ next unless notifiable?(resource) || force
231
276
  print('.')
232
277
 
233
278
  # For logging
@@ -245,10 +290,10 @@ module Effective
245
290
  notified > 0 ? update!(last_notified_at: Time.zone.now, last_notified_count: notified) : touch
246
291
  end
247
292
 
248
- def notify_by_schedule!
293
+ def notify_by_schedule!(force: false)
249
294
  notified = 0
250
295
 
251
- if notifiable_scheduled?
296
+ if notifiable_scheduled? || force
252
297
  build_notification_log(resource: nil).save!
253
298
  Effective::NotificationsMailer.notify(self).deliver_now
254
299
  notified += 1
@@ -257,22 +302,27 @@ module Effective
257
302
  notified > 0 ? update!(last_notified_at: Time.zone.now, last_notified_count: notified) : touch
258
303
  end
259
304
 
260
- def notifiable?(resource)
305
+ def notifiable?(resource, date: nil)
261
306
  raise('expected an acts_as_reportable resource') unless resource.class.try(:acts_as_reportable?)
262
307
 
263
308
  if schedule_type == 'immediate'
264
- notifiable_immediate?(resource: resource)
309
+ notifiable_immediate?(resource: resource, date: date)
265
310
  elsif schedule_type == 'scheduled'
266
- notifiable_scheduled?(date: nil)
311
+ notifiable_scheduled?(date: date)
267
312
  else
268
313
  raise("unsupported schedule_type")
269
314
  end
270
315
  end
271
316
 
317
+ def notifiable_tomorrow?(resource)
318
+ date = Time.zone.now.beginning_of_day.advance(days: 1)
319
+ notifiable?(resource, date: date)
320
+ end
321
+
272
322
  # Consider the notification logs which track how many and how long ago this notification was sent
273
323
  # It's notifiable? when first time or if it's been immediate_days since last notification
274
- def notifiable_immediate?(resource:)
275
- raise('expected an immexiate? notification') unless immediate?
324
+ def notifiable_immediate?(resource:, date: nil)
325
+ raise('expected an immediate? notification') unless immediate?
276
326
 
277
327
  email = resource_email(resource) || resource_user(resource).try(:email)
278
328
  raise("expected an email for #{report} #{report&.id} and #{resource} #{resource&.id}") unless email.present?
@@ -283,8 +333,8 @@ module Effective
283
333
  true # This is the first time. We should send.
284
334
  elsif logs.count < immediate_times
285
335
  # We still have to send it but consider dates.
286
- last_sent_days_ago = logs.map(&:days_ago).min || 0
287
- last_sent_days_ago >= immediate_days
336
+ last_sent_days_ago = logs.map { |log| log.days_ago(date: date) }.min || 0
337
+ (last_sent_days_ago >= immediate_days)
288
338
  else
289
339
  false # We've already sent enough times
290
340
  end
@@ -348,13 +398,13 @@ module Effective
348
398
  report_assigns.merge(reportable_view_assigns)
349
399
  end
350
400
 
351
- def build_notification_log(resource: nil)
401
+ def build_notification_log(resource: nil, skipped: false)
352
402
  user = resource_user(resource)
353
403
 
354
404
  email = resource_email(resource) || user.try(:email)
355
405
  email ||= audience_emails_to_s if scheduled_email?
356
406
 
357
- notification_logs.build(email: email, report: report, resource: resource, user: user)
407
+ notification_logs.build(email: email, report: report, resource: resource, user: user, skipped: skipped)
358
408
  end
359
409
 
360
410
  private
@@ -12,6 +12,7 @@ module Effective
12
12
 
13
13
  effective_resource do
14
14
  email :string
15
+ skipped :boolean
15
16
 
16
17
  timestamps
17
18
  end
@@ -25,8 +26,8 @@ module Effective
25
26
  model_name.human
26
27
  end
27
28
 
28
- def days_ago
29
- now = Time.zone.now.to_date
29
+ def days_ago(date: nil)
30
+ now = (date || Time.zone.now).to_date
30
31
  (now - (created_at&.to_date || now)).to_i
31
32
  end
32
33
 
@@ -76,9 +76,5 @@
76
76
 
77
77
  = f.submit do
78
78
  = f.save 'Save'
79
-
80
- - if EffectiveResources.authorized?(self, :send_now, f.object)
81
- = f.save 'Send Now', class: 'btn btn-warning', 'data-confirm': "Really send now?"
82
-
83
79
  = f.save 'Add New', class: 'btn btn-secondary'
84
80
  = f.save 'Continue', class: 'btn btn-secondary'
@@ -1,43 +1,11 @@
1
- %p
2
- This notification will be sent to all rows from the
3
- = link_to(notification.report, effective_reports.admin_report_path(notification.report), target: '_blank')
4
- report at the time of sending.
1
+ = tabs do
2
+ = tab 'Notification' do
3
+ = render 'admin/notifications/summary', notification: notification
5
4
 
6
- %p Currently there are #{pluralize(notification.rows_count, 'rows')} that would be notified.
5
+ - if notification.persisted? && notification.respond_to?(:logs_datatable)
6
+ = tab 'Email Logs' do
7
+ - datatable = Admin::EffectiveNotificationLogsDatatable.new(notification: notification)
8
+ = render_inline_datatable(datatable)
7
9
 
8
- = card(notification) do
9
- = effective_table_with(notification)
10
-
11
- - if notification.rows_count > 0
12
- %p Using a random row from the data source, a preview of the notification follows:
13
-
14
- = card('Preview of Notification') do
15
- - resource = notification.report.collection.order('RANDOM()').first
16
- - rendered = notification.assign_renderer(self).render_email(resource)
17
-
18
- %table.table
19
- %tbody
20
- %tr
21
- %th To
22
- %td= rendered.fetch(:to)
23
- %tr
24
- %th From
25
- %td= rendered.fetch(:from)
26
-
27
- - if (cc = rendered[:cc]).present?
28
- %tr
29
- %th CC
30
- %td= cc
31
-
32
- - if (bcc = rendered[:bcc]).present?
33
- %tr
34
- %th BCC
35
- %td= bcc
36
-
37
- %tr
38
- %th Subject
39
- %td= rendered.fetch(:subject)
40
-
41
- %tr
42
- %td{colspan: 2}
43
- = simple_format(rendered.fetch(:body).to_s)
10
+ = tab 'Logs' do
11
+ = render_inline_datatable(notification.logs_datatable)
@@ -0,0 +1,49 @@
1
+ %p
2
+ This notification will be sent to all rows from the
3
+ = link_to(notification.report, effective_reports.admin_report_path(notification.report), target: '_blank')
4
+ report at the time of sending.
5
+
6
+ %p Tomorrow morning, #{pluralize(notification.notifiable_tomorrow_rows_count, 'rows')} notifications will be sent.
7
+
8
+ .mb-2
9
+ = collapse('Show notification details') do
10
+ = effective_table_with(notification)
11
+
12
+ .mb-2
13
+ = collapse("Show report data") do
14
+ %h4= notification.report.to_s
15
+ = render 'admin/reports/report', report: notification.report
16
+
17
+ - if notification.rows_count > 0
18
+ %p Using a random row from the data source, a preview of the notification follows:
19
+
20
+ = card('Preview') do
21
+ - resource = notification.report.collection.order('RANDOM()').first
22
+ - rendered = notification.assign_renderer(self).render_email(resource)
23
+
24
+ %table.table
25
+ %tbody
26
+ %tr
27
+ %th To
28
+ %td= rendered.fetch(:to)
29
+ %tr
30
+ %th From
31
+ %td= rendered.fetch(:from)
32
+
33
+ - if (cc = rendered[:cc]).present?
34
+ %tr
35
+ %th CC
36
+ %td= cc
37
+
38
+ - if (bcc = rendered[:bcc]).present?
39
+ %tr
40
+ %th BCC
41
+ %td= bcc
42
+
43
+ %tr
44
+ %th Subject
45
+ %td= rendered.fetch(:subject)
46
+
47
+ %tr
48
+ %td{colspan: 2}
49
+ = simple_format(rendered.fetch(:body).to_s)
data/config/routes.rb CHANGED
@@ -13,7 +13,15 @@ EffectiveMessaging::Engine.routes.draw do
13
13
  namespace :admin do
14
14
  resources :chats
15
15
  resources :chat_messages, only: [:index, :show, :destroy]
16
- resources :notifications
16
+
17
+ resources :notifications do
18
+ post :enable, on: :member
19
+ post :disable, on: :member
20
+
21
+ post :send_now, on: :member
22
+ post :skip_once, on: :member
23
+ end
24
+
17
25
  resources :notification_logs, only: [:index, :destroy]
18
26
  end
19
27
 
@@ -87,6 +87,7 @@ class CreateEffectiveMessaging < ActiveRecord::Migration[6.0]
87
87
  t.string :resource_type
88
88
 
89
89
  t.string :email
90
+ t.boolean :skipped, default: false
90
91
 
91
92
  t.timestamps
92
93
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveMessaging
2
- VERSION = '0.4.2'.freeze
2
+ VERSION = '0.5.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_messaging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-26 00:00:00.000000000 Z
11
+ date: 2023-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -237,6 +237,7 @@ files:
237
237
  - app/views/admin/notifications/_form.html.haml
238
238
  - app/views/admin/notifications/_form_notification.html.haml
239
239
  - app/views/admin/notifications/_notification.html.haml
240
+ - app/views/admin/notifications/_summary.html.haml
240
241
  - app/views/effective/chats/_chat.html.haml
241
242
  - app/views/effective/chats/_chat_message.html.haml
242
243
  - app/views/effective/chats/_form.html.haml