activity_notification 1.0.0 → 1.0.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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +3 -3
  3. data/README.md +49 -9
  4. data/activity_notification.gemspec +1 -1
  5. data/app/controllers/activity_notification/notifications_controller.rb +75 -31
  6. data/app/mailers/activity_notification/mailer.rb +19 -4
  7. data/app/views/activity_notification/mailer/default/batch_default.html.erb +79 -0
  8. data/app/views/activity_notification/mailer/default/batch_default.text.erb +13 -0
  9. data/app/views/activity_notification/mailer/default/default.html.erb +75 -10
  10. data/app/views/activity_notification/mailer/default/default.text.erb +2 -2
  11. data/app/views/activity_notification/notifications/default/_default.html.erb +15 -14
  12. data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +165 -0
  13. data/app/views/activity_notification/notifications/default/_index.html.erb +8 -4
  14. data/app/views/activity_notification/notifications/default/destroy.js.erb +2 -2
  15. data/app/views/activity_notification/notifications/default/index.html.erb +9 -5
  16. data/app/views/activity_notification/notifications/default/open.js.erb +6 -2
  17. data/app/views/activity_notification/notifications/default/open_all.js.erb +6 -2
  18. data/lib/activity_notification/apis/notification_api.rb +42 -9
  19. data/lib/activity_notification/helpers/view_helpers.rb +48 -19
  20. data/lib/activity_notification/mailers/helpers.rb +74 -37
  21. data/lib/activity_notification/models/concerns/target.rb +290 -26
  22. data/lib/activity_notification/models/notification.rb +85 -29
  23. data/lib/activity_notification/roles/acts_as_target.rb +4 -2
  24. data/lib/activity_notification/version.rb +1 -1
  25. data/spec/concerns/apis/notification_api_spec.rb +46 -0
  26. data/spec/concerns/models/target_spec.rb +281 -22
  27. data/spec/controllers/notifications_controller_shared_examples.rb +77 -0
  28. data/spec/helpers/view_helpers_spec.rb +39 -3
  29. data/spec/mailers/mailer_spec.rb +54 -1
  30. data/spec/models/notification_spec.rb +11 -0
  31. data/spec/rails_app/app/models/user.rb +1 -1
  32. data/spec/rails_app/app/views/layouts/_header.html.erb +2 -0
  33. data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +6 -0
  34. data/spec/roles/acts_as_target_spec.rb +1 -1
  35. metadata +7 -4
@@ -0,0 +1,13 @@
1
+ Dear <%= @target.printable_target_name %>
2
+
3
+ You have recieved follwing notifications.
4
+
5
+ <% @notifications.each do |notification| %>
6
+ <%= notification.notifier.present? ? notification.notifier.printable_notifier_name : 'Someone' %> notified you of <%= notification.notifiable.printable_notifiable_name(notification.target) %><%= " in #{notification.group.printable_group_name}" if notification.group.present? %>.
7
+ <%= "Move to notified #{notification.notifiable.printable_type.downcase}:" %>
8
+ <%= move_notification_url_for(notification, open: true) %>
9
+ <%= notification.created_at.strftime("%b %d %H:%M") %>
10
+
11
+ <% end %>
12
+
13
+ Thank you!
@@ -1,12 +1,77 @@
1
- <p>Dear <%= @notification.target.printable_target_name %></p>
2
-
3
- <p>
4
- <strong><%= @notification.notifier.present? ? @notification.notifier.printable_notifier_name : 'Someone' %></strong>
5
- notified you of
6
- <%= @notification.notifiable.printable_notifiable_name(@notification.target) %><%= @notification.group.present? ? "in #{@notification.group.printable_group_name}." : "." %>
7
- </p>
1
+ <!doctype html>
2
+ <html lang="ja">
3
+ <head>
4
+ <meta content="text/html; charset=UTF-8" />
5
+ <style>
6
+ body {
7
+ font-family: 'Lucida Grande', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif;
8
+ color: #4f4f4f;
9
+ font-weight: normal;
10
+ font-style: normal;
11
+ }
12
+ p{
13
+ font-size: 14px;
14
+ }
15
+ .activity_wrapper {
16
+ padding: 15px 10px;
17
+ position: relative;
18
+ }
19
+ .activity_wrapper:after{
20
+ content: "";
21
+ clear: both;
22
+ display: block;
23
+ }
24
+ .activity_wrapper .user_image {
25
+ float: left;
26
+ width: 40px;
27
+ height: 40px;
28
+ background-position: center;
29
+ background-repeat: no-repeat;
30
+ background-size: cover;
31
+ background-color: #979797;
32
+ }
33
+ .activity_wrapper .user_desc_wrapper {
34
+ float: left;
35
+ width: calc(100% - 130px);
36
+ margin-top: 0;
37
+ margin-left: 10px;
38
+ }
39
+ .activity_wrapper .user_desc_wrapper .user_desc {
40
+ font-size: 12px;
41
+ line-height: 1.6;
42
+ margin-top: 0;
43
+ margin-bottom: 0;
44
+ }
45
+ .activity_wrapper .user_desc_wrapper .user_desc span{
46
+ color: #979797;
47
+ font-weight: bold;
48
+ }
49
+ .activity_wrapper .user_desc_wrapper .user_desc strong{
50
+ font-weight: bold;
51
+ }
52
+ </style>
53
+ <%= yield :head %>
54
+ </head>
55
+ <body>
56
+ <p>Dear <%= @target.printable_target_name %></p>
57
+ <div class="activity_wrapper">
58
+ <div class="user_image"></div>
59
+ <div class="user_desc_wrapper">
60
+ <p class="user_desc">
61
+ <strong><%= @notification.notifier.present? ? @notification.notifier.printable_notifier_name : 'Someone' %></strong>
62
+ notified you of
63
+ <%= @notification.notifiable.printable_notifiable_name(@notification.target) %><%= @notification.group.present? ? " in #{@notification.group.printable_group_name}." : "." %><br>
64
+ <span><%= @notification.created_at.strftime("%b %d %H:%M") %></span>
65
+ </p>
66
+ <p class="user_desc">
67
+ <span>
68
+ <%= link_to "Move to notified #{@notification.notifiable.printable_type.downcase}", move_notification_url_for(@notification, open: true) %>
69
+ </span>
70
+ </p>
71
+ </div>
72
+ </div>
73
+ <p>Thank you!</p>
74
+ </body>
75
+ </html>
8
76
 
9
- <p><%= link_to "Move to notified #{@notifiable.printable_type.downcase}", move_notification_url_for(@notification, open: true) %></p>
10
77
 
11
- <p>Thank you!</p>
12
- <p><span><%= @notification.created_at.strftime("%b %d %H:%M") %></span></p>
@@ -1,8 +1,8 @@
1
- Dear <%= @notification.target.printable_target_name %>
1
+ Dear <%= @target.printable_target_name %>
2
2
 
3
3
  <%= @notification.notifier.present? ? @notification.notifier.printable_notifier_name : 'Someone' %> notified you of <%= @notification.notifiable.printable_notifiable_name(@notification.target) %><%= " in #{@notification.group.printable_group_name}" if @notification.group.present? %>.
4
4
 
5
- <%= "Move to notified #{@notifiable.printable_type.downcase}:" %>
5
+ <%= "Move to notified #{@notification.notifiable.printable_type.downcase}:" %>
6
6
  <%= move_notification_url_for(@notification, open: true) %>
7
7
 
8
8
  Thank you!
@@ -1,5 +1,5 @@
1
1
  <% content_for :notification_content, flush: true do %>
2
- <li class="notification_list <%= notification.opened? ? "opened" : "unopened" %>">
2
+ <div class='notification_list <%= notification.opened? ? "opened" : "unopened" %>'>
3
3
  <div class="notification_list_cover"></div>
4
4
  <div class="list_image"></div>
5
5
  <div class="list_text_wrapper">
@@ -29,12 +29,12 @@
29
29
  <span><%= notification.created_at.strftime("%b %d %H:%M") %></span>
30
30
  </p>
31
31
  </div>
32
- </li>
32
+ </div>
33
33
  <% end %>
34
34
 
35
- <div class="<%= "notification_#{notification.id}" %>">
35
+ <div class='<%= "notification_#{notification.id}" %>'>
36
36
  <% if notification.unopened? %>
37
- <%= link_to open_notification_path_for(notification, filter: params[:filter], limit: params[:limit], reload: false), method: :post, remote: true, class: "unopned_wrapper" do %>
37
+ <%= link_to open_notification_path_for(notification, reload: false), method: :post, remote: true, class: "unopned_wrapper" do %>
38
38
  <div class="unopned_circle"></div>
39
39
  <div class="unopned_description_wrapper">
40
40
  <p class="unopned_description">Open</p>
@@ -49,17 +49,18 @@
49
49
  <%= yield :notification_content %>
50
50
  <% end %>
51
51
  <% end %>
52
- </div>
53
52
 
54
- <%#= link_to "Move", move_notification_path_for(notification) %>
55
- <%# if notification.unopened? %>
56
- <%#= link_to "Open and move (GET)", move_notification_path_for(notification, open: true) %
57
- <%#= link_to "Open and move (POST)", open_notification_path_for(notification, move: true), method: :post %>
58
- <%#= link_to "Open", open_notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :post %>
59
- <%#= link_to "Open (Ajax)", open_notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :post, remote: true %>
60
- <%# end %>
61
- <%#= link_to "Destroy", notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :delete %>
62
- <%#= link_to "Destroy (Ajax)", notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :delete, remote: true %>
53
+ <%#= link_to "Move", move_notification_path_for(notification) %>
54
+ <%# if notification.unopened? %>
55
+ <%#= link_to "Open and move (GET)", move_notification_path_for(notification, open: true) %>
56
+ <%#= link_to "Open and move (POST)", open_notification_path_for(notification, move: true), method: :post %>
57
+ <%#= link_to "Open", open_notification_path_for(notification, index_options: @index_options), method: :post %>
58
+ <%#= link_to "Open (Ajax)", open_notification_path_for(notification, reload: false), method: :post, remote: true %>
59
+ <%# end %>
60
+ <%#= link_to "Destroy", notification_path_for(notification, index_options: @index_options), method: :delete %>
61
+ <%#= link_to "Destroy (Ajax)", notification_path_for(notification, reload: false), method: :delete, remote: true %>
62
+
63
+ </div>
63
64
 
64
65
  <style>
65
66
  /* unopned_circle */
@@ -0,0 +1,165 @@
1
+ <% content_for :notification_content, flush: true do %>
2
+ <div class='notification_list <%= notification.opened? ? "opened" : "unopened" %>'>
3
+ <div class="notification_list_cover"></div>
4
+ <div class="list_image"></div>
5
+ <div class="list_text_wrapper">
6
+ <p class="list_text">
7
+ <strong><%= notification.notifier.present? ? notification.notifier.printable_notifier_name : 'Someone' %></strong>
8
+ notified you of
9
+ <% if notification.notifiable.present? %>
10
+ <%= notification.notifiable.printable_notifiable_name(notification.target) %>
11
+ <%= "in #{notification.group.printable_group_name}" if notification.group.present? %>
12
+ <% else %>
13
+ <%= " a #{notification.notifiable_type.humanize.singularize.downcase}" %>
14
+ <%= "in #{notification.group.printable_group_name}" if notification.group.present? %>
15
+ but the notifiable is not found. It may have been deleted.
16
+ <% end %>
17
+ <br>
18
+ <span><%= notification.created_at.strftime("%b %d %H:%M") %></span>
19
+ </p>
20
+ </div>
21
+ </div>
22
+ <% end %>
23
+
24
+ <div class='<%= "notification_#{notification.id}" %>'>
25
+ <% if notification.unopened? %>
26
+ <%= link_to open_notification_path_for(notification, reload: false, without_grouping: parameters[:with_group_members]), method: :post, remote: true, class: "unopned_wrapper" do %>
27
+ <div class="unopned_circle"></div>
28
+ <div class="unopned_description_wrapper">
29
+ <p class="unopned_description">Open</p>
30
+ </div>
31
+ <% end %>
32
+ <%= link_to open_notification_path_for(notification, move: true), method: :post do %>
33
+ <%= yield :notification_content %>
34
+ <% end %>
35
+ <div class="unopened_wrapper"></div>
36
+ <% else %>
37
+ <%= link_to move_notification_path_for(notification) do %>
38
+ <%= yield :notification_content %>
39
+ <% end %>
40
+ <% end %>
41
+
42
+ <%#= link_to "Move", move_notification_path_for(notification) %>
43
+ <%# if notification.unopened? %>
44
+ <%#= link_to "Open and move (GET)", move_notification_path_for(notification, open: true) %>
45
+ <%#= link_to "Open and move (POST)", open_notification_path_for(notification, move: true), method: :post %>
46
+ <%#= link_to "Open", open_notification_path_for(notification, index_options: @index_options), method: :post %>
47
+ <%#= link_to "Open (Ajax)", open_notification_path_for(notification, reload: false, with_group_members: parameters[:with_group_members]), method: :post, remote: true %>
48
+ <%# end %>
49
+ <%#= link_to "Destroy", notification_path_for(notification, index_options: @index_options), method: :delete %>
50
+ <%#= link_to "Destroy (Ajax)", notification_path_for(notification, reload: false, with_group_members: parameters[:with_group_members]), method: :delete, remote: true %>
51
+
52
+ </div>
53
+
54
+ <style>
55
+ /* unopned_circle */
56
+ .unopned_wrapper{
57
+ position: absolute;
58
+ margin-top: 20px;
59
+ margin-left: 56px;
60
+ }
61
+ .unopned_wrapper .unopned_circle {
62
+ display: block;
63
+ width: 10px;
64
+ height: 10px;
65
+ position: absolute;
66
+ border-radius: 50%;
67
+ background-color: #27a5eb;
68
+ z-index: 2;
69
+ }
70
+ .unopned_wrapper:hover > .unopned_description_wrapper{
71
+ display: block;
72
+ }
73
+ .unopned_wrapper .unopned_description_wrapper {
74
+ display: none;
75
+ position: absolute;
76
+ margin-top: 26px;
77
+ margin-left: -24px;
78
+ }
79
+ .unopned_wrapper .unopned_description_wrapper .unopned_description {
80
+ position: absolute;
81
+ color: #fff;
82
+ font-size: 12px;
83
+ text-align: center;
84
+
85
+ border-radius: 4px;
86
+ background: rgba(0, 0, 0, 0.8);
87
+ padding: 4px 12px;
88
+ z-index: 999;
89
+ }
90
+ .unopned_wrapper .unopned_description_wrapper .unopned_description:before {
91
+ border: solid transparent;
92
+ border-top-width: 0;
93
+ content: "";
94
+ display: block;
95
+ position: absolute;
96
+ width: 0;
97
+ left: 50%;
98
+ top: -5px;
99
+ margin-left: -5px;
100
+ height: 0;
101
+ border-width: 0 5px 5px 5px;
102
+ border-color: transparent transparent rgba(0, 0, 0, 0.8) transparent;
103
+ z-index: 0;
104
+ }
105
+
106
+ /* list */
107
+ .notification_list {
108
+ padding: 15px 10px;
109
+ position: relative;
110
+ border-bottom: 1px solid #e5e5e5;
111
+ }
112
+ .notification_list.unopened {
113
+ background-color: #eeeff4;
114
+ }
115
+ .notification_list:hover {
116
+ background-color: #f8f9fb;
117
+ }
118
+ .notification_list:last-child {
119
+ border-bottom: none;
120
+ }
121
+ .notification_list:after{
122
+ content: "";
123
+ clear: both;
124
+ display: block;
125
+ }
126
+ .notification_list .notification_list_cover{
127
+ position: absolute;
128
+ opacity: 0;
129
+ top: 0;
130
+ left: 0;
131
+ width: 100%;
132
+ height: 100%;
133
+ z-index: 1;
134
+
135
+ }
136
+ .notification_list .list_image {
137
+ float: left;
138
+ width: 40px;
139
+ height: 40px;
140
+ background-position: center;
141
+ background-repeat: no-repeat;
142
+ background-size: cover;
143
+ background-color: #979797;
144
+ }
145
+ .notification_list .list_text_wrapper {
146
+ float: left;
147
+ width: calc(100% - 60px);
148
+ margin-left: 20px;
149
+ }
150
+ .notification_list .list_text_wrapper .list_text {
151
+ color: #4f4f4f;
152
+ font-size: 14px;
153
+ line-height: 1.4;
154
+ margin-top: 0;
155
+ height: auto;
156
+ font-weight: normal;
157
+ }
158
+ .notification_list .list_text_wrapper .list_text strong{
159
+ font-weight: bold;
160
+ }
161
+ .notification_list .list_text_wrapper .list_text span {
162
+ color: #979797;
163
+ font-size: 13px;
164
+ }
165
+ </style>
@@ -1,6 +1,10 @@
1
1
  <div class="notification_wrapper">
2
2
  <a class="dropdown_notification">
3
- <p><span class="notification_count"><span class="<%= 'unopened' if @target.has_unopened_notifications? %>"><%= @target.unopened_notification_count %></span></span></p>
3
+ <p class="notification_count" id="notification_count">
4
+ <span class="<%= 'unopened' if @target.has_unopened_notifications?(parameters) %>">
5
+ <%= @target.unopened_notification_count(parameters) %>
6
+ </span>
7
+ </p>
4
8
  </a>
5
9
  <div class="notification_list_wrapper">
6
10
  <div class="notification_header_wrapper">
@@ -8,7 +12,7 @@
8
12
  Notifications
9
13
  </p>
10
14
  <p class="notification_header_menu">
11
- <%= link_to "Open all", open_all_notifications_path_for(@target), method: :post, remote: true %>
15
+ <%= link_to "Open all", open_all_notifications_path_for(@target, parameters), method: :post, remote: true %>
12
16
  </p>
13
17
  </div>
14
18
  <div class="notifications">
@@ -34,14 +38,14 @@
34
38
  .notification_wrapper .dropdown_notification{
35
39
  cursor: pointer;
36
40
  }
37
- .notification_wrapper .dropdown_notification p span span{
41
+ .notification_wrapper .dropdown_notification .notification_count span{
38
42
  color: #fff;
39
43
  background-color: #e5e5e5;
40
44
  border-radius: 4px;
41
45
  font-size: 12px;
42
46
  padding: 4px 8px;
43
47
  }
44
- .notification_wrapper .dropdown_notification p span span.unopened{
48
+ .notification_wrapper .dropdown_notification .notification_count span.unopened{
45
49
  background-color: #f87880;
46
50
  }
47
51
  .notification_wrapper.open .notification_list_wrapper {
@@ -1,2 +1,2 @@
1
- $(".notification_count").html("<span class=\"<%= 'unopened' if @target.has_unopened_notifications? %>\"><%= @target.unopened_notification_count %></span>");
2
- $("<%= ".notification_#{@notification.id}" %>").html("<%= escape_javascript( render_notification(@notification, fallback: :default) ) %>");
1
+ $(".notification_count").html("<span class=\"<%= 'unopened' if @target.has_unopened_notifications?(@index_options) %>\"><%= @target.unopened_notification_count(@index_options) %></span>");
2
+ $('<%= ".notification_#{@notification.id}" %>').remove();
@@ -1,18 +1,22 @@
1
1
  <div class="notification_wrapper">
2
2
  <div class="notification_header">
3
- <h1>Notifications to <%= @target.printable_target_name %> <%= link_to open_all_notifications_path_for(@target), method: :post, remote: true do %><span class="notification_count"><span class="<%= 'unopened' if @target.has_unopened_notifications? %>"><%= @target.unopened_notification_count %></span></span><% end %></h1>
3
+ <h1>Notifications to <%= @target.printable_target_name %> <%= link_to open_all_notifications_path_for(@target, @index_options), method: :post, remote: true do %><span class="notification_count"><span class="<%= 'unopened' if @target.has_unopened_notifications?(@index_options) %>"><%= @target.unopened_notification_count(@index_options) %></span></span><% end %></h1>
4
4
  </div>
5
- <%#= link_to "Open all", open_all_notifications_path_for(@target), method: :post %>
6
- <%#= link_to "Open all (ajax)", open_all_notifications_path_for(@target), method: :post, remote: true %>
7
5
  <ul>
8
6
  <div class="notifications">
9
- <%= render_notification @notifications, fallback: :default %>
10
- <%#= render_notification @notifications, fallback: :text %>
7
+ <% if @index_options[:with_group_members] %>
8
+ <%= render_notification @notifications, fallback: :default_without_grouping, with_group_members: true %>
9
+ <% else %>
10
+ <%= render_notification @notifications, fallback: :default %>
11
+ <%#= render_notification @notifications, fallback: :text %>
12
+ <% end %>
11
13
  </div>
12
14
  </ul>
13
15
  </div>
14
16
 
15
17
  <%#= render_notifications_of @target, fallback: :default, index_content: :with_attributes %>
18
+ <%#= render_notifications_of @target, fallback: :default, index_content: :unopened_with_attributes, reverse: true %>
19
+ <%#= render_notifications_of @target, fallback: :default_without_grouping, index_content: :with_attributes, with_group_members: true %>
16
20
 
17
21
  <style>
18
22
  .notification_wrapper .notification_header h1 span span{
@@ -1,2 +1,6 @@
1
- $(".notification_count").html("<span class=\"<%= 'unopened' if @target.has_unopened_notifications? %>\"><%= @target.unopened_notification_count %></span>");
2
- $("<%= ".notification_#{@notification.id}" %>").html("<%= escape_javascript( render_notification(@notification, fallback: :default) ) %>");
1
+ $(".notification_count").html("<span class=\"<%= 'unopened' if @target.has_unopened_notifications?(@index_options) %>\"><%= @target.unopened_notification_count(@index_options) %></span>");
2
+ <% if @index_options[:with_group_members] %>
3
+ $('<%= ".notification_#{@notification.id}" %>').html("<%= escape_javascript( render_notification(@notification, fallback: :default_without_grouping, with_group_members: true) ) %>");
4
+ <% else %>
5
+ $('<%= ".notification_#{@notification.id}" %>').html("<%= escape_javascript( render_notification(@notification, fallback: :default) ) %>");
6
+ <% end %>
@@ -1,2 +1,6 @@
1
- $(".notification_count").html("<span class=\"<%= 'unopened' if @target.has_unopened_notifications? %>\"><%= @target.unopened_notification_count %></span>");
2
- $(".notifications").html("<%= escape_javascript( render_notification(@notifications, fallback: :default) ) %>");
1
+ $(".notification_count").html("<span class=\"<%= 'unopened' if @target.has_unopened_notifications?(@index_options) %>\"><%= @target.unopened_notification_count(@index_options) %></span>");
2
+ <% if @index_options[:with_group_members] %>
3
+ $(".notifications").html("<%= escape_javascript( render_notification(@notifications, fallback: :default_without_grouping, with_group_members: true) ) %>");
4
+ <% else %>
5
+ $(".notifications").html("<%= escape_javascript( render_notification(@notifications, fallback: :default) ) %>");
6
+ <% end %>
@@ -54,7 +54,7 @@ module ActivityNotification
54
54
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
55
55
  # @return [Array<Notificaion>] Array of generated notifications
56
56
  def notify_all(targets, notifiable, options = {})
57
- Array(targets).map { |target| notify_to(target, notifiable, options) }
57
+ targets.map { |target| target.notify_to(notifiable, options) }
58
58
  end
59
59
 
60
60
  # Generates notifications to one target.
@@ -109,6 +109,27 @@ module ActivityNotification
109
109
  notifications.present? and where(group_owner_id: notifications.map(&:id)).exists?
110
110
  end
111
111
 
112
+ # Sends batch notification email to the target.
113
+ #
114
+ # @param [Object] target Target of batch notification email
115
+ # @param [Array<Notification>] notifications Target notifications to send batch notification email
116
+ # @param [Hash] options Options for notification email
117
+ # @option options [Boolean] :send_later (false) If it sends notification email asynchronously
118
+ # @option options [String, Symbol] :fallback (:batch_default) Fallback template to use when MissingTemplate is raised
119
+ # @option options [String] :batch_key (nil) Key of the batch notification email, a key of the first notification will be used if not specified
120
+ # @return [Mail::Message|ActionMailer::DeliveryJob|NilClass] Email message or its delivery job, return NilClass for wrong target
121
+ def send_batch_notification_email(target, notifications, options = {})
122
+ return if notifications.blank?
123
+ if target.batch_notification_email_allowed?(notifications.first.notifiable_type, notifications.first.key)
124
+ send_later = options.has_key?(:send_later) ? options[:send_later] : true
125
+ if send_later
126
+ Mailer.send_batch_notification_email(target, notifications, options).deliver_later
127
+ else
128
+ Mailer.send_batch_notification_email(target, notifications, options).deliver_now
129
+ end
130
+ end
131
+ end
132
+
112
133
  # Returns available options for kinds of notify methods.
113
134
  #
114
135
  # @return [Array<Notificaion>] Available options for kinds of notify methods
@@ -143,15 +164,18 @@ module ActivityNotification
143
164
  # Sends notification email to the target.
144
165
  #
145
166
  # @param [Hash] options Options for notification email
146
- # @option send_later [Boolean] :send_later If it sends notification email asynchronously
147
- # @option options [String, Symbol] :fallback (:default) Fallback template to use when MissingTemplate is raised
148
- # @return [Mail::Message, ActionMailer::DeliveryJob] Email message or its delivery job
167
+ # @option options [Boolean] :send_later If it sends notification email asynchronously
168
+ # @option options [String, Symbol] :fallback (:default) Fallback template to use when MissingTemplate is raised
169
+ # @return [Mail::Message|ActionMailer::DeliveryJob] Email message or its delivery job
149
170
  def send_notification_email(options = {})
150
- send_later = options.has_key?(:send_later) ? options[:send_later] : true
151
- if send_later
152
- Mailer.send_notification_email(self, options).deliver_later
153
- else
154
- Mailer.send_notification_email(self, options).deliver_now
171
+ if target.notification_email_allowed?(notifiable, key) and
172
+ notifiable.notification_email_allowed?(target, key)
173
+ send_later = options.has_key?(:send_later) ? options[:send_later] : true
174
+ if send_later
175
+ Mailer.send_notification_email(self, options).deliver_later
176
+ else
177
+ Mailer.send_notification_email(self, options).deliver_now
178
+ end
155
179
  end
156
180
  end
157
181
 
@@ -256,6 +280,15 @@ module ActivityNotification
256
280
  notification.notifier.present? ? group_member_notifier_count(limit) + 1 : 0
257
281
  end
258
282
 
283
+ # Returns the latest group member notification instance of this notification.
284
+ # If this group owner has no group members, group owner instance self will be returned.
285
+ #
286
+ # @return [Notificaion] Notification instance of the latest group member notification
287
+ def latest_group_member
288
+ notification = group_member? ? group_owner : self
289
+ notification.group_member_exists? ? notification.group_members.latest : self
290
+ end
291
+
259
292
  # Returns notifiable_path to move after opening notification with notifiable.notifiable_path.
260
293
  #
261
294
  # @return [String] Notifiable path URL to move after opening notification