georgia_mailer 0.1.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +3 -11
  4. data/app/assets/javascripts/georgia_mailer/components/message_table.js.coffee +32 -26
  5. data/app/assets/stylesheets/georgia_mailer/application.css.scss +1 -0
  6. data/app/assets/stylesheets/georgia_mailer/components/_button.scss +4 -0
  7. data/app/assets/stylesheets/georgia_mailer/{modules → components}/_message.scss +4 -7
  8. data/app/assets/stylesheets/georgia_mailer/modules/_categories.scss +17 -0
  9. data/app/assets/stylesheets/georgia_mailer/modules/_messages.scss +7 -0
  10. data/app/controllers/georgia/mailer/messages_controller.rb +38 -0
  11. data/app/controllers/georgia/messages_controller.rb +71 -36
  12. data/app/decorators/georgia/mailer/message_decorator.rb +23 -0
  13. data/app/helpers/georgia/messages_helper.rb +1 -1
  14. data/app/mailers/georgia/mailer/notifier.rb +20 -0
  15. data/app/models/georgia/mailer/message.rb +54 -0
  16. data/app/policies/georgia/mailer/mailer_policy.rb +52 -0
  17. data/app/presenters/georgia/mailer/message_actions_presenter.rb +42 -0
  18. data/app/searches/georgia/mailer/message_search.rb +7 -0
  19. data/app/services/georgia/mailer/spam_check.rb +19 -0
  20. data/app/views/georgia/header/_messages.html.erb +1 -1
  21. data/app/views/georgia/{georgia_mailer → mailer}/messages/_message.html.erb +2 -0
  22. data/app/views/{georgia_mailer → georgia/mailer}/messages/create.js.erb +0 -0
  23. data/app/views/{georgia_mailer → georgia/mailer}/notifier/new_message_notification.html.erb +10 -3
  24. data/app/views/georgia/messages/destroy.js.erb +4 -0
  25. data/app/views/georgia/messages/ham.js.erb +7 -0
  26. data/app/views/georgia/messages/search.html.erb +55 -37
  27. data/app/views/georgia/messages/show.html.erb +8 -8
  28. data/app/views/georgia/messages/spam.js.erb +7 -0
  29. data/app/views/public_activity/georgia_mailer_message/_create.html.erb +17 -0
  30. data/app/workers/georgia/mailer/destroy_all_spam_worker.rb +18 -0
  31. data/app/workers/georgia/mailer/email_delivery_worker.rb +21 -0
  32. data/app/workers/georgia/mailer/spam_worker.rb +20 -0
  33. data/config/routes.rb +3 -3
  34. data/lib/generators/georgia/mailer/install/install_generator.rb +24 -0
  35. data/lib/georgia/mailer/engine.rb +12 -0
  36. data/lib/georgia/mailer/version.rb +5 -0
  37. data/lib/georgia_mailer.rb +20 -7
  38. data/lib/tasks/georgia_mailer_tasks.rake +17 -17
  39. metadata +54 -47
  40. data/app/controllers/georgia_mailer/messages_controller.rb +0 -35
  41. data/app/decorators/georgia_mailer/message_decorator.rb +0 -21
  42. data/app/mailers/georgia_mailer/notifier.rb +0 -18
  43. data/app/models/georgia_mailer/message.rb +0 -32
  44. data/app/presenters/georgia_mailer/message_actions_presenter.rb +0 -53
  45. data/app/services/georgia_mailer/spam_check.rb +0 -17
  46. data/app/workers/georgia_mailer/email_delivery_worker.rb +0 -19
  47. data/app/workers/georgia_mailer/spam_worker.rb +0 -18
  48. data/lib/generators/georgia_mailer/install/install_generator.rb +0 -23
  49. data/lib/georgia/indexer/extensions/solr_adapter/georgia_mailer/message.rb +0 -44
  50. data/lib/georgia/indexer/extensions/tire_adapter/georgia_mailer/message.rb +0 -46
  51. data/lib/georgia_mailer/engine.rb +0 -10
  52. data/lib/georgia_mailer/version.rb +0 -3
@@ -0,0 +1,52 @@
1
+ module Georgia
2
+ module Mailer
3
+ class MailerPolicy < Georgia::ApplicationPolicy
4
+
5
+ def index?
6
+ mailer_user_permissions(:read_messages).include?(true)
7
+ end
8
+
9
+ def search?
10
+ index?
11
+ end
12
+
13
+ def show?
14
+ index?
15
+ end
16
+
17
+ def destroy?
18
+ mailer_user_permissions(:delete_messages).include?(true)
19
+ end
20
+
21
+ def spam?
22
+ mailer_user_permissions(:mark_messages_as_spam).include?(true)
23
+ end
24
+
25
+ def ham?
26
+ mailer_user_permissions(:mark_messages_as_ham).include?(true)
27
+ end
28
+
29
+ def print?
30
+ mailer_user_permissions(:print_messages).include?(true)
31
+ end
32
+
33
+ def destroy_all_spam?
34
+ mailer_user_permissions(:empty_trash).include?(true)
35
+ end
36
+
37
+ def resend_notification?
38
+ index?
39
+ end
40
+
41
+ private
42
+
43
+ def mailer_permissions
44
+ Georgia.permissions[:mailer]
45
+ end
46
+
47
+ def mailer_user_permissions action
48
+ user_permissions(mailer_permissions, action)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,42 @@
1
+ module Georgia
2
+ module Mailer
3
+ class MessageActionsPresenter < ::Georgia::Presenter
4
+
5
+ def initialize view_context, message
6
+ @message = (message.decorated? ? message.object : message)
7
+ super
8
+ end
9
+
10
+ def to_s
11
+ html = ActiveSupport::SafeBuffer.new
12
+ if @message.spam
13
+ html << link_to_ham# if can?(:ham, @message)
14
+ else
15
+ html << link_to_spam# if can?(:spam, @message)
16
+ end
17
+ html << link_to_resend_notification
18
+ html << link_to_trash# if can?(:destroy, @message)
19
+ html
20
+ end
21
+
22
+ private
23
+
24
+ def link_to_ham
25
+ link_to "#{icon_tag('thumbs-up')} Move to Inbox".html_safe, [:ham, @message], method: :post, class: 'btn btn-warning btn-sm'
26
+ end
27
+
28
+ def link_to_spam
29
+ link_to "#{icon_tag('exclamation-triangle')} Report spam".html_safe, [:spam, @message], method: :post, class: 'btn btn-warning btn-sm'
30
+ end
31
+
32
+ def link_to_resend_notification
33
+ link_to "#{icon_tag('envelope')} Resend notification".html_safe, [:resend_notification, @message], class: 'btn btn-warning btn-sm'
34
+ end
35
+
36
+ def link_to_trash
37
+ link_to "#{icon_tag('trash-o')} Trash".html_safe, @message, method: :delete, data: {confirm: 'Are you sure?'}, class: 'btn btn-danger btn-sm'
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ module Georgia
2
+ module Mailer
3
+ class MessageSearch < Georgia::SearchDefinition
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ module Georgia
2
+ module Mailer
3
+ class SpamCheck
4
+
5
+ def initialize message
6
+ @message = message
7
+ end
8
+
9
+ # The .spam? method comes from Rakismet. It gathers the necessary information and
10
+ # and calls Akismet for a spam check. It returns true or false based on the status
11
+ #
12
+ # https://github.com/joshfrench/rakismet/blob/master/lib/rakismet/model.rb
13
+ def call
14
+ @message.spam?
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
- <% if can? :index, GeorgiaMailer::Message %>
1
+ <% if policy(Georgia::Mailer::Message).search? %>
2
2
  <%= sidebar_navigation_link 'Inbox', georgia.search_messages_url, controller: 'messages', icon: 'envelope' %>
3
3
  <% end -%>
@@ -1,4 +1,6 @@
1
1
  <tr id='<%= dom_id(message) %>' class='message' data-status="<%= message.status %>">
2
+ <td class='status <%= message.status %>'>
3
+ </td>
2
4
  <td class='checkbox-cell'>
3
5
  <%= checkboxable_tag message %>
4
6
  </td>
@@ -173,11 +173,18 @@ ul li, ol li {
173
173
  <tr>
174
174
  <td>
175
175
  <p>Hi there,</p>
176
- <p>You've received a new message on Georgia CMS from <%= @message.name_or_anonymous %></p>
177
- <% if @message.subject.present? %><h1><%= @message.subject %></h1><% end %>
176
+ <p>You've received a new message on Georgia CMS.</p>
177
+ <% if @message.subject.present? %>
178
+ <h1><%= @message.subject %></h1>
179
+ <% end %>
178
180
  <p><%= @message.message %></p>
181
+ <p>Date: <%= @message.created_at.strftime('%F %H:%M:%S') %></p>
182
+ <p>From: <%= @message.name_or_anonymous %></p>
183
+ <p>URL: <%= @message.referrer || 'unknown' %></p>
179
184
  <% if @message.phone.present? %><p><%= @message.phone %></p><% end -%>
180
- <p><a href="<%= georgia.message_path(@message, only_path: false) %>" class='btn-primary'>Have a closer look</a></p>
185
+ <p>
186
+ <a href="<%= georgia.message_path(@message, only_path: false) %>" class='btn-primary'>Have a closer look</a>
187
+ </p>
181
188
  <p>Thanks, have a lovely day.</p>
182
189
  </td>
183
190
  </tr>
@@ -1,3 +1,7 @@
1
+ <% if @status_message and @status %>
2
+ new Flash('<%= @status_message %>', '<%= @status %>')
3
+ <% end %>
4
+
1
5
  <% @messages.each do |m| %>
2
6
  $('tr#message_<%= m.id %>').remove()
3
7
  <% end -%>
@@ -0,0 +1,7 @@
1
+ <% if @status_message and @status %>
2
+ new Flash('<%= @status_message %>', '<%= @status %>')
3
+ <% end %>
4
+
5
+ <% @messages.each do |m| %>
6
+ $('tr#message_<%= m.id %>').remove();
7
+ <% end -%>
@@ -22,42 +22,60 @@
22
22
 
23
23
  <section class="body-main">
24
24
 
25
- <table class="table table-hover table-results messages js-checkboxable">
26
- <thead>
27
- <th colspan='3'>
28
- <div class="btn-group">
29
- <div class="btn btn-default dropdown-toggle" data-toggle="dropdown">
30
- <%= checkboxable_all_tag :messages %>
31
- <span class="caret"></span>
32
- </div>
33
- <ul class="dropdown-menu" role="menu">
34
- <li><%= link_to 'All', '#', class: 'js-select-all' %></li>
35
- <li><%= link_to 'None', '#', class: 'js-select-none' %></li>
36
- <li><%= link_to 'Spam', '#', class: 'js-select-spam' %></li>
37
- </ul>
38
- </div>
39
- <%= link_to "#{icon_tag('thumbs-up')} ham".html_safe, '#', class: 'btn btn-default btn-xs js-ham disabled' %>
40
- <%= link_to "#{icon_tag('thumbs-down')} spam".html_safe, '#', class: 'btn btn-default btn-xs js-spam disabled' %>
41
- <%= link_to "#{icon_tag('trash-o')} trash".html_safe, '#', class: 'btn btn-default btn-xs js-delete disabled' %>
42
- <%#= link_to '#', class: 'btn btn-warning' do %>
43
- <%#= icon_tag('tags') %> <%#= icon_tag('caret-down') %>
44
- <%# end -%>
45
- </th>
46
- <th colspan='3'>
47
- <%= pagination_tag(@search) %>
48
- </th>
49
- </thead>
50
- <tbody>
51
- <% if @messages and @messages.any? %>
52
- <%= render @messages %>
53
- <% else %>
54
- <tr>
55
- <td colspan="6">
56
- There are currently no messages.
57
- </td>
58
- </tr>
59
- <% end %>
60
- </tbody>
61
- </table>
25
+ <div class="row">
26
+ <div class="col-md-1">
27
+ <div class="inbox-categories">
28
+ <%= link_to 'Inbox', search_messages_path, class: "inbox-category-link#{' active' unless params[:spam].present?}" %>
29
+ <%= link_to 'Spam', search_messages_path(spam: 1), class: "inbox-category-link#{' active' if params[:spam] == '1'}" %>
30
+ <%= link_to 'All', search_messages_path(spam: 0), class: "inbox-category-link#{' active' if params[:spam] == '0'}" %>
31
+ </div>
32
+ </div>
33
+ <div class="col-md-11">
34
+ <table class="table table-hover table-results messages js-checkboxable">
35
+ <thead>
36
+ <tr>
37
+ <th class='status'></th>
38
+ <th class='checkbox-cell'>
39
+ <%= checkboxable_all_tag :messages %>
40
+ </th>
41
+ <th class='actions'>
42
+ <% if params[:spam] == '1' %>
43
+ <%= link_to "#{icon_tag('thumbs-up')} Move to Inbox".html_safe, '#', class: 'btn btn-default btn-xs js-ham disabled' %>
44
+ <% else %>
45
+ <%= link_to "#{icon_tag('thumbs-down')} Report spam".html_safe, '#', class: 'btn btn-default btn-xs js-spam disabled' %>
46
+ <% end %>
47
+ <%= link_to "#{icon_tag('trash-o')} Delete".html_safe, '#', class: 'btn btn-default btn-xs js-delete disabled' %>
48
+ </th>
49
+ <th colspan='3'>
50
+ <%= pagination_tag(@search) %>
51
+ </th>
52
+ </tr>
53
+ <% if params[:spam] == '1' and @messages and @messages.any? %>
54
+ <tr class='active'>
55
+ <th colspan='7' class='messages-destroy-spam'>
56
+ <%= link_to 'delete all spam messages now', destroy_all_spam_messages_path %>
57
+ </th>
58
+ </tr>
59
+ <% end %>
60
+ </thead>
61
+ <tbody>
62
+ <% if @messages and @messages.any? %>
63
+ <%= render @messages %>
64
+ <% else %>
65
+ <tr>
66
+ <td colspan="7">
67
+ <%# FIXME: Should work with I18n %>
68
+ <% if params[:spam] == '1' %>
69
+ Hooray, no spam here!
70
+ <% else %>
71
+ Your inbox is empty.
72
+ <% end %>
73
+ </td>
74
+ </tr>
75
+ <% end %>
76
+ </tbody>
77
+ </table>
78
+ </div>
79
+ </div>
62
80
 
63
81
  </section>
@@ -7,7 +7,9 @@
7
7
  <div class="header-gutter">
8
8
  <%= link_to_back search_messages_path %>
9
9
  </div>
10
- <div class="header-title"></div>
10
+ <div class="header-title">
11
+ <%= message_actions_list(@message) %>
12
+ </div>
11
13
  <div class="header-actions">
12
14
  </div>
13
15
  </header>
@@ -16,13 +18,11 @@
16
18
  <h2><%= @message.subject %></h2>
17
19
  <div class="message-info">
18
20
  <div class="btn-group pull-right hidden-print">
19
- <%= link_to "#{icon_tag('reply')} Reply".html_safe, "mailto:#{@message.email}", class: 'btn btn-warning btn-sm', target: '_blank' %>
20
- <button type="button" class="btn btn-warning btn-sm dropdown-toggle" data-toggle="dropdown">
21
- <span class="caret"></span>
22
- <span class="sr-only">Toggle Dropdown</span>
23
- </button>
24
- <ul class="dropdown-menu" role="menu">
25
- <%= message_actions_list(@message) %>
21
+ <ul class="nav">
22
+ <li>
23
+ <%= link_to "#{icon_tag('print')} Print".html_safe, "javascript:window.print()", class: 'btn btn-info btn-sm', target: '_blank' %></li>
24
+ <li>
25
+ <%= link_to "#{icon_tag('reply')} Reply".html_safe, "mailto:#{@message.email}", class: 'btn btn-warning btn-sm', target: '_blank' %></li>
26
26
  </ul>
27
27
  </div>
28
28
  <strong><%= @message.name_or_anonymous %></strong>
@@ -0,0 +1,7 @@
1
+ <% if @status_message and @status %>
2
+ new Flash('<%= @status_message %>', '<%= @status %>')
3
+ <% end %>
4
+
5
+ <% @messages.each do |m| %>
6
+ $('tr#message_<%= m.id %>').remove()
7
+ <% end -%>
@@ -0,0 +1,17 @@
1
+ <% if activity.trackable and !activity.trackable.spam %>
2
+ <div id='activity_<%= activity.id %>' class="activity media">
3
+ <%= image_tag(avatar_url(activity.trackable.email), alt: '', class: 'media-object pull-left') %>
4
+ <div class="media-body">
5
+ <h4 class="media-heading">
6
+ <%= activity.trackable.name %> posted a new message <em><%= link_to activity.trackable.subject, activity.trackable %></em>
7
+ </h4>
8
+ <p>
9
+ <small>
10
+ <time class='text-muted js-time-ago' datetime="<%= activity.created_at %>">
11
+ About <%= time_ago_in_words(activity.created_at) %> ago
12
+ </time>
13
+ </small>
14
+ </p>
15
+ </div>
16
+ </div>
17
+ <% end -%>
@@ -0,0 +1,18 @@
1
+ module Georgia
2
+ module Mailer
3
+ class DestroyAllSpamWorker
4
+ include SuckerPunch::Job
5
+
6
+ def perform
7
+ ActiveRecord::Base.connection_pool.with_connection do
8
+ begin
9
+ Message.destroy_all(spam: true)
10
+ rescue ActiveRecord::RecordNotFound
11
+ Rails.logger.info "Message with ID #{message_id} was destroy before it could be processed"
12
+ end
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ module Georgia
2
+ module Mailer
3
+ class EmailDeliveryWorker
4
+ include SuckerPunch::Job
5
+
6
+ def perform(message_id)
7
+ ActiveRecord::Base.connection_pool.with_connection do
8
+ message = Message.find(message_id)
9
+ unless message.spam or !Georgia::Mailer.turn_on_email_notifications
10
+ Notifier.new_message_notification(message).deliver_now
11
+ end
12
+ end
13
+ end
14
+
15
+ def later(sec, message_id)
16
+ after(sec) { perform(message_id) }
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ module Georgia
2
+ module Mailer
3
+ class SpamWorker
4
+ include SuckerPunch::Job
5
+
6
+ def perform(message_id)
7
+ ActiveRecord::Base.connection_pool.with_connection do
8
+ begin
9
+ message = Message.find(message_id)
10
+ is_spam = SpamCheck.new(message).call
11
+ message.update_attributes(spam: is_spam, verified_at: Time.zone.now)
12
+ rescue ActiveRecord::RecordNotFound
13
+ Rails.logger.info "Message with ID #{message_id} was destroy before it could be processed"
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -1,4 +1,4 @@
1
- GeorgiaMailer::Engine.routes.draw do
1
+ Georgia::Mailer::Engine.routes.draw do
2
2
 
3
3
  resources :messages, only: :create
4
4
 
@@ -12,9 +12,9 @@ Georgia::Engine.routes.draw do
12
12
  get :destroy_all_spam
13
13
  end
14
14
  member do
15
- get :spam
16
- get :ham
17
15
  get :resend_notification
16
+ post :spam
17
+ post :ham
18
18
  end
19
19
  end
20
20
 
@@ -0,0 +1,24 @@
1
+ module Georgia
2
+ module Mailer
3
+ module Generators
4
+ class InstallGenerator < ::Rails::Generators::Base
5
+
6
+ def mount_engine
7
+ route "mount Georgia::Mailer::Engine => '/mailer'"
8
+ end
9
+
10
+ def run_migrations
11
+ rake "railties:install:migrations"
12
+ rake "db:migrate"
13
+ end
14
+
15
+ def create_index
16
+ Georgia::Mailer::Message.__elasticsearch__.indices.delete! Georgia::Mailer::Message.index_name rescue nil
17
+ Georgia::Mailer::Message.__elasticsearch__.create_index! force: true
18
+ Georgia::Mailer::Message.import
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ module Georgia
2
+ module Mailer
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Georgia::Mailer
5
+
6
+ require 'georgia'
7
+ require 'rakismet'
8
+ require 'sucker_punch'
9
+
10
+ end
11
+ end
12
+ end