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.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +49 -9
- data/activity_notification.gemspec +1 -1
- data/app/controllers/activity_notification/notifications_controller.rb +75 -31
- data/app/mailers/activity_notification/mailer.rb +19 -4
- data/app/views/activity_notification/mailer/default/batch_default.html.erb +79 -0
- data/app/views/activity_notification/mailer/default/batch_default.text.erb +13 -0
- data/app/views/activity_notification/mailer/default/default.html.erb +75 -10
- data/app/views/activity_notification/mailer/default/default.text.erb +2 -2
- data/app/views/activity_notification/notifications/default/_default.html.erb +15 -14
- data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +165 -0
- data/app/views/activity_notification/notifications/default/_index.html.erb +8 -4
- data/app/views/activity_notification/notifications/default/destroy.js.erb +2 -2
- data/app/views/activity_notification/notifications/default/index.html.erb +9 -5
- data/app/views/activity_notification/notifications/default/open.js.erb +6 -2
- data/app/views/activity_notification/notifications/default/open_all.js.erb +6 -2
- data/lib/activity_notification/apis/notification_api.rb +42 -9
- data/lib/activity_notification/helpers/view_helpers.rb +48 -19
- data/lib/activity_notification/mailers/helpers.rb +74 -37
- data/lib/activity_notification/models/concerns/target.rb +290 -26
- data/lib/activity_notification/models/notification.rb +85 -29
- data/lib/activity_notification/roles/acts_as_target.rb +4 -2
- data/lib/activity_notification/version.rb +1 -1
- data/spec/concerns/apis/notification_api_spec.rb +46 -0
- data/spec/concerns/models/target_spec.rb +281 -22
- data/spec/controllers/notifications_controller_shared_examples.rb +77 -0
- data/spec/helpers/view_helpers_spec.rb +39 -3
- data/spec/mailers/mailer_spec.rb +54 -1
- data/spec/models/notification_spec.rb +11 -0
- data/spec/rails_app/app/models/user.rb +1 -1
- data/spec/rails_app/app/views/layouts/_header.html.erb +2 -0
- data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +6 -0
- data/spec/roles/acts_as_target_spec.rb +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eafbddc7c4427310930baf3d6f23464f4d0c2baa
|
4
|
+
data.tar.gz: 38dce4c34e4e22e06be7132d588906500127c017
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4da1eff72e8906c9398bb43f9273ca1c788ce91debeccfc4ec9d371fa6032b11c12fb60594c5191e37717f88df4b1d020b82506357c469c9f1894ba0930ac992
|
7
|
+
data.tar.gz: 08ce06b4beaf320607e276d7dabd9486c58b7f979aa29ee522da90a7c9972eda2bc8148cadad1b90c66dd46bbead0fa819a0bff43a5fd17b9c8b9a1db5e4c113
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
activity_notification (1.0.
|
4
|
+
activity_notification (1.0.1)
|
5
5
|
activerecord (>= 4.2.0)
|
6
6
|
i18n (>= 0.5.0)
|
7
7
|
jquery-rails (>= 3.1.1)
|
@@ -164,7 +164,7 @@ GEM
|
|
164
164
|
actionpack (>= 4.0)
|
165
165
|
activesupport (>= 4.0)
|
166
166
|
sprockets (>= 3.0.0)
|
167
|
-
sqlite3 (1.3.
|
167
|
+
sqlite3 (1.3.12)
|
168
168
|
term-ansicolor (1.4.0)
|
169
169
|
tins (~> 1.0)
|
170
170
|
thor (0.19.1)
|
@@ -197,7 +197,7 @@ DEPENDENCIES
|
|
197
197
|
rails-controller-testing
|
198
198
|
rspec-rails (~> 3.5.1)
|
199
199
|
simplecov (~> 0.12.0)
|
200
|
-
sqlite3 (~> 1.3.
|
200
|
+
sqlite3 (~> 1.3.12)
|
201
201
|
timecop
|
202
202
|
yard (~> 0.9.5)
|
203
203
|
yard-activesupport-concern (~> 0.0.1)
|
data/README.md
CHANGED
@@ -21,6 +21,7 @@
|
|
21
21
|
* Notification views (presentation of notifications)
|
22
22
|
* Grouping notifications (grouping like `"Kevin and 7 other users posted comments to this article"`)
|
23
23
|
* Email notification
|
24
|
+
* Batch email notification
|
24
25
|
* Integration with [Devise](https://github.com/plataformatec/devise) authentication
|
25
26
|
|
26
27
|
### Notification index
|
@@ -55,8 +56,11 @@
|
|
55
56
|
1. [Setup mailer](#setup-mailer)
|
56
57
|
2. [Email templates](#email-templates)
|
57
58
|
3. [i18n for email](#i18n-for-email)
|
58
|
-
2. [
|
59
|
-
|
59
|
+
2. [Batch email notification](#batch-email-notification)
|
60
|
+
1. [Batch email templates](#batch-email-templates)
|
61
|
+
2. [i18n for batch email](#i18n-for-batch-email)
|
62
|
+
3. [Grouping notifications](#grouping-notifications)
|
63
|
+
4. [Integration with Devise](#integration-with-devise)
|
60
64
|
4. [Testing](#testing)
|
61
65
|
5. [Documentation](#documentation)
|
62
66
|
6. **[Common examples](#common-examples)**
|
@@ -308,7 +312,7 @@ If you want to set notification index in the common layout, such as common heade
|
|
308
312
|
<%= render_notifications_of current_user, index_content: :with_attributes %>
|
309
313
|
```
|
310
314
|
|
311
|
-
Then, content named
|
315
|
+
Then, content named `:notification_index` will be prepared and you can use it in your partial template.
|
312
316
|
|
313
317
|
```activity_notifications/notifications/users/_index.html.erb
|
314
318
|
...
|
@@ -330,29 +334,29 @@ For example, if you have an notification with `:key` set to `"notification.comme
|
|
330
334
|
|
331
335
|
*Hint*: the `"notification."` prefix in `:key` is completely optional, you can skip it in your projects or use this prefix only to make namespace.
|
332
336
|
|
333
|
-
If you would like to fallback to a partial, you can utilize the
|
337
|
+
If you would like to fallback to a partial, you can utilize the `:fallback` parameter to specify the path of a partial to use when one is missing:
|
334
338
|
|
335
339
|
```erb
|
336
|
-
<%= render_notification(@notification, target: :users, fallback:
|
340
|
+
<%= render_notification(@notification, target: :users, fallback: :default) %>
|
337
341
|
```
|
338
342
|
|
339
|
-
When used in this manner, if a partial with the specified `:key` cannot be located it will use the partial defined in the
|
343
|
+
When used in this manner, if a partial with the specified `:key` cannot be located it will use the partial defined in the `:fallback` instead. In the example above this would resolve to `activity_notification/notifications/users/_default.html.(|erb|haml|slim|something_else)`.
|
340
344
|
|
341
345
|
If you do not specify `:target` option like this,
|
342
346
|
|
343
347
|
```erb
|
344
|
-
<%= render_notification(@notification, fallback:
|
348
|
+
<%= render_notification(@notification, fallback: :default) %>
|
345
349
|
```
|
346
350
|
|
347
351
|
the gem will look for a partial in `default` as the target type which means `activity_notification/notifications/default/_default.html.(|erb|haml|slim|something_else)`.
|
348
352
|
|
349
|
-
If a view file does not exist then ActionView::MisingTemplate will be raised. If you wish to fallback to the old behaviour and use an i18n based translation in this situation you can specify a `:fallback` parameter of
|
353
|
+
If a view file does not exist then ActionView::MisingTemplate will be raised. If you wish to fallback to the old behaviour and use an i18n based translation in this situation you can specify a `:fallback` parameter of `:text` to fallback to this mechanism like such:
|
350
354
|
|
351
355
|
```erb
|
352
356
|
<%= render_notification(@notification, fallback: :text) %>
|
353
357
|
```
|
354
358
|
|
355
|
-
|
359
|
+
Finally, default views of `activity_notification` depends on jQuery and you have to add requirements to `application.js` in your apps:
|
356
360
|
|
357
361
|
```app/assets/javascripts/application.js
|
358
362
|
//= require jquery
|
@@ -456,6 +460,42 @@ notification:
|
|
456
460
|
mail_subject: 'New comment to your article'
|
457
461
|
```
|
458
462
|
|
463
|
+
### Batch email notification
|
464
|
+
|
465
|
+
`activity_notification` provides batch email notification to the notification targets. You can send notification daily or hourly with scheduler like `whenever`.
|
466
|
+
|
467
|
+
You can automatically send batch notification email for unopened notifications only to the all specified targets with `batch_key`.
|
468
|
+
|
469
|
+
```ruby
|
470
|
+
# Send batch notification email to the users with unopened notifications
|
471
|
+
User.send_batch_unopened_notification_email(batch_key: 'batch.comment.post')
|
472
|
+
```
|
473
|
+
|
474
|
+
You can also add conditions to filter notifications, like this:
|
475
|
+
|
476
|
+
```ruby
|
477
|
+
# Send batch notification email to the users with unopened notifications of specified key in 1 hour
|
478
|
+
User.send_batch_unopened_notification_email(batch_key: 'batch.comment.post', filtered_by_key: 'comment.post', custom_filter: ["created_at >= ?", time.hour.ago])
|
479
|
+
```
|
480
|
+
|
481
|
+
#### Batch email templates
|
482
|
+
|
483
|
+
`activity_notification` will look for batch email template in the same way as email notification using `batch_key`.
|
484
|
+
`batch_key` is specified by `:batch_key` option. If the option is not specified, The key of the first notification will be used as `batch_key`.
|
485
|
+
|
486
|
+
#### i18n for batch email
|
487
|
+
|
488
|
+
The subject of batch notification email also can be put in your locale `.yml` files as `mail_subject` field for `batch_key`.
|
489
|
+
|
490
|
+
```yaml
|
491
|
+
notification:
|
492
|
+
user:
|
493
|
+
batch:
|
494
|
+
comment:
|
495
|
+
post:
|
496
|
+
mail_subject: 'New comments to your article'
|
497
|
+
```
|
498
|
+
|
459
499
|
### Grouping notifications
|
460
500
|
|
461
501
|
`activity_notification` provides the function for automatically grouping notifications. When you created a notification like this, all *unopened* notifications to the same target will be grouped by `article` set as `:group` options:
|
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_dependency 'activerecord', '>= 4.2.0'
|
26
26
|
s.add_dependency 'jquery-rails', '>= 3.1.1'
|
27
27
|
|
28
|
-
s.add_development_dependency 'sqlite3', '~> 1.3.
|
28
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.12'
|
29
29
|
s.add_development_dependency 'rspec-rails', '~> 3.5.1'
|
30
30
|
s.add_development_dependency 'factory_girl_rails', '~> 4.7.0'
|
31
31
|
s.add_development_dependency 'simplecov', '~> 0.12.0'
|
@@ -15,13 +15,21 @@ module ActivityNotification
|
|
15
15
|
#
|
16
16
|
# GET /:target_type/:target_id/notifcations
|
17
17
|
# @overload index(params)
|
18
|
-
# @param [Hash] params Request
|
19
|
-
# @option params [String] :filter
|
20
|
-
# @option params [String] :limit
|
21
|
-
# @option params [String] :
|
18
|
+
# @param [Hash] params Request parameter options for notification index
|
19
|
+
# @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
|
20
|
+
# @option params [String] :limit (nil) Limit to query for notifications
|
21
|
+
# @option params [String] :reverse ('false') If notification index will be ordered as earliest first
|
22
|
+
# @option params [String] :without_grouping ('false') If notification index will include group members
|
23
|
+
# @option params [String] :with_group_members ('false') If notification index will include group members
|
24
|
+
# @option params [String] :filtered_by_type (nil) Notifiable type for filter
|
25
|
+
# @option params [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
|
26
|
+
# @option params [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
|
27
|
+
# @option params [String] :filtered_by_key (nil) Key of the notification for filter
|
28
|
+
# @option params [String] :reload ('true') Whether notification index will be reloaded
|
22
29
|
# @return [Responce] HTML view as default or JSON of notification index with json format parameter
|
23
30
|
def index
|
24
|
-
|
31
|
+
set_index_options
|
32
|
+
@notifications = load_notification_index(@index_options) if params[:reload].to_s.to_boolean(true)
|
25
33
|
respond_to do |format|
|
26
34
|
format.html # index.html.erb
|
27
35
|
format.json { render json: @notifications.to_json(include: [:target, :notifiable, :group]) }
|
@@ -36,6 +44,8 @@ module ActivityNotification
|
|
36
44
|
# @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
|
37
45
|
# @option params [String] :limit (nil) Limit to query for notifications
|
38
46
|
# @option params [String] :reload ('true') Whether notification index will be reloaded
|
47
|
+
# @option params [String] :without_grouping ('false') If notification index will include group members
|
48
|
+
# @option params [String] :with_group_members ('false') If notification index will include group members
|
39
49
|
# @option params [String] :filtered_by_type (nil) Notifiable type for filter
|
40
50
|
# @option params [String] :filtered_by_group_type (nil) Group type for filter, valid only :filtered_by_group_id
|
41
51
|
# @option params [String] :filtered_by_group_id (nil) Group instance id for filter, valid only :filtered_by_group_type
|
@@ -43,7 +53,7 @@ module ActivityNotification
|
|
43
53
|
# @return [Responce] JavaScript view for ajax request or redirects to back as default
|
44
54
|
def open_all
|
45
55
|
@target.open_all_notifications(params)
|
46
|
-
return_back_or_ajax
|
56
|
+
return_back_or_ajax
|
47
57
|
end
|
48
58
|
|
49
59
|
# Shows a notification.
|
@@ -61,13 +71,15 @@ module ActivityNotification
|
|
61
71
|
#
|
62
72
|
# @overload destroy(params)
|
63
73
|
# @param [Hash] params Request parameters
|
64
|
-
# @option params [String] :filter
|
65
|
-
# @option params [String] :limit
|
66
|
-
# @option params [String] :reload
|
74
|
+
# @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
|
75
|
+
# @option params [String] :limit (nil) Limit to query for notifications
|
76
|
+
# @option params [String] :reload ('true') Whether notification index will be reloaded
|
77
|
+
# @option params [String] :without_grouping ('false') If notification index will include group members
|
78
|
+
# @option params [String] :with_group_members ('false') If notification index will include group members
|
67
79
|
# @return [Responce] JavaScript view for ajax request or redirects to back as default
|
68
80
|
def destroy
|
69
81
|
@notification.destroy
|
70
|
-
return_back_or_ajax
|
82
|
+
return_back_or_ajax
|
71
83
|
end
|
72
84
|
|
73
85
|
# Opens a notification.
|
@@ -75,16 +87,19 @@ module ActivityNotification
|
|
75
87
|
# POST /:target_type/:target_id/notifcations/:id/open
|
76
88
|
# @overload open(params)
|
77
89
|
# @param [Hash] params Request parameters
|
78
|
-
# @option params [String] :move
|
79
|
-
# @option params [String] :filter
|
80
|
-
# @option params [String] :limit
|
81
|
-
# @option params [String] :reload
|
90
|
+
# @option params [String] :move ('false') Whether redirects to notifiable_path after the notification is opened
|
91
|
+
# @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
|
92
|
+
# @option params [String] :limit (nil) Limit to query for notifications
|
93
|
+
# @option params [String] :reload ('true') Whether notification index will be reloaded
|
94
|
+
# @option params [String] :without_grouping ('false') If notification index will include group members
|
95
|
+
# @option params [String] :with_group_members ('false') If notification index will include group members
|
82
96
|
# @return [Responce] JavaScript view for ajax request or redirects to back as default
|
83
97
|
def open
|
84
|
-
|
98
|
+
with_members = !(params[:with_group_members].to_s.to_boolean(false) || params[:without_grouping].to_s.to_boolean(false))
|
99
|
+
@notification.open!(with_members: with_members)
|
85
100
|
params[:move].to_s.to_boolean(false) ?
|
86
101
|
move :
|
87
|
-
return_back_or_ajax
|
102
|
+
return_back_or_ajax
|
88
103
|
end
|
89
104
|
|
90
105
|
# Moves to notifiable_path of the notification.
|
@@ -146,20 +161,40 @@ module ActivityNotification
|
|
146
161
|
end
|
147
162
|
end
|
148
163
|
|
164
|
+
# Sets options to load notification index from request parameters.
|
165
|
+
# @api protected
|
166
|
+
# @return [Hash] options to load notification index
|
167
|
+
def set_index_options
|
168
|
+
limit = params[:limit].to_i > 0 ? params[:limit].to_i : nil
|
169
|
+
reverse = params[:reverse].present? ?
|
170
|
+
params[:reverse].to_s.to_boolean(false) : nil
|
171
|
+
with_group_members = params[:with_group_members].present? || params[:without_grouping].present? ?
|
172
|
+
params[:with_group_members].to_s.to_boolean(false) || params[:without_grouping].to_s.to_boolean(false) : nil
|
173
|
+
@index_options = params.permit(:filter, :filtered_by_type, :filtered_by_group_type, :filtered_by_group_id, :filtered_by_key)
|
174
|
+
.to_h.symbolize_keys
|
175
|
+
.merge(limit: limit, reverse: reverse, with_group_members: with_group_members)
|
176
|
+
end
|
177
|
+
|
149
178
|
# Loads notification index with request parameters.
|
150
179
|
# @api protected
|
151
|
-
# @param [
|
152
|
-
# @
|
180
|
+
# @param [Hash] params Request parameter options for notification index
|
181
|
+
# @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
|
182
|
+
# @option params [Integer] :limit (nil) Limit to query for notifications
|
183
|
+
# @option params [Boolean] :reverse (false) If notification index will be ordered as earliest first
|
184
|
+
# @option params [Boolean] :without_grouping (false) If notification index will include group members
|
185
|
+
# @option params [String] :filtered_by_type (nil) Notifiable type for filter
|
186
|
+
# @option params [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
|
187
|
+
# @option params [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
|
188
|
+
# @option params [String] :filtered_by_key (nil) Key of the notification for filter
|
153
189
|
# @return [Array] Array of notification index
|
154
|
-
def load_notification_index(
|
155
|
-
|
156
|
-
case filter
|
190
|
+
def load_notification_index(options = {})
|
191
|
+
case options[:filter]
|
157
192
|
when 'opened'
|
158
|
-
@target.opened_notification_index_with_attributes(
|
193
|
+
@target.opened_notification_index_with_attributes(options)
|
159
194
|
when 'unopened'
|
160
|
-
@target.unopened_notification_index_with_attributes(
|
195
|
+
@target.unopened_notification_index_with_attributes(options)
|
161
196
|
else
|
162
|
-
@target.notification_index_with_attributes(
|
197
|
+
@target.notification_index_with_attributes(options)
|
163
198
|
end
|
164
199
|
end
|
165
200
|
|
@@ -171,23 +206,32 @@ module ActivityNotification
|
|
171
206
|
|
172
207
|
# Returns JavaScript view for ajax request or redirects to back as default.
|
173
208
|
# @api protected
|
174
|
-
# @
|
175
|
-
# @
|
209
|
+
# @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
|
210
|
+
# @option params [Integer] :limit (nil) Limit to query for notifications
|
211
|
+
# @option params [Boolean] :reverse (false) If notification index will be ordered as earliest first
|
212
|
+
# @option params [Boolean] :without_grouping (false) If notification index will include group members
|
213
|
+
# @option params [String] :filtered_by_type (nil) Notifiable type for filter
|
214
|
+
# @option params [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
|
215
|
+
# @option params [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
|
216
|
+
# @option params [String] :filtered_by_key (nil) Key of the notification for filter
|
176
217
|
# @return [Responce] JavaScript view for ajax request or redirects to back as default
|
177
|
-
def return_back_or_ajax
|
178
|
-
|
218
|
+
def return_back_or_ajax
|
219
|
+
set_index_options
|
220
|
+
if params[:reload].to_s.to_boolean(true)
|
221
|
+
@notifications = load_notification_index(@index_options)
|
222
|
+
end
|
179
223
|
respond_to do |format|
|
180
224
|
if request.xhr?
|
181
225
|
format.js
|
182
226
|
# :skip-rails4:
|
183
227
|
elsif Rails::VERSION::MAJOR >= 5
|
184
|
-
redirect_back fallback_location: { action: :index },
|
228
|
+
redirect_back fallback_location: { action: :index }, **@index_options and return
|
185
229
|
# :skip-rails4:
|
186
230
|
# :skip-rails5:
|
187
231
|
elsif request.referer
|
188
|
-
redirect_to :back,
|
232
|
+
redirect_to :back, **@index_options and return
|
189
233
|
else
|
190
|
-
redirect_to action: :index,
|
234
|
+
redirect_to action: :index, **@index_options and return
|
191
235
|
end
|
192
236
|
# :skip-rails5:
|
193
237
|
end
|
@@ -4,18 +4,33 @@ if defined?(ActionMailer)
|
|
4
4
|
include ActivityNotification::Mailers::Helpers
|
5
5
|
|
6
6
|
# Sends notification email.
|
7
|
+
#
|
7
8
|
# @param [Notification] notification Notification instance to send email
|
8
|
-
# @param [Hash]
|
9
|
+
# @param [Hash] options Options for notification email
|
9
10
|
# @option options [String, Symbol] :fallback (:default) Fallback template to use when MissingTemplate is raised
|
11
|
+
# @return [Mail::Message|ActionMailer::DeliveryJob] Email message or its delivery job, return NilClass for wrong target
|
10
12
|
def send_notification_email(notification, options = {})
|
11
13
|
options[:fallback] ||= :default
|
12
14
|
if options[:fallback] == :none
|
13
15
|
options.delete(:fallback)
|
14
16
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
notification_mail(notification, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Sends batch notification email.
|
21
|
+
#
|
22
|
+
# @param [Object] target Target of batch notification email
|
23
|
+
# @param [Array<Notification>] notifications Target notifications to send batch notification email
|
24
|
+
# @param [Hash] options Options for notification email
|
25
|
+
# @option options [String, Symbol] :fallback (:batch_default) Fallback template to use when MissingTemplate is raised
|
26
|
+
# @option options [String] :batch_key (nil) Key of the batch notification email, a key of the first notification will be used if not specified
|
27
|
+
# @return [Mail::Message|ActionMailer::DeliveryJob] Email message or its delivery job, return NilClass for wrong target
|
28
|
+
def send_batch_notification_email(target, notifications, options = {})
|
29
|
+
options[:fallback] ||= :batch_default
|
30
|
+
if options[:fallback] == :none
|
31
|
+
options.delete(:fallback)
|
18
32
|
end
|
33
|
+
batch_notification_mail(target, notifications, options)
|
19
34
|
end
|
20
35
|
|
21
36
|
end
|
@@ -0,0 +1,79 @@
|
|
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
|
+
<% @notifications.each do |notification| %>
|
58
|
+
<div class="activity_wrapper">
|
59
|
+
<div class="user_image"></div>
|
60
|
+
<div class="user_desc_wrapper">
|
61
|
+
<p class="user_desc">
|
62
|
+
<strong><%= notification.notifier.present? ? notification.notifier.printable_notifier_name : 'Someone' %></strong>
|
63
|
+
notified you of
|
64
|
+
<%= notification.notifiable.printable_notifiable_name(notification.target) %><%= notification.group.present? ? " in #{notification.group.printable_group_name}." : "." %><br>
|
65
|
+
<span><%= notification.created_at.strftime("%b %d %H:%M") %></span>
|
66
|
+
</p>
|
67
|
+
<p class="user_desc">
|
68
|
+
<span>
|
69
|
+
<%= link_to "Move to notified #{notification.notifiable.printable_type.downcase}", move_notification_url_for(notification, open: true) %>
|
70
|
+
</span>
|
71
|
+
</p>
|
72
|
+
</div>
|
73
|
+
</div>
|
74
|
+
<% end %>
|
75
|
+
<p>Thank you!</p>
|
76
|
+
</body>
|
77
|
+
</html>
|
78
|
+
|
79
|
+
|