studio-engine 0.37.0 → 0.39.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 +4 -4
- data/CHANGELOG.md +93 -2
- data/README.md +53 -23
- data/app/controllers/studio/email_images_controller.rb +4 -4
- data/app/controllers/studio/emails_controller.rb +55 -11
- data/app/mailers/user_mailer.rb +1 -1
- data/app/models/image_cache.rb +1 -1
- data/app/services/studio/email_catalog.rb +450 -0
- data/app/services/studio/email_image.rb +56 -317
- data/app/views/layouts/_navbar.html.erb +9 -7
- data/app/views/layouts/branded_mailer.html.erb +1 -1
- data/app/views/studio/banners/_app_banner.html.erb +6 -3
- data/app/views/studio/banners/_stack.html.erb +34 -50
- data/app/views/studio/email_images/index.html.erb +2 -2
- data/app/views/studio/emails/_row.html.erb +8 -3
- data/app/views/studio/emails/index.html.erb +4 -4
- data/app/views/studio/emails/show.html.erb +91 -0
- data/lib/studio/version.rb +1 -1
- data/lib/studio.rb +10 -3
- metadata +3 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<%# admin/emails/:key — one email, previewed live.
|
|
2
|
+
|
|
3
|
+
A bare content wrapper like the index, so it renders inside each host's
|
|
4
|
+
layout. Lifted from turf-monster's admin/emails/show (the prior art this
|
|
5
|
+
work folds into the engine) and given the banner half: the same iframe over
|
|
6
|
+
the real rendered email, plus what artwork is riding on top of it and where
|
|
7
|
+
that artwork came from. %>
|
|
8
|
+
<% content_for(:title) { @entry.label } %>
|
|
9
|
+
<%
|
|
10
|
+
source = Studio::EmailCatalog.source(@entry.key)
|
|
11
|
+
banner_url = Studio::EmailCatalog.preview_url(@entry.key)
|
|
12
|
+
aspect = Studio::EmailCatalog::ASPECT_RATIO
|
|
13
|
+
|
|
14
|
+
badge_class, badge_label =
|
|
15
|
+
case source
|
|
16
|
+
when :app then ["badge bg-success/10 text-success border-success/30", "#{Studio.app_name}'s own"]
|
|
17
|
+
when :default then ["badge bg-inset text-muted border-subtle", "Inherited default"]
|
|
18
|
+
else ["badge bg-warning/10 text-warning border-warning/30", "No image"]
|
|
19
|
+
end
|
|
20
|
+
%>
|
|
21
|
+
<div class="max-w-5xl mx-auto px-4 pb-16">
|
|
22
|
+
<header class="pt-8 pb-5">
|
|
23
|
+
<%= link_to "← All emails", admin_emails_path,
|
|
24
|
+
class: "text-sm text-muted hover:text-heading underline underline-offset-2" %>
|
|
25
|
+
<h1 class="text-3xl font-bold text-heading mt-2"><%= @entry.label %></h1>
|
|
26
|
+
|
|
27
|
+
<div class="flex flex-wrap items-center gap-2 mt-3">
|
|
28
|
+
<span class="badge <%= @entry.marketing? ? "bg-primary/10 text-primary border-primary/30" : "bg-inset text-muted border-subtle" %> whitespace-nowrap">
|
|
29
|
+
<%= @entry.type.to_s.titleize %>
|
|
30
|
+
</span>
|
|
31
|
+
<span class="<%= badge_class %> whitespace-nowrap"><%= badge_label %></span>
|
|
32
|
+
<span class="font-mono text-2xs text-muted"><%= @entry.key %></span>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<% if @entry.description.present? %>
|
|
36
|
+
<p class="text-body max-w-2xl mt-3"><%= @entry.description %></p>
|
|
37
|
+
<% end %>
|
|
38
|
+
|
|
39
|
+
<% if @subject.present? %>
|
|
40
|
+
<p class="text-sm text-muted mt-2">
|
|
41
|
+
Subject: <strong class="text-heading"><%= @subject %></strong>
|
|
42
|
+
</p>
|
|
43
|
+
<% end %>
|
|
44
|
+
</header>
|
|
45
|
+
|
|
46
|
+
<%# The banner riding on top of this email, and where it came from. %>
|
|
47
|
+
<section class="card p-4 mb-6">
|
|
48
|
+
<p class="label-upper mb-3">Banner</p>
|
|
49
|
+
<div class="rounded-lg overflow-hidden border border-subtle max-w-md"
|
|
50
|
+
style="aspect-ratio: <%= aspect %>; background: linear-gradient(135deg, var(--color-primary-700), var(--color-primary-900));">
|
|
51
|
+
<% if banner_url %>
|
|
52
|
+
<%= image_tag banner_url, class: "w-full h-full object-cover",
|
|
53
|
+
alt: "#{@entry.label} email banner" %>
|
|
54
|
+
<% else %>
|
|
55
|
+
<div class="w-full h-full flex items-center justify-center text-xs text-white/80 text-center px-4">
|
|
56
|
+
This email sends without a banner.
|
|
57
|
+
</div>
|
|
58
|
+
<% end %>
|
|
59
|
+
</div>
|
|
60
|
+
<p class="text-sm text-muted mt-3">
|
|
61
|
+
<% if @uploads_available %>
|
|
62
|
+
Change it on the <%= link_to "emails list", admin_emails_path, class: "underline underline-offset-2" %>.
|
|
63
|
+
<% else %>
|
|
64
|
+
<%= Studio.app_name %> has no object storage configured, so this image can be
|
|
65
|
+
viewed but not replaced yet.
|
|
66
|
+
<% end %>
|
|
67
|
+
</p>
|
|
68
|
+
</section>
|
|
69
|
+
|
|
70
|
+
<%# The email itself. An iframe because the response IS an email document —
|
|
71
|
+
its own <html>, its own table layout, and no business inheriting the admin
|
|
72
|
+
page's stylesheet. %>
|
|
73
|
+
<section class="card p-3 bg-inset">
|
|
74
|
+
<p class="label-upper mb-3 px-1">Preview</p>
|
|
75
|
+
<% if @entry.previewable? %>
|
|
76
|
+
<iframe src="<%= admin_email_raw_path(@entry.key) %>"
|
|
77
|
+
style="width:100%;height:780px;border:0;border-radius:8px;background:#ffffff;"
|
|
78
|
+
title="<%= @entry.label %> preview"></iframe>
|
|
79
|
+
<% else %>
|
|
80
|
+
<div class="px-3 pb-4">
|
|
81
|
+
<p class="text-sm text-body">
|
|
82
|
+
No preview is registered for this email. Pass a <code class="font-mono text-2xs bg-surface px-1.5 py-0.5 rounded">preview:</code>
|
|
83
|
+
callable when registering it — anything that returns a Mail — and it renders here.
|
|
84
|
+
</p>
|
|
85
|
+
</div>
|
|
86
|
+
<% end %>
|
|
87
|
+
<% if @preview_error.present? %>
|
|
88
|
+
<p class="text-2xs text-danger mt-2 px-1 font-mono break-all"><%= @preview_error %></p>
|
|
89
|
+
<% end %>
|
|
90
|
+
</section>
|
|
91
|
+
</div>
|
data/lib/studio/version.rb
CHANGED
data/lib/studio.rb
CHANGED
|
@@ -558,10 +558,17 @@ module Studio
|
|
|
558
558
|
# Studio::EmailImage.resolved_url — so an app is branded on day one whether
|
|
559
559
|
# or not it draws the page.
|
|
560
560
|
if Studio.draw_admin_emails_routes
|
|
561
|
-
get "admin/emails",
|
|
562
|
-
|
|
561
|
+
get "admin/emails", to: "studio/emails#index", as: :admin_emails
|
|
562
|
+
# /raw is drawn BEFORE /:key so "raw" is never captured as a key.
|
|
563
|
+
get "admin/emails/:key/raw", to: "studio/emails#raw", as: :admin_email_raw,
|
|
563
564
|
constraints: { key: /[a-z0-9_]+/ }
|
|
564
|
-
|
|
565
|
+
get "admin/emails/:key", to: "studio/emails#show", as: :admin_email,
|
|
566
|
+
constraints: { key: /[a-z0-9_]+/ }
|
|
567
|
+
# Same path, same helper (admin_email_path) — a named route only needs
|
|
568
|
+
# to be declared once per name, and these share the show route's URL.
|
|
569
|
+
patch "admin/emails/:key", to: "studio/emails#update",
|
|
570
|
+
constraints: { key: /[a-z0-9_]+/ }
|
|
571
|
+
delete "admin/emails/:key", to: "studio/emails#destroy",
|
|
565
572
|
constraints: { key: /[a-z0-9_]+/ }
|
|
566
573
|
end
|
|
567
574
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: studio-engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.39.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex McRitchie
|
|
@@ -223,6 +223,7 @@ files:
|
|
|
223
223
|
- app/models/studio/model_page.rb
|
|
224
224
|
- app/models/theme_setting.rb
|
|
225
225
|
- app/services/google_oauth_validator.rb
|
|
226
|
+
- app/services/studio/email_catalog.rb
|
|
226
227
|
- app/services/studio/email_image.rb
|
|
227
228
|
- app/views/components/_admin_dropdown.html.erb
|
|
228
229
|
- app/views/components/_avatar.html.erb
|
|
@@ -276,6 +277,7 @@ files:
|
|
|
276
277
|
- app/views/studio/email_images/index.html.erb
|
|
277
278
|
- app/views/studio/emails/_row.html.erb
|
|
278
279
|
- app/views/studio/emails/index.html.erb
|
|
280
|
+
- app/views/studio/emails/show.html.erb
|
|
279
281
|
- app/views/studio/links/confirm.html.erb
|
|
280
282
|
- app/views/studio/local_emails/index.html.erb
|
|
281
283
|
- app/views/studio/modals/_crop_photo.html.erb
|