emailbutler 0.3.0 → 0.5.0

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: 2cb350207d1f0d4174a10f2589ee604cc3ddb71438ed6c63b057ef9975a93ed4
4
- data.tar.gz: a0dae6c1a23c417827d03abf56ae9386696ca175f5de107eb81473925d3010b4
3
+ metadata.gz: 66b96f7ab9361587e0c960875903a0c85cece5ed19ed6891a2acac9027600735
4
+ data.tar.gz: 93d341ed01c2a44c50b84bcdcbce9bb174a6aae6f88e896ac4f8e2a298a9cb2b
5
5
  SHA512:
6
- metadata.gz: 5c69ecaab954896b0378320e4c535dcfb152356117181fc55c3f5fb479afa73ddceee39bfbd10707c6b488710b07e8b281fa96dcc723c114fa76ed78a849aba2
7
- data.tar.gz: 8362e1119289ec26d18b29d7575d629a334265ae9365a052bc84f0e731694ad6372e314f976b22d118a31389691cc06c3194650dcc8b22f994bdfd8e05ab1282
6
+ metadata.gz: 2c3b0c916fc98bde2ab88bc1b0a226288ab1bb5123faac70b121b6d025e22e6892bfc56d55bbffb96f0c9370b15be8b4f096f3d3c773b1afd4baa614aa687fc6
7
+ data.tar.gz: b844827b40c941522993c4993a4c0aa2ab75d789a703189ed1f47c92733166a34d1c16f9b93d7e599d3a699d88e82655024146d4f879c7f28ce880457d1f9986
data/README.md CHANGED
@@ -42,6 +42,13 @@ Add this line to config/routes.rb
42
42
  mount Emailbutler::Engine => '/emailbutler'
43
43
  ```
44
44
 
45
+ ### UI styles
46
+
47
+ For adding styles for UI you need to add this line to assets/config/manifest.js
48
+ ```js
49
+ //= link emailbutler.css
50
+ ```
51
+
45
52
  ### Mailers
46
53
 
47
54
  Update you application mailer
@@ -68,8 +75,12 @@ end
68
75
 
69
76
  ### UI
70
77
 
71
- Emailbutler provides UI with rendering email tracking statistics - /emailbutler/ui/dashboard.
72
- And with opportunity to resend emails.
78
+ Emailbutler provides UI with rendering email tracking statistics - /emailbutler/ui, with opportunity to search, resend and/or destroy emails.
79
+
80
+ <img width="1463" alt="ui_index" src="https://user-images.githubusercontent.com/6195394/202743189-19d1845d-7991-494f-93c1-0dd92b0b5dac.png">
81
+
82
+ <img width="1461" alt="ui_show" src="https://user-images.githubusercontent.com/6195394/202743225-b0ba0ca2-d373-428c-973d-5ec4566a3784.png">
83
+
73
84
 
74
85
  ## License
75
86
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,9 +1,11 @@
1
1
  #emailbutler {
2
2
  #dashboard {
3
3
  padding-top: 1rem;
4
+ display: flex;
4
5
 
5
6
  .summary {
6
7
  list-style: none;
8
+ flex: 1;
7
9
  display: flex;
8
10
  flex-direction: row;
9
11
  padding: .75rem 1rem;
@@ -37,54 +39,74 @@
37
39
  }
38
40
  }
39
41
 
40
- .messages {
41
- width: 100%;
42
+ .search-form {
43
+ width: 20rem;
44
+ padding-right: 2rem;
42
45
 
43
- thead {
44
- tr {
45
- th {
46
- text-align: left;
47
- padding: .125rem .25rem;
48
- }
46
+ .form-field {
47
+ display: flex;
48
+ flex-direction: column;
49
+ margin-bottom: .5rem;
50
+
51
+ label {
52
+ margin-bottom: .25rem;
53
+ }
54
+
55
+ input {
56
+ padding: .25rem;
49
57
  }
50
58
  }
59
+ }
51
60
 
52
- tbody {
53
- tr {
54
- &:nth-of-type(odd) {
55
- background: #e5e7eb;
56
- }
61
+ .messages {
62
+ flex: 1;
63
+ height: 100%;
64
+
65
+ .pagination {
66
+ margin-bottom: 1rem;
57
67
 
58
- &:hover {
59
- background: #d1d5db;
68
+ .page {
69
+ padding: .25rem .5rem;
70
+ background: #bbf7d0;
71
+ color: #000;
72
+
73
+ a {
74
+ color: #000;
60
75
  }
76
+ }
77
+ }
61
78
 
62
- td {
63
- padding: .125rem .25rem;
79
+ table {
80
+ width: 100%;
64
81
 
65
- &.actions {
66
- display: flex;
82
+ thead {
83
+ tr {
84
+ th {
85
+ text-align: left;
86
+ padding: .125rem .25rem;
87
+ }
88
+ }
89
+ }
67
90
 
68
- button {
69
- box-shadow: none;
70
- border: none;
71
- cursor: pointer;
72
- padding: .25rem;
91
+ tbody {
92
+ tr {
93
+ &:nth-of-type(odd) {
94
+ background: #e5e7eb;
95
+ }
73
96
 
74
- &.resend {
75
- background: #bbf7d0;
76
- margin-right: .5rem;
97
+ &:hover {
98
+ background: #d1d5db;
99
+ }
77
100
 
78
- &:hover {
79
- background: #86efac;
80
- }
81
- }
101
+ td {
102
+ padding: .125rem .25rem;
82
103
 
83
- &.destroy {
84
- background: #fecaca;
104
+ &.actions {
105
+ display: flex;
85
106
 
86
- &:hover {
87
- background: #fca5a5;
107
+ button {
108
+ &:nth-of-type(1) {
109
+ margin-right: .5rem;
88
110
  }
89
111
  }
90
112
  }
@@ -94,4 +116,24 @@
94
116
  }
95
117
  }
96
118
  }
119
+
120
+ .button {
121
+ box-shadow: none;
122
+ border: none;
123
+ cursor: pointer;
124
+ padding: .25rem;
125
+ background: #bbf7d0;
126
+
127
+ &:hover {
128
+ background: #86efac;
129
+ }
130
+
131
+ &.warning {
132
+ background: #fecaca;
133
+
134
+ &:hover {
135
+ background: #fca5a5;
136
+ }
137
+ }
138
+ }
97
139
  }
@@ -7,12 +7,12 @@ module Emailbutler
7
7
 
8
8
  def update
9
9
  Emailbutler.resend_message(@message)
10
- redirect_to ui_dashboard_index_path
10
+ redirect_to ui_index_path
11
11
  end
12
12
 
13
13
  def destroy
14
14
  Emailbutler.destroy_message(@message)
15
- redirect_to ui_dashboard_index_path
15
+ redirect_to ui_index_path
16
16
  end
17
17
 
18
18
  private
@@ -1,13 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pagy'
4
+
3
5
  module Emailbutler
4
6
  class UiController < Emailbutler::ApplicationController
7
+ include Pagy::Backend
8
+
5
9
  http_basic_authenticate_with name: Emailbutler.configuration.ui_username,
6
10
  password: Emailbutler.configuration.ui_password,
7
11
  if: -> { basic_auth_enabled? }
8
12
 
13
+ def index
14
+ @summary = Emailbutler.count_messages_by_status
15
+ end
16
+
17
+ def show
18
+ @pagy, @messages = pagy(Emailbutler.find_messages_by(search_condition))
19
+ end
20
+
9
21
  private
10
22
 
23
+ def search_condition
24
+ {
25
+ status: params[:id] == 'all' ? nil : params[:id],
26
+ mailer: params[:mailer_name].presence,
27
+ action: params[:action_name].presence,
28
+ send_to: [params[:receiver].presence].compact.presence
29
+ }.compact
30
+ end
31
+
11
32
  def basic_auth_enabled?
12
33
  configuration = Emailbutler.configuration
13
34
 
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emailbutler
4
+ module ApplicationHelper
5
+ include Pagy::Frontend
6
+ end
7
+ end
@@ -1,12 +1,14 @@
1
1
  <div id="dashboard">
2
2
  <ul class="summary">
3
- <li class="status-summary">
4
- <span><%= @summary.values.sum %></span>
5
- <span>Total</span>
3
+ <li>
4
+ <%= link_to ui_path(:all), class: 'status-summary' do %>
5
+ <span><%= @summary.values.sum %></span>
6
+ <span>Total</span>
7
+ <% end %>
6
8
  </li>
7
9
  <% Emailbutler.adapter.message_class.statuses.each_key do |status| %>
8
10
  <li>
9
- <%= link_to ui_dashboard_path(status), class: 'status-summary' do %>
11
+ <%= link_to ui_path(status), class: 'status-summary' do %>
10
12
  <span><%= @summary[status].to_i %></span>
11
13
  <span><%= status.capitalize %></span>
12
14
  <% end %>
@@ -1,6 +1,6 @@
1
1
  <header>
2
2
  <div class="header-wrapper flex justify-between items-center">
3
- <%= link_to ui_dashboard_index_path do %>
3
+ <%= link_to ui_index_path do %>
4
4
  <h1>Emailbutler</h1>
5
5
  <% end %>
6
6
  <nav>
@@ -0,0 +1,61 @@
1
+ <div id="dashboard">
2
+ <section class="search-form">
3
+ <%= form_with url: ui_path(params[:id]), method: :get do |form| %>
4
+ <div class="form-field">
5
+ <%= form.label :mailer_name, 'Mailer', class: 'form-label' %>
6
+ <%= form.text_field :mailer_name, class: 'form-value', value: params[:mailer_name] %>
7
+ </div>
8
+ <div class="form-field">
9
+ <%= form.label :action_name, 'Action', class: 'form-label' %>
10
+ <%= form.text_field :action_name, class: 'form-value', value: params[:action_name] %>
11
+ </div>
12
+ <div class="form-field">
13
+ <%= form.label :receiver, 'Receiver', class: 'form-label' %>
14
+ <%= form.text_field :receiver, class: 'form-value', value: params[:receiver] %>
15
+ </div>
16
+ <%= form.submit 'Search', class: 'button' %>
17
+ <% end %>
18
+ </section>
19
+ <section class="messages">
20
+ <%== pagy_nav(@pagy) %>
21
+ <table cellspacing="0">
22
+ <thead>
23
+ <tr>
24
+ <th>ID</th>
25
+ <th>Mailer</th>
26
+ <th>Action</th>
27
+ <th>Send to</th>
28
+ <% if params[:id] == 'all' %>
29
+ <th>Status</th>
30
+ <% end %>
31
+ <th>Action params</th>
32
+ <th>Mailer params</th>
33
+ <th></th>
34
+ </tr>
35
+ </thead>
36
+ <tbody>
37
+ <% @messages.each do |message| %>
38
+ <tr>
39
+ <td><%= message.id %></td>
40
+ <td><%= message.mailer %></td>
41
+ <td><%= message.action %></td>
42
+ <td>
43
+ <% message.send_to.each do |receiver| %>
44
+ <p><%= receiver %></p>
45
+ <% end %>
46
+ </td>
47
+ <% if params[:id] == 'all' %>
48
+ <td><%= message.status %></td>
49
+ <% end %>
50
+ <td><%= message.params['action_params'] %></td>
51
+ <td><%= message.params['mailer_params'] %></td>
52
+ <td class="actions">
53
+ <%= button_to 'Resend', ui_message_path(message.uuid), method: :patch, class: 'button' %>
54
+ <%= button_to 'Destroy', ui_message_path(message.uuid), method: :delete, class: 'button warning' %>
55
+ </td>
56
+ </tr>
57
+ <% end %>
58
+ </tbody>
59
+ </table>
60
+ </section>
61
+ </div>
data/config/routes.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  Emailbutler::Engine.routes.draw do
4
4
  post '/webhooks', to: 'webhooks#create'
5
5
 
6
+ resources :ui, only: %i[index show]
6
7
  namespace :ui do
7
- resources :dashboard, only: %i[index show]
8
8
  resources :messages, only: %i[update destroy]
9
9
  end
10
10
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Emailbutler
4
- VERSION = '0.3.0'
4
+ VERSION = '0.5.0'
5
5
  end
@@ -12,8 +12,8 @@ module Emailbutler
12
12
  'dropped' => 'failed'
13
13
  }.freeze
14
14
 
15
- def self.call(args={})
16
- new.call(**args)
15
+ def self.call(...)
16
+ new.call(...)
17
17
  end
18
18
 
19
19
  def call(payload:)
@@ -7,8 +7,8 @@ module Emailbutler
7
7
  class Receiver
8
8
  SENDGRID_USER_AGENT = 'SendGrid Event API'
9
9
 
10
- def self.call(args={})
11
- new.call(**args)
10
+ def self.call(...)
11
+ new.call(...)
12
12
  end
13
13
 
14
14
  def call(user_agent:, payload:)
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emailbutler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bogdanov Anton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-04 00:00:00.000000000 Z
11
+ date: 2022-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pagy
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.10'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.10'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rails
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -70,16 +84,16 @@ dependencies:
70
84
  name: puma
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - ">"
87
+ - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '5.0'
89
+ version: '6.0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - ">"
94
+ - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '5.0'
96
+ version: '6.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rake
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +114,14 @@ dependencies:
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: '1.3'
117
+ version: '1.39'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: '1.3'
124
+ version: '1.39'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rubocop-performance
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -150,7 +164,8 @@ dependencies:
150
164
  - - "~>"
151
165
  - !ruby/object:Gem::Version
152
166
  version: '2.0'
153
- description: Write a longer description or delete this line.
167
+ description: Emailbutler allows you to track delivery status of emails sent by your
168
+ app.
154
169
  email:
155
170
  - kortirso@gmail.com
156
171
  executables: []
@@ -167,17 +182,16 @@ files:
167
182
  - app/assets/stylesheets/emailbutler/shared/header.scss
168
183
  - app/assets/stylesheets/emailbutler/views/dashboard.scss
169
184
  - app/controllers/emailbutler/application_controller.rb
170
- - app/controllers/emailbutler/ui/dashboard_controller.rb
171
185
  - app/controllers/emailbutler/ui/messages_controller.rb
172
186
  - app/controllers/emailbutler/ui_controller.rb
173
187
  - app/controllers/emailbutler/webhooks_controller.rb
174
- - app/views/emailbutler/ui/dashboard/index.html.erb
175
- - app/views/emailbutler/ui/dashboard/show.html.erb
188
+ - app/helpers/emailbutler/application_helper.rb
189
+ - app/views/emailbutler/ui/index.html.erb
176
190
  - app/views/emailbutler/ui/shared/_footer.html.erb
177
191
  - app/views/emailbutler/ui/shared/_header.html.erb
192
+ - app/views/emailbutler/ui/show.html.erb
178
193
  - app/views/layouts/emailbutler/application.html.erb
179
194
  - config/routes.rb
180
- - db/migrate/20220916162720_create_emailbutler_tables.rb
181
195
  - lib/emailbutler.rb
182
196
  - lib/emailbutler/adapters/active_record.rb
183
197
  - lib/emailbutler/configuration.rb
@@ -216,5 +230,5 @@ requirements: []
216
230
  rubygems_version: 3.3.7
217
231
  signing_key:
218
232
  specification_version: 4
219
- summary: Write a short summary, because RubyGems requires one.
233
+ summary: Email tracker for Ruby on Rails applications.
220
234
  test_files: []
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Emailbutler
4
- module Ui
5
- class DashboardController < Emailbutler::UiController
6
- def index
7
- @summary = Emailbutler.count_messages_by_status
8
- end
9
-
10
- def show
11
- @messages = Emailbutler.find_messages_by(status: params[:id])
12
- end
13
- end
14
- end
15
- end
@@ -1,35 +0,0 @@
1
- <div id="dashboard">
2
- <table class="messages" cellspacing="0">
3
- <thead>
4
- <tr>
5
- <th>ID</th>
6
- <th>UUID</th>
7
- <th>Mailer</th>
8
- <th>Action</th>
9
- <th>Send to</th>
10
- <th>Params</th>
11
- <th></th>
12
- </tr>
13
- </thead>
14
- <tbody>
15
- <% @messages.each do |message| %>
16
- <tr>
17
- <td><%= message.id %></td>
18
- <td><%= message.uuid %></td>
19
- <td><%= message.mailer %></td>
20
- <td><%= message.action %></td>
21
- <td>
22
- <% message.send_to.each do |receiver| %>
23
- <p><%= receiver %></p>
24
- <% end %>
25
- </td>
26
- <td><%= message.params %></td>
27
- <td class="actions">
28
- <%= button_to 'Resend', ui_message_path(message.uuid), method: :patch, class: 'resend' %>
29
- <%= button_to 'Destroy', ui_message_path(message.uuid), method: :delete, class: 'destroy' %>
30
- </td>
31
- </tr>
32
- <% end %>
33
- </tbody>
34
- </table>
35
- </div>
@@ -1,23 +0,0 @@
1
- class CreateEmailbutlerTables < ActiveRecord::Migration[7.0]
2
- def self.up
3
- enable_extension 'pgcrypto' unless extensions.include?('pgcrypto')
4
- enable_extension 'uuid-ossp' unless extensions.include?('uuid-ossp')
5
-
6
- create_table :emailbutler_messages do |t|
7
- t.uuid :uuid, null: false, default: ''
8
- t.string :mailer, null: false
9
- t.string :action, null: false
10
- t.jsonb :params, null: false, default: {}
11
- t.string :send_to, array: true
12
- t.integer :status, null: false, default: 0
13
- t.datetime :timestamp
14
- t.integer :lock_version
15
- t.timestamps
16
- end
17
- add_index :emailbutler_messages, :uuid, unique: true
18
- end
19
-
20
- def self.down
21
- drop_table :emailbutler_messages
22
- end
23
- end