rails_email_preview 0.2.21 → 0.2.22
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 +8 -4
- data/README.md +71 -57
- data/Rakefile +15 -0
- data/app/assets/stylesheets/rails_email_preview/_layout.css.sass +0 -8
- data/app/controllers/rails_email_preview/application_controller.rb +14 -0
- data/app/controllers/rails_email_preview/emails_controller.rb +130 -92
- data/app/helpers/rails_email_preview/emails_helper.rb +26 -37
- data/app/models/rails_email_preview/preview.rb +16 -6
- data/app/presenters/rails_email_preview/preview_list_presenter.rb +36 -0
- data/app/views/integrations/cms/_customize_cms_for_rails_email_preview.html.slim +16 -6
- data/app/views/layouts/rails_email_preview/email.html.slim +3 -1
- data/app/views/rails_email_preview/emails/_email_iframe.html.slim +63 -24
- data/app/views/rails_email_preview/emails/_format_nav.html.slim +2 -2
- data/app/views/rails_email_preview/emails/_headers.html.slim +2 -2
- data/app/views/rails_email_preview/emails/_i18n_nav.html.slim +3 -4
- data/app/views/rails_email_preview/emails/_send_form.html.slim +3 -3
- data/app/views/rails_email_preview/emails/index.html.slim +10 -7
- data/app/views/rails_email_preview/emails/show.html.slim +11 -11
- data/config/i18n-tasks.yml +5 -4
- data/config/locales/de.yml +11 -7
- data/config/locales/en.yml +10 -4
- data/config/locales/ru.yml +49 -0
- data/config/routes.rb +19 -9
- data/lib/rails_email_preview.rb +1 -1
- data/lib/rails_email_preview/version.rb +1 -1
- metadata +7 -6
- data/app/views/rails_email_preview/emails/show_body.html.slim +0 -1
@@ -1,19 +1,19 @@
|
|
1
1
|
module RailsEmailPreview::EmailsHelper
|
2
2
|
|
3
|
-
|
3
|
+
FORMAT_LABELS = { 'html' => 'HTML', 'plain' => 'Text', 'raw' => 'Raw'}
|
4
4
|
|
5
5
|
def format_label(mime_type)
|
6
|
-
|
6
|
+
FORMAT_LABELS[mime_type]
|
7
7
|
end
|
8
8
|
|
9
9
|
def change_locale_attr(locale)
|
10
|
-
{href: rails_email_preview.
|
10
|
+
{href: rails_email_preview.rep_email_path(preview_params.merge(part_type: @part_type, email_locale: locale)),
|
11
11
|
class: rep_btn_class(@email_locale == locale.to_s)}
|
12
12
|
end
|
13
13
|
|
14
|
-
def change_format_attr(
|
15
|
-
{href: rails_email_preview.
|
16
|
-
class: rep_btn_class(@part_type ==
|
14
|
+
def change_format_attr(format)
|
15
|
+
{href: rails_email_preview.rep_email_path(preview_params.merge(part_type: format)),
|
16
|
+
class: rep_btn_class(@part_type == format)}
|
17
17
|
end
|
18
18
|
|
19
19
|
def locale_name(locale)
|
@@ -24,28 +24,27 @@ module RailsEmailPreview::EmailsHelper
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
|
27
|
+
def human_headers(mail, &block)
|
28
|
+
{t('rep.headers.subject') => mail.subject || '(no subject)',
|
29
|
+
t('rep.headers.from') => mail.from,
|
30
|
+
t('rep.headers.reply_to') => mail.reply_to,
|
31
|
+
t('rep.headers.to') => mail.to,
|
32
|
+
t('rep.headers.cc') => mail.cc,
|
33
|
+
t('rep.headers.bcc') => mail.bcc,
|
34
|
+
t('rep.headers.attachments') => attachment_links(mail)
|
35
|
+
}.each do |name, value|
|
36
|
+
block.call(name, format_header_value(value)) unless value.blank?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def attachment_links(mail)
|
41
|
+
mail.attachments.map do |attachment|
|
29
42
|
url = rails_email_preview.rep_raw_email_attachment_path(params[:preview_id], attachment.filename)
|
30
43
|
link_to(attachment.filename, url)
|
31
44
|
end.join('').html_safe
|
32
45
|
end
|
33
46
|
|
34
|
-
def
|
35
|
-
I18n.with_locale @email_locale do
|
36
|
-
{
|
37
|
-
'Subject' => @mail.subject || '(no subject)',
|
38
|
-
'From' => @mail.from,
|
39
|
-
'Reply to' => @mail.reply_to,
|
40
|
-
'To' => @mail.to,
|
41
|
-
'CC' => @mail.cc,
|
42
|
-
'BCC' => @mail.bcc,
|
43
|
-
'Attachments' => attachment_links
|
44
|
-
}.delete_if { |k, v| v.blank? }
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def format_header(value)
|
47
|
+
def format_header_value(value)
|
49
48
|
if value.is_a?(Array)
|
50
49
|
value.map(&:to_s) * ', '
|
51
50
|
else
|
@@ -53,25 +52,15 @@ module RailsEmailPreview::EmailsHelper
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
|
-
def split_in_halves(elements, &weight)
|
57
|
-
tot_w = elements.map(&weight).sum
|
58
|
-
cols = [elements.dup, []]
|
59
|
-
col2_w = 0
|
60
|
-
cols[0].reverse_each do |cl|
|
61
|
-
n = weight.call(cl)
|
62
|
-
break if col2_w + n > tot_w / 2
|
63
|
-
col2_w += n
|
64
|
-
cols[1] << cols[0].pop
|
65
|
-
end
|
66
|
-
cols[1].reverse!
|
67
|
-
cols
|
68
|
-
end
|
69
|
-
|
70
55
|
# style
|
71
56
|
def rep_style
|
72
57
|
RailsEmailPreview.style
|
73
58
|
end
|
74
59
|
|
60
|
+
def preview_params
|
61
|
+
params.except(*request.path_parameters.keys)
|
62
|
+
end
|
63
|
+
|
75
64
|
def rep_btn_class(active = false)
|
76
65
|
rep_style[:"btn_#{active ? 'active' : 'default'}_class"]
|
77
66
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module RailsEmailPreview
|
2
|
-
#
|
2
|
+
# Preview for one mailer method
|
3
3
|
class Preview
|
4
4
|
attr_accessor :id, :preview_class_name, :preview_method
|
5
5
|
|
@@ -12,11 +12,14 @@ module RailsEmailPreview
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def formats
|
15
|
-
%w(
|
15
|
+
%w(html plain raw)
|
16
16
|
end
|
17
17
|
|
18
|
-
def preview_mail(run_hooks = false)
|
19
|
-
preview_class_name.constantize.new
|
18
|
+
def preview_mail(run_hooks = false, search_query_params = {})
|
19
|
+
preview_instance = preview_class_name.constantize.new
|
20
|
+
setup_instance_variables(preview_instance, search_query_params)
|
21
|
+
|
22
|
+
preview_instance.send(preview_method).tap do |mail|
|
20
23
|
RailsEmailPreview.run_before_render(mail, self) if run_hooks
|
21
24
|
end
|
22
25
|
end
|
@@ -40,7 +43,7 @@ module RailsEmailPreview
|
|
40
43
|
|
41
44
|
alias_method :[], :find
|
42
45
|
|
43
|
-
attr_reader :all
|
46
|
+
attr_reader :all
|
44
47
|
|
45
48
|
def mail_methods(mailer)
|
46
49
|
mailer.public_instance_methods(false).map(&:to_s)
|
@@ -66,7 +69,14 @@ module RailsEmailPreview
|
|
66
69
|
end
|
67
70
|
end
|
68
71
|
@all.sort_by!(&:name)
|
69
|
-
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def setup_instance_variables(object, params)
|
78
|
+
unless params.empty?
|
79
|
+
params.each { |k,v| object.instance_variable_set("@#{k}", v) }
|
70
80
|
end
|
71
81
|
end
|
72
82
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module RailsEmailPreview
|
2
|
+
class PreviewListPresenter
|
3
|
+
attr_reader :previews
|
4
|
+
|
5
|
+
def initialize(previews)
|
6
|
+
@previews = previews
|
7
|
+
end
|
8
|
+
|
9
|
+
def columns(&block)
|
10
|
+
split_in_halves(groups) { |_k, v| v.length }.each do |column_groups|
|
11
|
+
block.call(column_groups)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def groups
|
16
|
+
@groups ||= by_class_name.inject({}) do |h, (_class_name, previews)|
|
17
|
+
h.update previews.first.group_name => previews
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def split_in_halves(xs, &weight)
|
24
|
+
xs = xs.to_a
|
25
|
+
ws = xs.map(&weight)
|
26
|
+
col_w = ws.sum / 2
|
27
|
+
cur_w = 0
|
28
|
+
mid = ws.find_index { |w| (cur_w += w) >= col_w + w }
|
29
|
+
[xs.first(mid), xs.from(mid)]
|
30
|
+
end
|
31
|
+
|
32
|
+
def by_class_name
|
33
|
+
@by_class_name ||= previews.group_by(&:preview_class_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -3,14 +3,14 @@ ruby:
|
|
3
3
|
adapter = ::RailsEmailPreview::Integrations::ComfortableMexicanSofa
|
4
4
|
snippet = @snippet || (adapter.cms_snippet_class === @record && @record)
|
5
5
|
if snippet && (p = adapter.rep_email_params_from_snippet(snippet))
|
6
|
-
show_url = rails_email_preview.rep_raw_email_url(p
|
6
|
+
show_url = rails_email_preview.rep_raw_email_url(p)
|
7
7
|
end
|
8
8
|
customize_form = show_url.present? || snippet && !snippet.persisted?
|
9
9
|
|
10
10
|
- if customize_form
|
11
11
|
javascript:
|
12
|
-
|
13
|
-
|
12
|
+
if (window.parent && window.parent.rep && (new RegExp('#{rails_email_preview.rep_root_path}')).test(parent.location.href)) {
|
13
|
+
jQuery(function($) {
|
14
14
|
// Hide nav:
|
15
15
|
$('.left-column,.right-column').hide();
|
16
16
|
$('.center-column').css('margin', 0);
|
@@ -18,6 +18,9 @@ ruby:
|
|
18
18
|
var showUrl = '#{show_url}';
|
19
19
|
|
20
20
|
if (showUrl) {
|
21
|
+
var parentParams = parent.location.search;
|
22
|
+
if (!/\?/.test(showUrl)) showUrl += '?';
|
23
|
+
showUrl = showUrl.replace(/\?.*$/, parentParams);
|
21
24
|
$('.page-header h2').html(
|
22
25
|
"#{t '.edit_email'}" + " <a class='btn btn-primary' href='" + showUrl + "'>#{t '.view_link'}</a>");
|
23
26
|
}
|
@@ -31,9 +34,16 @@ ruby:
|
|
31
34
|
|
32
35
|
// hide identifier and categories
|
33
36
|
control('identifier').hide();
|
34
|
-
control('category_ids').hide()
|
37
|
+
control('category_ids').hide();
|
35
38
|
|
36
39
|
// Do not mess with identifier
|
37
40
|
$('[data-slug]').removeAttr('data-slug');
|
38
|
-
}
|
39
|
-
|
41
|
+
});
|
42
|
+
|
43
|
+
// Schedule headers view refresh on next load
|
44
|
+
jQuery(window).on('load', function() {
|
45
|
+
setTimeout(function(){
|
46
|
+
window.parent.rep.fetchHeadersOnNextLoad = true;
|
47
|
+
})
|
48
|
+
});
|
49
|
+
}
|
@@ -7,9 +7,11 @@ html
|
|
7
7
|
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
8
8
|
word-break: break-word;
|
9
9
|
}
|
10
|
+
body {
|
11
|
+
background-color:white;
|
12
|
+
}
|
10
13
|
|
11
14
|
= yield(:head)
|
12
15
|
body
|
13
16
|
#content.container
|
14
|
-
= render 'layouts/rails_email_preview/flash_notices'
|
15
17
|
= yield
|
@@ -1,31 +1,70 @@
|
|
1
1
|
javascript:
|
2
|
-
(function(doc){
|
3
|
-
var rep = window
|
4
|
-
resizeIframe: function(id) {
|
5
|
-
var el = doc.getElementById(id);
|
6
|
-
if (!el) return;
|
7
|
-
var w = el.parentNode.clientWidth,
|
8
|
-
h = el.contentWindow.document.body.scrollHeight;
|
9
|
-
el.height = (h) + "px";
|
10
|
-
el.width = (w) + "px";
|
11
|
-
},
|
12
|
-
iframeLoad: function(id){
|
13
|
-
document.getElementById('loading-el').style.display = 'none';
|
14
|
-
setTimeout(function() { rep.resizeIframe(id); rep.loaded = true; });
|
15
|
-
},
|
16
|
-
resizeAttached: false
|
17
|
-
};
|
2
|
+
(function(doc) {
|
3
|
+
var rep = window['rep'] || (window['rep'] = { resizeAttached: false });
|
18
4
|
rep.loaded = false;
|
5
|
+
|
6
|
+
function findIframe() {
|
7
|
+
return doc.getElementById('src-iframe');
|
8
|
+
}
|
9
|
+
|
10
|
+
function resizeIframe() {
|
11
|
+
var el = findIframe();
|
12
|
+
if (!el) {
|
13
|
+
rep.loaded = false;
|
14
|
+
return;
|
15
|
+
}
|
16
|
+
var iframeBody = el.contentWindow.document.body;
|
17
|
+
if (iframeBody) {
|
18
|
+
el.style.height = (getBodyHeight(iframeBody)) + "px";
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
function getBodyHeight(body) {
|
23
|
+
// browser compat
|
24
|
+
return Math.max(body.scrollHeight, body.offsetHeight, body.clientHeight);
|
25
|
+
}
|
26
|
+
|
27
|
+
// This is only called back once the iframe has finished loading everything, including images
|
28
|
+
rep.iframeOnLoad = function() {
|
29
|
+
rep.loaded = true;
|
30
|
+
resizeIframe();
|
31
|
+
|
32
|
+
// CMS refresh headers hook
|
33
|
+
if (rep.fetchHeadersOnNextLoad) {
|
34
|
+
rep.fetchHeadersOnNextLoad = false;
|
35
|
+
var headersView = doc.getElementById('email-headers'),
|
36
|
+
xhr = new XMLHttpRequest();
|
37
|
+
xhr.open('GET', headersView.getAttribute('data-url'), true);
|
38
|
+
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
39
|
+
xhr.send(null);
|
40
|
+
xhr.onreadystatechange = function() {
|
41
|
+
if (xhr.readyState === 4) {
|
42
|
+
headersView.innerHTML = xhr.responseText;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
};
|
47
|
+
|
48
|
+
// Resize on window resize
|
19
49
|
if (!rep.resizeAttached) {
|
20
50
|
window.addEventListener('resize', function() {
|
21
|
-
if (rep.loaded)
|
22
|
-
});
|
51
|
+
if (rep.loaded) resizeIframe();
|
52
|
+
}, true);
|
23
53
|
rep.resizeAttached = true
|
24
54
|
}
|
25
|
-
})(document)
|
26
55
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
56
|
+
// Only show progress bar after some time to avoid flashing
|
57
|
+
setTimeout(function() {
|
58
|
+
doc.getElementById('email-progress-bar').style.display = 'block';
|
59
|
+
}, 200);
|
60
|
+
})(document);
|
61
|
+
|
62
|
+
|
63
|
+
div style='min-height: 400px; position: relative'
|
64
|
+
#email-progress-bar.progress style='display: none; position: absolute; z-index: -1; width: 100%; text-align: center'
|
65
|
+
.progress-bar.progress-bar-striped.active style='width:100%'
|
66
|
+
= t 'rep.base.loading'
|
67
|
+
|
68
|
+
iframe#src-iframe[
|
69
|
+
srcdoc=(@mail_body_html.to_str) seamless="seamless" onload='rep.iframeOnLoad()'
|
70
|
+
style='width:100%;border:none;padding:0;margin:0;height:0;']
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
1
|
+
span class=rep_btn_group_class
|
2
2
|
- @preview.locales.each do |locale|
|
3
|
-
|
4
|
-
|
5
|
-
= locale_name(locale)
|
3
|
+
a *change_locale_attr(locale)
|
4
|
+
= locale_name locale
|
@@ -1,6 +1,6 @@
|
|
1
|
-
.
|
2
|
-
= form_tag rails_email_preview.rep_test_deliver_url, method: :post do
|
1
|
+
.rep-send-to-wrapper style='max-width: 290px; display: inline-block'
|
2
|
+
= form_tag rails_email_preview.rep_test_deliver_url(params: preview_params), method: :post do
|
3
3
|
= hidden_field_tag :email_locale, @email_locale
|
4
|
-
.input-group
|
4
|
+
span.input-group.input-group-sm
|
5
5
|
span.input-group-btn: button.btn.btn-danger type='submit' data-confirm=t('.send_are_you_sure') #{t('.send_btn')}
|
6
6
|
= text_field_tag :recipient_email, '', class: 'form-control', placeholder: t('.send_recipient_placeholder')
|
@@ -1,17 +1,20 @@
|
|
1
|
+
ruby:
|
2
|
+
list = @list
|
3
|
+
previews = @previews
|
4
|
+
|
1
5
|
h1 = t '.list_title'
|
2
6
|
|
3
7
|
div class=rep_row_class
|
4
|
-
-
|
8
|
+
- list.columns do |groups|
|
5
9
|
div class=rep_col_class(6)
|
6
|
-
-
|
7
|
-
h2 =
|
10
|
+
- groups.each do |title, group_previews|
|
11
|
+
h2 = title
|
8
12
|
div class=rep_style[:list_group_class]
|
9
|
-
-
|
10
|
-
a class=rep_style[:list_group_item_class] href=rails_email_preview.
|
13
|
+
- group_previews.each do |p|
|
14
|
+
a class=rep_style[:list_group_item_class] href=rails_email_preview.rep_email_path(preview_id: p.id, email_locale: @email_locale)
|
11
15
|
= p.method_name
|
12
|
-
|
13
16
|
hr
|
14
17
|
p.text-center.text-small.text-info
|
15
|
-
| #{t 'rep.base.email', count:
|
18
|
+
| #{t 'rep.base.email', count: previews.length} #{t 'rep.base.in'} #{t 'rep.base.mailer', count: list.groups.length }
|
16
19
|
br
|
17
20
|
a href="https://github.com/glebm/rails_email_preview" target='_blank' REP #{RailsEmailPreview::VERSION}
|
@@ -2,24 +2,24 @@
|
|
2
2
|
div class=rep_row_class
|
3
3
|
.pull-left
|
4
4
|
ul.breadcrumb
|
5
|
-
li: a href=rails_email_preview.
|
6
|
-
li.active: a href=(request.
|
5
|
+
li: a href=rails_email_preview.rep_emails_path(email_locale: @email_locale) #{t '.breadcrumb_list'}
|
6
|
+
li.active: a href=(request.path) = @preview.name
|
7
7
|
|
8
8
|
div class=rep_style[:panel_class]
|
9
9
|
div class=rep_style[:panel_body_class]
|
10
10
|
div class=rep_style[:row_class]
|
11
11
|
-# From, To, Subject and other headers
|
12
|
-
|
13
|
-
= render 'rails_email_preview/emails/headers'
|
12
|
+
#email-headers data-url=rails_email_preview.rep_email_headers_path(preview_params) class=rep_col_class(8)
|
13
|
+
= render 'rails_email_preview/emails/headers', mail: @mail
|
14
14
|
-# Locale, format and actions
|
15
|
-
|
16
|
-
|
15
|
+
.text-right class=rep_col_class(4)
|
16
|
+
.rep-email-options.text-right
|
17
17
|
- if I18n.available_locales.length > 1
|
18
|
-
|
18
|
+
p= render 'rails_email_preview/emails/i18n_nav'
|
19
|
+
p= render 'rails_email_preview/emails/format_nav'
|
19
20
|
- if RailsEmailPreview.enable_send_email
|
20
|
-
|
21
|
-
|
21
|
+
= render 'rails_email_preview/emails/send_form'
|
22
|
+
|
22
23
|
|
23
24
|
-# actual email content, rendered in an iframe to prevent browser styles from interfering
|
24
|
-
|
25
|
-
= render 'rails_email_preview/emails/email_iframe'
|
25
|
+
= render 'rails_email_preview/emails/email_iframe'
|