mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 15:48:43 -05:00
FEATURE: add filters on email logs
This commit is contained in:
parent
21f757fd72
commit
3f3c9ca7cb
16 changed files with 145 additions and 67 deletions
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
This controller supports email logs functionality.
|
||||||
|
|
||||||
|
@class AdminEmailSkippedController
|
||||||
|
@extends Discourse.Controller
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.AdminEmailSkippedController = Discourse.Controller.extend({
|
||||||
|
|
||||||
|
filterEmailLogs: Discourse.debounce(function() {
|
||||||
|
var self = this;
|
||||||
|
this.set("loading", true);
|
||||||
|
Discourse.EmailLog.findAll(this.get("filter")).then(function(logs) {
|
||||||
|
self.set("model", false);
|
||||||
|
self.set("model", logs);
|
||||||
|
});
|
||||||
|
}, 250).observes("filter.user", "filter.address", "filter.type", "filter.reason"),
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
This controller supports email logs functionality.
|
||||||
|
|
||||||
|
@class AdminEmailSentController
|
||||||
|
@extends Discourse.Controller
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.AdminEmailSentController = Discourse.Controller.extend({
|
||||||
|
|
||||||
|
filterEmailLogs: Discourse.debounce(function() {
|
||||||
|
var self = this;
|
||||||
|
this.set("loading", true);
|
||||||
|
Discourse.EmailLog.findAll(this.get("filter")).then(function(logs) {
|
||||||
|
self.set("loading", false);
|
||||||
|
self.set("model", logs);
|
||||||
|
});
|
||||||
|
}, 250).observes("filter.user", "filter.address", "filter.type", "filter.reply_key"),
|
||||||
|
|
||||||
|
});
|
|
@ -9,25 +9,27 @@
|
||||||
Discourse.EmailLog = Discourse.Model.extend({});
|
Discourse.EmailLog = Discourse.Model.extend({});
|
||||||
|
|
||||||
Discourse.EmailLog.reopenClass({
|
Discourse.EmailLog.reopenClass({
|
||||||
|
|
||||||
create: function(attrs) {
|
create: function(attrs) {
|
||||||
attrs = attrs || {};
|
attrs = attrs || {};
|
||||||
|
|
||||||
if (attrs.user) {
|
if (attrs.user) {
|
||||||
attrs.user = Discourse.AdminUser.create(attrs.user);
|
attrs.user = Discourse.AdminUser.create(attrs.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._super(attrs);
|
return this._super(attrs);
|
||||||
},
|
},
|
||||||
|
|
||||||
findAll: function(filter) {
|
findAll: function(filter) {
|
||||||
var result = Em.A();
|
filter = filter || {};
|
||||||
Discourse.ajax("/admin/email/" + (filter === 'skipped' ? 'skipped' : 'logs') + ".json", {
|
var status = filter.status || "sent";
|
||||||
data: { filter: filter }
|
filter = _.omit(filter, "status");
|
||||||
}).then(function(logs) {
|
|
||||||
_.each(logs,function(log) {
|
return Discourse.ajax("/admin/email/" + status + ".json", { data: filter }).then(function(logs) {
|
||||||
result.pushObject(Discourse.EmailLog.create(log));
|
return _.map(logs, function (log) {
|
||||||
|
return Discourse.EmailLog.create(log);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,11 @@
|
||||||
**/
|
**/
|
||||||
Discourse.AdminEmailIndexRoute = Discourse.Route.extend({
|
Discourse.AdminEmailIndexRoute = Discourse.Route.extend({
|
||||||
|
|
||||||
setupController: function(controller) {
|
model: function() {
|
||||||
Discourse.EmailSettings.find().then(function (model) {
|
return Discourse.EmailSettings.find();
|
||||||
controller.set('model', model);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderTemplate: function() {
|
renderTemplate: function() {
|
||||||
this.render('admin/templates/email_index', {into: 'adminEmail'});
|
this.render('admin/templates/email_index', { into: 'adminEmail' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
/**
|
|
||||||
Handles routes related to viewing email logs.
|
|
||||||
|
|
||||||
@class AdminEmailLogsRoute
|
|
||||||
@extends Discourse.Route
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.AdminEmailLogsRoute = Discourse.Route.extend({
|
|
||||||
model: function() {
|
|
||||||
return Discourse.EmailLog.findAll();
|
|
||||||
},
|
|
||||||
|
|
||||||
renderTemplate: function() {
|
|
||||||
this.render('admin/templates/email_logs', {into: 'adminEmail'});
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
Handles routes related to viewing email logs.
|
||||||
|
|
||||||
|
@class AdminEmailSentRoute
|
||||||
|
@extends Discourse.Route
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.AdminEmailLogsRoute = Discourse.Route.extend({
|
||||||
|
|
||||||
|
model: function() {
|
||||||
|
return Discourse.EmailLog.findAll({ status: this.get("status") });
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController: function(controller) {
|
||||||
|
// resets the filters
|
||||||
|
controller.set("filter", { status: this.get("status") });
|
||||||
|
},
|
||||||
|
|
||||||
|
renderTemplate: function() {
|
||||||
|
this.render("admin/templates/email_" + this.get("status"), { into: "adminEmail" });
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Discourse.AdminEmailSentRoute = Discourse.AdminEmailLogsRoute.extend({ status: "sent" });
|
||||||
|
Discourse.AdminEmailSkippedRoute = Discourse.AdminEmailLogsRoute.extend({ status: "skipped" });
|
|
@ -1,17 +0,0 @@
|
||||||
/**
|
|
||||||
Handles routes related to viewing email logs of emails that were NOT sent.
|
|
||||||
|
|
||||||
@class AdminEmailSkippedRoute
|
|
||||||
@extends Discourse.Route
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.AdminEmailSkippedRoute = Discourse.Route.extend({
|
|
||||||
model: function() {
|
|
||||||
return Discourse.EmailLog.findAll('skipped');
|
|
||||||
},
|
|
||||||
|
|
||||||
renderTemplate: function() {
|
|
||||||
this.render('admin/templates/email_skipped', {into: 'adminEmail'});
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -16,7 +16,7 @@ Discourse.Route.buildRoutes(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.resource('adminEmail', { path: '/email'}, function() {
|
this.resource('adminEmail', { path: '/email'}, function() {
|
||||||
this.route('logs');
|
this.route('sent');
|
||||||
this.route('skipped');
|
this.route('skipped');
|
||||||
this.route('previewDigest', { path: '/preview-digest' });
|
this.route('previewDigest', { path: '/preview-digest' });
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class='span15'>
|
<div class='span15'>
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li>{{#link-to 'adminEmail.index'}}{{i18n admin.email.settings}}{{/link-to}}</li>
|
<li>{{#link-to 'adminEmail.index'}}{{i18n admin.email.settings}}{{/link-to}}</li>
|
||||||
<li>{{#link-to 'adminEmail.logs'}}{{i18n admin.email.logs}}{{/link-to}}</li>
|
<li>{{#link-to 'adminEmail.sent'}}{{i18n admin.email.sent}}{{/link-to}}</li>
|
||||||
<li>{{#link-to 'adminEmail.skipped'}}{{i18n admin.email.skipped}}{{/link-to}}</li>
|
<li>{{#link-to 'adminEmail.skipped'}}{{i18n admin.email.skipped}}{{/link-to}}</li>
|
||||||
<li>{{#link-to 'adminEmail.previewDigest'}}{{i18n admin.email.preview_digest}}{{/link-to}}</li>
|
<li>{{#link-to 'adminEmail.previewDigest'}}{{i18n admin.email.preview_digest}}{{/link-to}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -9,7 +9,15 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
{{#if model.length}}
|
<tr class="filters">
|
||||||
|
<td>{{i18n admin.email.logs.filters.title}}</td>
|
||||||
|
<td>{{textField value=filter.user placeholderKey="admin.email.logs.filters.user_placeholder"}}</td>
|
||||||
|
<td>{{textField value=filter.address placeholderKey="admin.email.logs.filters.address_placeholder"}}</td>
|
||||||
|
<td>{{textField value=filter.type placeholderKey="admin.email.logs.filters.type_placeholder"}}</td>
|
||||||
|
<td>{{textField value=filter.reply_key placeholderKey="admin.email.logs.filters.reply_key_placeholder"}}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{{#if model}}
|
||||||
{{#groupedEach model}}
|
{{#groupedEach model}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{unboundDate created_at}}</td>
|
<td>{{unboundDate created_at}}</td>
|
||||||
|
@ -26,6 +34,8 @@
|
||||||
<td>{{reply_key}}</td>
|
<td>{{reply_key}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/groupedEach}}
|
{{/groupedEach}}
|
||||||
|
{{else}}
|
||||||
|
<tr><td colspan="5">{{i18n admin.email.logs.none}}</td></tr>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
</table>
|
</table>
|
|
@ -9,7 +9,15 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
{{#if model.length}}
|
<tr class="filters">
|
||||||
|
<td>{{i18n admin.email.logs.filters.title}}</td>
|
||||||
|
<td>{{textField value=filter.user placeholderKey="admin.email.logs.filters.user_placeholder"}}</td>
|
||||||
|
<td>{{textField value=filter.address placeholderKey="admin.email.logs.filters.address_placeholder"}}</td>
|
||||||
|
<td>{{textField value=filter.type placeholderKey="admin.email.logs.filters.type_placeholder"}}</td>
|
||||||
|
<td>{{textField value=filter.skipReason placeholderKey="admin.email.logs.filters.skip_reason_placeholder"}}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{{#if model}}
|
||||||
{{#groupedEach model}}
|
{{#groupedEach model}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{unboundDate created_at}}</td>
|
<td>{{unboundDate created_at}}</td>
|
||||||
|
@ -23,11 +31,11 @@
|
||||||
</td>
|
</td>
|
||||||
<td><a href='mailto:{{unbound to_address}}'>{{to_address}}</a></td>
|
<td><a href='mailto:{{unbound to_address}}'>{{to_address}}</a></td>
|
||||||
<td>{{email_type}}</td>
|
<td>{{email_type}}</td>
|
||||||
<td>
|
<td>{{skipped_reason}}</td>
|
||||||
{{skipped_reason}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{{/groupedEach}}
|
{{/groupedEach}}
|
||||||
|
{{else}}
|
||||||
|
<tr><td colspan="5">{{i18n admin.email.logs.none}}</td></tr>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
td {border-bottom: 1px solid $primary_lighter; border-top: 1px solid $primary_lighter;}
|
td {border-bottom: 1px solid $primary_lighter; border-top: 1px solid $primary_lighter;}
|
||||||
tr:hover { background-color: darken($secondary, 2.5%); }
|
tr:hover { background-color: darken($secondary, 2.5%); }
|
||||||
tr.selected { background-color: lighten($tertiary, 58%); }
|
tr.selected { background-color: lighten($tertiary, 58%); }
|
||||||
|
.filters input { margin-bottom: 0px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-list li a span.count {
|
.content-list li a span.count {
|
||||||
|
|
|
@ -3,10 +3,8 @@ require_dependency 'email/renderer'
|
||||||
class Admin::EmailController < Admin::AdminController
|
class Admin::EmailController < Admin::AdminController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render_json_dump({
|
data = { delivery_method: delivery_method, settings: delivery_settings }
|
||||||
delivery_method: delivery_method,
|
render_json_dump(data)
|
||||||
settings: delivery_settings
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test
|
def test
|
||||||
|
@ -15,14 +13,14 @@ class Admin::EmailController < Admin::AdminController
|
||||||
render nothing: true
|
render nothing: true
|
||||||
end
|
end
|
||||||
|
|
||||||
def logs
|
def sent
|
||||||
@email_logs = EmailLog.sent.limit(50).includes(:user).order('created_at desc').to_a
|
email_logs = filter_email_logs(EmailLog.sent, params)
|
||||||
render_serialized(@email_logs, EmailLogSerializer)
|
render_serialized(email_logs, EmailLogSerializer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def skipped
|
def skipped
|
||||||
@email_logs = EmailLog.skipped.limit(50).includes(:user).order('created_at desc').to_a
|
email_logs = filter_email_logs(EmailLog.skipped, params)
|
||||||
render_serialized(@email_logs, EmailLogSerializer)
|
render_serialized(email_logs, EmailLogSerializer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def preview_digest
|
def preview_digest
|
||||||
|
@ -33,6 +31,16 @@ class Admin::EmailController < Admin::AdminController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def filter_email_logs(email_logs, params)
|
||||||
|
email_logs = email_logs.limit(50).includes(:user).order("email_logs.created_at desc").references(:user)
|
||||||
|
email_logs = email_logs.where("users.username LIKE ?", "%#{params[:user]}%") if params[:user].present?
|
||||||
|
email_logs = email_logs.where("email_logs.to_address LIKE ?", "%#{params[:address]}%") if params[:address].present?
|
||||||
|
email_logs = email_logs.where("email_logs.email_type LIKE ?", "%#{params[:type]}%") if params[:type].present?
|
||||||
|
email_logs = email_logs.where("email_logs.reply_key LIKE ?", "%#{params[:reply_key]}%") if params[:reply_key].present?
|
||||||
|
email_logs = email_logs.where("email_logs.skipped_reason LIKE ?", "%#{params[:reason]}%") if params[:reason].present?
|
||||||
|
email_logs.to_a
|
||||||
|
end
|
||||||
|
|
||||||
def delivery_settings
|
def delivery_settings
|
||||||
action_mailer_settings
|
action_mailer_settings
|
||||||
.reject { |k, v| k == :password }
|
.reject { |k, v| k == :password }
|
||||||
|
|
|
@ -1382,7 +1382,7 @@ en:
|
||||||
email:
|
email:
|
||||||
title: "Email"
|
title: "Email"
|
||||||
settings: "Settings"
|
settings: "Settings"
|
||||||
logs: "Logs"
|
sent: "Sent"
|
||||||
skipped: "Skipped"
|
skipped: "Skipped"
|
||||||
sent_at: "Sent At"
|
sent_at: "Sent At"
|
||||||
time: "Time"
|
time: "Time"
|
||||||
|
@ -1402,6 +1402,15 @@ en:
|
||||||
last_seen_user: "Last Seen User:"
|
last_seen_user: "Last Seen User:"
|
||||||
reply_key: "Reply Key"
|
reply_key: "Reply Key"
|
||||||
skip_reason: "Skip Reason"
|
skip_reason: "Skip Reason"
|
||||||
|
logs:
|
||||||
|
none: "No logs found."
|
||||||
|
filters:
|
||||||
|
title: "Filter"
|
||||||
|
user_placeholder: "username"
|
||||||
|
address_placeholder: "em@il.com"
|
||||||
|
type_placeholder: "digest, signup..."
|
||||||
|
reply_key_placeholder: ""
|
||||||
|
skip_reason_placeholder: "reason"
|
||||||
|
|
||||||
logs:
|
logs:
|
||||||
title: "Logs"
|
title: "Logs"
|
||||||
|
|
|
@ -67,7 +67,7 @@ Discourse::Application.routes.draw do
|
||||||
resources :email do
|
resources :email do
|
||||||
collection do
|
collection do
|
||||||
post "test"
|
post "test"
|
||||||
get "logs"
|
get "sent"
|
||||||
get "skipped"
|
get "skipped"
|
||||||
get "preview-digest" => "email#preview_digest"
|
get "preview-digest" => "email#preview_digest"
|
||||||
end
|
end
|
||||||
|
@ -120,7 +120,7 @@ Discourse::Application.routes.draw do
|
||||||
put "readonly" => "backups#readonly"
|
put "readonly" => "backups#readonly"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
get "memory_stats"=> "diagnostics#memory_stats", constraints: AdminConstraint.new
|
get "memory_stats"=> "diagnostics#memory_stats", constraints: AdminConstraint.new
|
||||||
|
|
||||||
end # admin namespace
|
end # admin namespace
|
||||||
|
|
|
@ -27,9 +27,18 @@ describe Admin::EmailController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context '.logs' do
|
context '.sent' do
|
||||||
before do
|
before do
|
||||||
xhr :get, :logs
|
xhr :get, :sent
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { response }
|
||||||
|
it { should be_success }
|
||||||
|
end
|
||||||
|
|
||||||
|
context '.skipped' do
|
||||||
|
before do
|
||||||
|
xhr :get, :skipped
|
||||||
end
|
end
|
||||||
|
|
||||||
subject { response }
|
subject { response }
|
||||||
|
|
Loading…
Reference in a new issue