activity_notification 0.0.10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -0
  3. data/Gemfile +6 -3
  4. data/Gemfile.lock +74 -58
  5. data/README.md +53 -26
  6. data/activity_notification.gemspec +2 -0
  7. data/app/controllers/activity_notification/notifications_controller.rb +4 -4
  8. data/app/mailers/activity_notification/mailer.rb +9 -3
  9. data/app/views/activity_notification/mailer/default/default.html.erb +9 -4
  10. data/app/views/activity_notification/mailer/default/default.text.erb +10 -0
  11. data/app/views/activity_notification/notifications/default/_default.html.erb +173 -34
  12. data/app/views/activity_notification/notifications/default/_index.html.erb +119 -11
  13. data/app/views/activity_notification/notifications/default/destroy.js.erb +2 -2
  14. data/app/views/activity_notification/notifications/default/index.html.erb +25 -14
  15. data/app/views/activity_notification/notifications/default/open.js.erb +2 -2
  16. data/app/views/activity_notification/notifications/default/open_all.js.erb +2 -2
  17. data/app/views/activity_notification/notifications/default/show.html.erb +1 -1
  18. data/gemfiles/Gemfile.rails-4.2 +0 -2
  19. data/gemfiles/Gemfile.rails-4.2.lock +3 -3
  20. data/gemfiles/Gemfile.rails-5.0 +1 -3
  21. data/lib/activity_notification.rb +10 -9
  22. data/lib/activity_notification/apis/notification_api.rb +108 -14
  23. data/lib/activity_notification/common.rb +11 -2
  24. data/lib/activity_notification/config.rb +13 -13
  25. data/lib/activity_notification/helpers/view_helpers.rb +26 -4
  26. data/lib/activity_notification/mailers/helpers.rb +8 -4
  27. data/lib/activity_notification/models.rb +4 -0
  28. data/lib/activity_notification/models/concerns/group.rb +32 -0
  29. data/lib/activity_notification/models/concerns/notifiable.rb +60 -32
  30. data/lib/activity_notification/models/concerns/notifier.rb +17 -1
  31. data/lib/activity_notification/models/concerns/target.rb +114 -55
  32. data/lib/activity_notification/models/notification.rb +26 -25
  33. data/lib/activity_notification/rails.rb +1 -0
  34. data/lib/activity_notification/renderable.rb +8 -3
  35. data/lib/activity_notification/roles/acts_as_common.rb +28 -0
  36. data/lib/activity_notification/roles/acts_as_group.rb +38 -0
  37. data/lib/activity_notification/roles/acts_as_notifiable.rb +56 -22
  38. data/lib/activity_notification/roles/acts_as_notifier.rb +25 -2
  39. data/lib/activity_notification/roles/acts_as_target.rb +27 -9
  40. data/lib/activity_notification/version.rb +1 -1
  41. data/lib/generators/templates/activity_notification.rb +1 -1
  42. data/spec/concerns/apis/notification_api_spec.rb +361 -2
  43. data/spec/concerns/common_spec.rb +36 -0
  44. data/spec/concerns/models/group_spec.rb +61 -0
  45. data/spec/concerns/models/notifiable_spec.rb +37 -0
  46. data/spec/concerns/models/notifier_spec.rb +48 -0
  47. data/spec/concerns/models/target_spec.rb +81 -31
  48. data/spec/factories/dummy/dummy_group.rb +4 -0
  49. data/spec/helpers/view_helpers_spec.rb +13 -0
  50. data/spec/mailers/mailer_spec.rb +8 -1
  51. data/spec/models/dummy/dummy_group_spec.rb +6 -0
  52. data/spec/rails_app/app/assets/stylesheets/application.css +15 -0
  53. data/spec/rails_app/app/assets/stylesheets/reset.css +85 -0
  54. data/spec/rails_app/app/assets/stylesheets/style.css +244 -0
  55. data/spec/rails_app/app/controllers/articles_controller.rb +1 -1
  56. data/spec/rails_app/app/models/admin.rb +2 -1
  57. data/spec/rails_app/app/models/article.rb +9 -2
  58. data/spec/rails_app/app/models/comment.rb +8 -2
  59. data/spec/rails_app/app/models/dummy/dummy_group.rb +4 -0
  60. data/spec/rails_app/app/models/user.rb +8 -3
  61. data/spec/rails_app/app/views/articles/_form.html.erb +14 -10
  62. data/spec/rails_app/app/views/articles/edit.html.erb +8 -6
  63. data/spec/rails_app/app/views/articles/index.html.erb +59 -67
  64. data/spec/rails_app/app/views/articles/new.html.erb +7 -5
  65. data/spec/rails_app/app/views/articles/show.html.erb +47 -36
  66. data/spec/rails_app/app/views/layouts/_header.html.erb +36 -9
  67. data/spec/rails_app/app/views/layouts/application.html.erb +8 -6
  68. data/spec/rails_app/config/environments/development.rb +9 -0
  69. data/spec/rails_app/config/initializers/activity_notification.rb +1 -1
  70. data/spec/rails_app/db/schema.rb +14 -20
  71. data/spec/rails_app/db/seeds.rb +5 -5
  72. data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +13 -0
  73. data/spec/roles/acts_as_group_spec.rb +32 -0
  74. data/spec/roles/acts_as_notifiable_spec.rb +1 -1
  75. data/spec/roles/acts_as_notifier_spec.rb +15 -0
  76. data/spec/roles/acts_as_target_spec.rb +1 -1
  77. metadata +52 -2
@@ -152,14 +152,14 @@ module ActivityNotification
152
152
  # @param [String] limit Limit to query for notifications
153
153
  # @return [Array] Array of notification index
154
154
  def load_notification_index(filter, limit)
155
- limit = nil unless limit.to_i > 0
155
+ limit = limit.to_i > 0 ? limit.to_i : nil
156
156
  case filter
157
157
  when 'opened'
158
- @target.opened_notification_index_with_attributes(limit)
158
+ @target.opened_notification_index_with_attributes({ limit: limit })
159
159
  when 'unopened'
160
- @target.unopened_notification_index_with_attributes(limit)
160
+ @target.unopened_notification_index_with_attributes({ limit: limit })
161
161
  else
162
- @target.notification_index_with_attributes(limit)
162
+ @target.notification_index_with_attributes({ limit: limit })
163
163
  end
164
164
  end
165
165
 
@@ -5,12 +5,18 @@ if defined?(ActionMailer)
5
5
 
6
6
  # Sends notification email.
7
7
  # @param [Notification] notification Notification instance to send email
8
- def send_notification_email(notification)
8
+ # @param [Hash] options Options for notification email
9
+ # @option options [String, Symbol] :fallback (:default) Fallback template to use when MissingTemplate is raised
10
+ def send_notification_email(notification, options = {})
11
+ options[:fallback] ||= :default
12
+ if options[:fallback] == :none
13
+ options.delete(:fallback)
14
+ end
9
15
  if notification.target.notification_email_allowed?(notification.notifiable, notification.key) and
10
16
  notification.notifiable.notification_email_allowed?(notification.target, notification.key)
11
- notification_mail(notification)
17
+ notification_mail(notification, options)
12
18
  end
13
19
  end
14
-
20
+
15
21
  end
16
22
  end
@@ -1,7 +1,12 @@
1
- <p>Dear <%= @target.mailer_to %></p>
1
+ <p>Dear <%= @notification.target.printable_target_name %></p>
2
2
 
3
- <p>This is a notification of <%= @notifiable.printable_name %> for you.</p>
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>
4
8
 
5
- <p><%= link_to "Move to #{@notifiable.printable_name}", move_notification_url_for(@notification, open: true) %></p>
9
+ <p><%= link_to "Move to notified #{@notifiable.printable_type.downcase}", move_notification_url_for(@notification, open: true) %></p>
6
10
 
7
- <p>Thank you!</p>
11
+ <p>Thank you!</p>
12
+ <p><span><%= @notification.created_at.strftime("%b %d %H:%M") %></span></p>
@@ -0,0 +1,10 @@
1
+ Dear <%= @notification.target.printable_target_name %>
2
+
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
+
5
+ <%= "Move to notified #{@notifiable.printable_type.downcase}:" %>
6
+ <%= move_notification_url_for(@notification, open: true) %>
7
+
8
+ Thank you!
9
+
10
+ <%= @notification.created_at.strftime("%b %d %H:%M") %>
@@ -1,36 +1,175 @@
1
- <li>
2
- <div>
3
- <%= notification.notifier.present? ? notification.notifier.printable_name : 'Someone' %>
4
- <% if notification.group_member_exists? %>
5
- <%= " and other #{notification.group_member_count} people" %>
6
- <% end %>
7
- notified you of <%= notification.notifiable.printable_name %>
8
- <%= "in #{notification.group.printable_name}" if notification.group.present? %>
9
- </div>
10
- <div>
11
- <%= notification.opened? ? "Opened" : "Unopened" %>
12
- </div>
13
- <div>
14
- <%= link_to "Move", move_notification_path_for(notification) %>
15
- </div>
16
- <% if notification.unopened? %>
17
- <div>
18
- <%= link_to "Open and move (GET)", move_notification_path_for(notification, open: true) %>
19
- </div>
20
- <div>
21
- <%= link_to "Open and move (POST)", open_notification_path_for(notification, move: true), method: :post %>
22
- </div>
23
- <div>
24
- <%= link_to "Open", open_notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :post %>
25
- </div>
26
- <div>
27
- <%= link_to "Open (Ajax)", open_notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :post, remote: true %>
1
+ <% content_for :notification_content, flush: true do %>
2
+ <li 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
+ <% if notification.group_member_notifier_exists? %>
9
+ <%= " and #{notification.group_member_notifier_count} other" %>
10
+ <%= notification.notifier.present? ? notification.notifier.printable_type.pluralize.downcase : 'people' %>
11
+ <% end %>
12
+ notified you of
13
+ <% if notification.notifiable.present? %>
14
+ <% if notification.group_member_exists? %>
15
+ <%= " #{notification.group_notification_count} #{notification.notifiable_type.humanize.pluralize.downcase} including" %>
16
+ <% end %>
17
+ <%= notification.notifiable.printable_notifiable_name(notification.target) %>
18
+ <%= "in #{notification.group.printable_group_name}" if notification.group.present? %>
19
+ <% else %>
20
+ <% if notification.group_member_exists? %>
21
+ <%= " #{notification.group_notification_count} #{notification.notifiable_type.humanize.pluralize.downcase}" %>
22
+ <% else %>
23
+ <%= " a #{notification.notifiable_type.humanize.singularize.downcase}" %>
24
+ <% end %>
25
+ <%= "in #{notification.group.printable_group_name}" if notification.group.present? %>
26
+ but the notifiable is not found. It may have been deleted.
27
+ <% end %>
28
+ <br>
29
+ <span><%= notification.created_at.strftime("%b %d %H:%M") %></span>
30
+ </p>
28
31
  </div>
32
+ </li>
33
+ <% end %>
34
+
35
+ <div class="<%= "notification_#{notification.id}" %>">
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 %>
38
+ <div class="unopned_circle"></div>
39
+ <div class="unopned_description_wrapper">
40
+ <p class="unopned_description">Open</p>
41
+ </div>
42
+ <% end %>
43
+ <%= link_to open_notification_path_for(notification, move: true), method: :post do %>
44
+ <%= yield :notification_content %>
45
+ <% end %>
46
+ <div class="unopened_wrapper"></div>
47
+ <% else %>
48
+ <%= link_to move_notification_path_for(notification) do %>
49
+ <%= yield :notification_content %>
50
+ <% end %>
29
51
  <% end %>
30
- <div>
31
- <%= link_to "Destroy", notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :delete %>
32
- </div>
33
- <div>
34
- <%= link_to "Destroy (Ajax)", notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :delete, remote: true %>
35
- </div>
36
- </li>
52
+ </div>
53
+
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 %>
63
+
64
+ <style>
65
+ /* unopned_circle */
66
+ .unopned_wrapper{
67
+ position: absolute;
68
+ margin-top: 20px;
69
+ margin-left: 56px;
70
+ }
71
+ .unopned_wrapper .unopned_circle {
72
+ display: block;
73
+ width: 10px;
74
+ height: 10px;
75
+ position: absolute;
76
+ border-radius: 50%;
77
+ background-color: #27a5eb;
78
+ z-index: 2;
79
+ }
80
+ .unopned_wrapper:hover > .unopned_description_wrapper{
81
+ display: block;
82
+ }
83
+ .unopned_wrapper .unopned_description_wrapper {
84
+ display: none;
85
+ position: absolute;
86
+ margin-top: 26px;
87
+ margin-left: -24px;
88
+ }
89
+ .unopned_wrapper .unopned_description_wrapper .unopned_description {
90
+ position: absolute;
91
+ color: #fff;
92
+ font-size: 12px;
93
+ text-align: center;
94
+
95
+ border-radius: 4px;
96
+ background: rgba(0, 0, 0, 0.8);
97
+ padding: 4px 12px;
98
+ z-index: 999;
99
+ }
100
+ .unopned_wrapper .unopned_description_wrapper .unopned_description:before {
101
+ border: solid transparent;
102
+ border-top-width: 0;
103
+ content: "";
104
+ display: block;
105
+ position: absolute;
106
+ width: 0;
107
+ left: 50%;
108
+ top: -5px;
109
+ margin-left: -5px;
110
+ height: 0;
111
+ border-width: 0 5px 5px 5px;
112
+ border-color: transparent transparent rgba(0, 0, 0, 0.8) transparent;
113
+ z-index: 0;
114
+ }
115
+
116
+ /* list */
117
+ .notification_list {
118
+ padding: 15px 10px;
119
+ position: relative;
120
+ border-bottom: 1px solid #e5e5e5;
121
+ }
122
+ .notification_list.unopened {
123
+ background-color: #eeeff4;
124
+ }
125
+ .notification_list:hover {
126
+ background-color: #f8f9fb;
127
+ }
128
+ .notification_list:last-child {
129
+ border-bottom: none;
130
+ }
131
+ .notification_list:after{
132
+ content: "";
133
+ clear: both;
134
+ display: block;
135
+ }
136
+ .notification_list .notification_list_cover{
137
+ position: absolute;
138
+ opacity: 0;
139
+ top: 0;
140
+ left: 0;
141
+ width: 100%;
142
+ height: 100%;
143
+ z-index: 1;
144
+
145
+ }
146
+ .notification_list .list_image {
147
+ float: left;
148
+ width: 40px;
149
+ height: 40px;
150
+ background-position: center;
151
+ background-repeat: no-repeat;
152
+ background-size: cover;
153
+ background-color: #979797;
154
+ }
155
+ .notification_list .list_text_wrapper {
156
+ float: left;
157
+ width: calc(100% - 60px);
158
+ margin-left: 20px;
159
+ }
160
+ .notification_list .list_text_wrapper .list_text {
161
+ color: #4f4f4f;
162
+ font-size: 14px;
163
+ line-height: 1.4;
164
+ margin-top: 0;
165
+ height: auto;
166
+ font-weight: normal;
167
+ }
168
+ .notification_list .list_text_wrapper .list_text strong{
169
+ font-weight: bold;
170
+ }
171
+ .notification_list .list_text_wrapper .list_text span {
172
+ color: #979797;
173
+ font-size: 13px;
174
+ }
175
+ </style>
@@ -1,14 +1,122 @@
1
- <div>
2
- <%= link_to open_all_notifications_path_for(@target), method: :post, remote: true,
3
- class: "dropdown-toggle", data: {toggle: "dropdown"} do %>
4
- <div id="notification_count"><%= @target.unopened_notification_count %></div>
5
- <% end %>
6
-
7
- <!-- Make this dropdown -->
8
- <ul class="dropdown-menu">
9
- <div id="notification_index">
10
- <p>Notifications</p>
1
+ <div class="notification_wrapper">
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>
4
+ </a>
5
+ <div class="notification_list_wrapper">
6
+ <div class="notification_header_wrapper">
7
+ <p class="notification_header_title">
8
+ Notifications
9
+ </p>
10
+ <p class="notification_header_menu">
11
+ <%= link_to "Open all", open_all_notifications_path_for(@target), method: :post, remote: true %>
12
+ </p>
13
+ </div>
14
+ <div class="notifications">
11
15
  <%= yield :notification_index %>
12
16
  </div>
13
- </ul>
17
+ <%= link_to notifications_path_for(@target) do %>
18
+ <div class="notification_link_wrapper">
19
+ <p class="notification_link">
20
+ See notifications
21
+ </p>
22
+ </div>
23
+ <% end %>
24
+ </div>
14
25
  </div>
26
+
27
+ <style>
28
+ .notification_wrapper {
29
+ margin-left: 20px;
30
+ margin-right: 10px;
31
+ float: left;
32
+ position: relative;
33
+ }
34
+ .notification_wrapper .dropdown_notification{
35
+ cursor: pointer;
36
+ }
37
+ .notification_wrapper .dropdown_notification p span span{
38
+ color: #fff;
39
+ background-color: #e5e5e5;
40
+ border-radius: 4px;
41
+ font-size: 12px;
42
+ padding: 4px 8px;
43
+ }
44
+ .notification_wrapper .dropdown_notification p span span.unopened{
45
+ background-color: #f87880;
46
+ }
47
+ .notification_wrapper.open .notification_list_wrapper {
48
+ display: block;
49
+ }
50
+ .notification_wrapper .notification_list_wrapper {
51
+ display: none;
52
+ z-index: 999;
53
+ width: 330px;
54
+ height: 500px;
55
+ border: 1px solid #e5e5e5;
56
+ position: absolute;
57
+ top: calc(100% + 20px);
58
+ right: -10px;
59
+ background-color: #fff;
60
+ }
61
+ .notification_wrapper .notification_list_wrapper .notification_header_wrapper {
62
+ position: relative;
63
+ width: 330px;
64
+ height: 37px;
65
+ border-bottom: 1px solid #e5e5e5;
66
+ box-sizing: border-box;
67
+ background-color: #fff;
68
+ }
69
+ .notification_wrapper .notification_list_wrapper .notification_header_wrapper .notification_header_title {
70
+ position: absolute;
71
+ top: 4px;
72
+ left: 10px;
73
+ font-size: 14px;
74
+ }
75
+ .notification_wrapper .notification_list_wrapper .notification_header_wrapper .notification_header_menu {
76
+ position: absolute;
77
+ top: 4px;
78
+ right: 10px;
79
+ font-size: 14px;
80
+ }
81
+
82
+ .notification_wrapper .notification_list_wrapper .notifications {
83
+ position: relative;
84
+ width: 330px;
85
+ height: calc(500px - 37px - 37px);
86
+ overflow: scroll;
87
+ }
88
+ .notification_wrapper .notification_list_wrapper .notification_link_wrapper{
89
+ position: absolute;
90
+ bottom: 0;
91
+ width: 330px;
92
+ height: 26px;
93
+ border-top: 1px solid #e5e5e5;
94
+ padding: 4px 0 8px 0;
95
+ text-align: center;
96
+ background-color: #fff;
97
+ z-index: 2;
98
+ }
99
+ .notification_wrapper .notification_list_wrapper .notification_link_wrapper:hover{
100
+ background-color: #f8f9fb;
101
+ }
102
+ .notification_wrapper .notification_list_wrapper .notification_link_wrapper .notification_link{
103
+ text-align: center;
104
+ font-size: 14px;
105
+ }
106
+ </style>
107
+
108
+ <script>
109
+ $(document).click(function(e){
110
+ if( !$(e.target).is(".notification_list_cover") && !$(e.target).is(".notification_wrapper a") ){
111
+ if($(".notification_wrapper").hasClass("open") && !$(".notification_wrapper").hasClass("opened")){
112
+ $(".notification_wrapper").addClass("opened");
113
+ }else if($(".notification_wrapper").hasClass("opened")){
114
+ $(".notification_wrapper").removeClass("open").removeClass("opened");
115
+ }
116
+ }
117
+ });
118
+
119
+ $(".dropdown_notification").click(function(){
120
+ $(this).parent().toggleClass("open");
121
+ });
122
+ </script>
@@ -1,2 +1,2 @@
1
- $("#notification_count").html("<%= @target.unopened_notification_count %>");
2
- $("#notifications").html("<%= escape_javascript( render_notification(@notifications, fallback: "default") ) %>");
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,17 +1,28 @@
1
- <h1>Notifications for <%= @target.printable_name %></h1>
2
- <div id="notification_count"><%= @target.unopened_notification_count %></div>
3
-
4
- <div>
5
- <%= link_to "Open all", open_all_notifications_path_for(@target), method: :post %>
6
- </div>
7
- <div>
8
- <%= link_to "Open all (ajax)", open_all_notifications_path_for(@target), method: :post, remote: true %>
9
- </div>
10
- <ul>
11
- <div id="notifications">
12
- <%= render_notification(@notifications, fallback: :default) %>
13
- <%#= render_notification(@notifications, fallback: :text) %>
1
+ <div class="notification_wrapper">
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>
14
4
  </div>
15
- </ul>
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
+ <ul>
8
+ <div class="notifications">
9
+ <%= render_notification @notifications, fallback: :default %>
10
+ <%#= render_notification @notifications, fallback: :text %>
11
+ </div>
12
+ </ul>
13
+ </div>
16
14
 
17
15
  <%#= render_notifications_of @target, fallback: :default, index_content: :with_attributes %>
16
+
17
+ <style>
18
+ .notification_wrapper .notification_header h1 span span{
19
+ color: #fff;
20
+ background-color: #e5e5e5;
21
+ border-radius: 4px;
22
+ font-size: 12px;
23
+ padding: 4px 8px;
24
+ }
25
+ .notification_wrapper .notification_header h1 span span.unopened{
26
+ background-color: #f87880;
27
+ }
28
+ </style>