spree_emails 5.5.3 → 5.6.0.rc2

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -14
  3. data/app/mailers/spree/customer_mailer.rb +21 -0
  4. data/app/mailers/spree/newsletter_mailer.rb +6 -15
  5. data/app/mailers/spree/order_mailer.rb +16 -10
  6. data/app/mailers/spree/reimbursement_mailer.rb +4 -3
  7. data/app/mailers/spree/shipment_mailer.rb +4 -3
  8. data/app/subscribers/spree/customer_email_subscriber.rb +30 -0
  9. data/app/views/spree/customer_mailer/password_reset_email.html.erb +9 -25
  10. data/app/views/spree/newsletter_mailer/email_confirmation.html.erb +11 -22
  11. data/app/views/spree/order_mailer/cancel_email.html.erb +11 -23
  12. data/app/views/spree/order_mailer/confirm_email.html.erb +12 -23
  13. data/app/views/spree/order_mailer/payment_link_email.html.erb +8 -13
  14. data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +11 -23
  15. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +44 -50
  16. data/app/views/spree/shared/_item_thumbnail_link.html.erb +7 -0
  17. data/app/views/spree/shared/_order_summary_section.html.erb +15 -0
  18. data/app/views/spree/shared/_purchased_items_table.html.erb +20 -63
  19. data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +3 -13
  20. data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +19 -24
  21. data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +3 -13
  22. data/app/views/spree/shared/purchased_items_table/_summary_row.html.erb +14 -0
  23. data/app/views/spree/shared/purchased_items_table/_total.html.erb +4 -13
  24. data/app/views/spree/shipment_mailer/shipped_email.html.erb +19 -35
  25. data/lib/generators/spree/emails/install/install_generator.rb +6 -14
  26. data/lib/spree/emails/engine.rb +10 -1
  27. data/lib/spree/emails/previews/customer_preview.rb +14 -0
  28. data/lib/spree/emails/previews/newsletter_preview.rb +30 -0
  29. data/lib/spree/emails/previews/order_preview.rb +28 -0
  30. data/lib/spree/emails/previews/reimbursement_preview.rb +12 -0
  31. data/lib/spree/emails/previews/shipment_preview.rb +12 -0
  32. metadata +16 -10
  33. data/lib/generators/spree/emails/install/templates/mailers/previews/order_preview.rb +0 -13
  34. data/lib/generators/spree/emails/install/templates/mailers/previews/reimbursement_preview.rb +0 -5
  35. data/lib/generators/spree/emails/install/templates/mailers/previews/shipment_preview.rb +0 -7
  36. data/lib/generators/spree/emails/install/templates/mailers/previews/user_preview.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f45895dba90121f176de0b3f18b6714d9703334a2bc9550c3e4381350579398
4
- data.tar.gz: 36bd73f12429bea0eb3823f419b55c113d2a99ec8d24397e5744c9f290f4f195
3
+ metadata.gz: 67fb3d4d12386b0b96c47be15e652c59e9f19ac7a64330afe7ccb9b0c4103d9c
4
+ data.tar.gz: 801359f2dfc3e9d9fd6d40edaf20a37c2811b2a81a43e57e73d5a26da7c36883
5
5
  SHA512:
6
- metadata.gz: a00191867bb2c160d53283f47fc7db4d656a9928f378e0a42c9f136a878a7b8a602017ae646704f8d3497884b8d3b7d4ed2a48b0f8f90711a4526c1515f1860a
7
- data.tar.gz: 23ed76d697d4767051635e6fb6fbd7fe2370f396850c3002b2d2fea91215ddec6e1d3a38a9e585a2b643f133d273dd12ae8678085d1b18d2a385902c3622f993
6
+ metadata.gz: 3548d009080808abf54f55de6acbf287beb4edd07c9e2262dad88cc832cccde9c107c69e3a8c942fa104358f590c00a8e469ab50da555304265b684115fa1042
7
+ data.tar.gz: 56ff4023bee3cbb86eeb0bfb833ac9932ec2034be697495263589e17a0515a4f4c15b9df887e59c3791dbd6deedb0cbe1be3b2b3270445bf54fb3474e0ed8389
data/README.md CHANGED
@@ -188,23 +188,15 @@ bundle remove spree_emails
188
188
 
189
189
  If you prefer to use a third-party email service like Klaviyo for transactional emails, you can use the [spree_klaviyo](https://github.com/spree/spree_klaviyo) extension. This allows you to leverage Klaviyo's email marketing platform for order confirmations, shipment notifications, and other transactional emails.
190
190
 
191
- ## Testing
191
+ ## Previewing emails
192
192
 
193
- Preview emails in development:
193
+ [ActionMailer previews](https://guides.rubyonrails.org/action_mailer_basics.html#previewing-and-testing-mailers) for every transactional email ship with this gem and are served automatically in development — no setup required. With a seeded development database, start the server and visit:
194
194
 
195
- ```ruby
196
- # test/mailers/previews/spree/order_mailer_preview.rb
197
- module Spree
198
- class OrderMailerPreview < ActionMailer::Preview
199
- def confirm_email
200
- order = Spree::Order.complete.last
201
- Spree::OrderMailer.confirm_email(order)
202
- end
203
- end
204
- end
205
- ```
195
+ `http://localhost:3000/rails/mailers`
206
196
 
207
- Visit `http://localhost:3000/rails/mailers/spree/order_mailer/confirm_email`
197
+ for example `http://localhost:3000/rails/mailers/spree/order/confirm_email`.
198
+
199
+ ## Testing
208
200
 
209
201
  Run the test suite:
210
202
 
@@ -0,0 +1,21 @@
1
+ module Spree
2
+ class CustomerMailer < BaseMailer
3
+ # Password reset requested through the Store API (`customer.password_reset_requested`).
4
+ # The link goes to the validated redirect URL when the storefront supplied one,
5
+ # falling back to the store's storefront URL, with the reset token appended.
6
+ def password_reset_email(user, reset_token, store, redirect_url: nil)
7
+ @user = user
8
+ @current_store = store
9
+ base_url = redirect_url.presence || store.storefront_url
10
+ @reset_url = append_token(base_url, reset_token)
11
+
12
+ with_store_locale(store) do
13
+ mail(
14
+ to: user.email,
15
+ subject: "#{store.name} #{Spree.t('customer_mailer.password_reset_email.subject')}",
16
+ store_url: store.storefront_url
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
@@ -3,24 +3,15 @@ module Spree
3
3
  def email_confirmation(subscriber, redirect_url: nil)
4
4
  @subscriber = subscriber
5
5
  store = subscriber.store || Spree::Current.store || Spree::Store.default
6
+ # The shared header/footer and from address read current_store — set it
7
+ # to the subscriber's store so multi-store installs brand correctly.
8
+ @current_store = store
6
9
  base_url = redirect_url.presence || store.storefront_url
7
10
  @confirm_email_url = append_token(base_url, @subscriber.verification_token)
8
- mail(to: @subscriber.email, from: from_address, subject: Spree.t('newsletter_mailer.email_confirmation.subject'))
11
+ with_store_locale(store) do
12
+ mail(to: @subscriber.email, subject: Spree.t('newsletter_mailer.email_confirmation.subject'))
13
+ end
9
14
  end
10
15
 
11
- private
12
-
13
- # URI-based merge preserves existing query params and fragments so the token
14
- # doesn't get swallowed by a `#section` or clobber an existing `?source=`.
15
- def append_token(url, token)
16
- uri = URI.parse(url.to_s)
17
- params = URI.decode_www_form(uri.query || '')
18
- params << ['token', token.to_s]
19
- uri.query = URI.encode_www_form(params)
20
- uri.to_s
21
- rescue URI::InvalidURIError
22
- separator = url.include?('?') ? '&' : '?'
23
- "#{url}#{separator}token=#{CGI.escape(token.to_s)}"
24
- end
25
16
  end
26
17
  end
@@ -5,24 +5,28 @@ module Spree
5
5
  def confirm_email(order, resend = false)
6
6
  @order = order.respond_to?(:id) ? order : Spree::Order.find(order)
7
7
  current_store = @order.store
8
- subject = (resend ? "[#{Spree.t(:resend).upcase}] " : '')
9
- subject += "#{current_store.name} #{Spree.t('order_mailer.confirm_email.subject')} ##{@order.number}"
10
- mail(to: @order.email, from: from_address, subject: subject, store_url: current_store.storefront_url, reply_to: reply_to_address)
8
+ with_store_locale(current_store, @order.locale) do
9
+ subject = order_email_subject(current_store, Spree.t('order_mailer.confirm_email.subject'), @order.number, resend: resend)
10
+ mail(to: @order.email, subject: subject, store_url: current_store.storefront_url)
11
+ end
11
12
  end
12
13
 
13
14
  def store_owner_notification_email(order)
14
15
  @order = order.respond_to?(:id) ? order : Spree::Order.find(order)
15
16
  current_store = @order.store
16
- subject = Spree.t('order_mailer.store_owner_notification_email.subject', store_name: current_store.name)
17
- mail(to: current_store.new_order_notifications_email, from: from_address, subject: subject, store_url: current_store.storefront_url, reply_to: reply_to_address)
17
+ with_store_locale(current_store) do
18
+ subject = Spree.t('order_mailer.store_owner_notification_email.subject', store_name: current_store.name)
19
+ mail(to: current_store.new_order_notifications_email, subject: subject, store_url: current_store.storefront_url)
20
+ end
18
21
  end
19
22
 
20
23
  def cancel_email(order, resend = false)
21
24
  @order = order.respond_to?(:id) ? order : Spree::Order.find(order)
22
25
  current_store = @order.store
23
- subject = (resend ? "[#{Spree.t(:resend).upcase}] " : '')
24
- subject += "#{current_store.name} #{Spree.t('order_mailer.cancel_email.subject')} ##{@order.number}"
25
- mail(to: @order.email, from: from_address, subject: subject, store_url: current_store.storefront_url, reply_to: reply_to_address)
26
+ with_store_locale(current_store, @order.locale) do
27
+ subject = order_email_subject(current_store, Spree.t('order_mailer.cancel_email.subject'), @order.number, resend: resend)
28
+ mail(to: @order.email, subject: subject, store_url: current_store.storefront_url)
29
+ end
26
30
  end
27
31
 
28
32
  def payment_link_email(order_id)
@@ -30,8 +34,10 @@ module Spree
30
34
  @current_store = @order.store
31
35
  @checkout_payment_url = spree.checkout_state_url(@order.token, :payment, host: @current_store.storefront_url)
32
36
 
33
- mail(to: @order.email, from: from_address, subject: Spree.t('order_mailer.payment_link_email.subject', number: @order.number),
34
- store_url: @current_store.storefront_url, reply_to: reply_to_address)
37
+ with_store_locale(@current_store, @order.locale) do
38
+ mail(to: @order.email, subject: Spree.t('order_mailer.payment_link_email.subject', number: @order.number),
39
+ store_url: @current_store.storefront_url)
40
+ end
35
41
  end
36
42
  end
37
43
  end
@@ -6,9 +6,10 @@ module Spree
6
6
  @reimbursement = reimbursement.respond_to?(:id) ? reimbursement : Spree::Reimbursement.find(reimbursement)
7
7
  @order = @reimbursement.order
8
8
  current_store = @reimbursement.store || Spree::Store.default
9
- subject = (resend ? "[#{Spree.t(:resend).upcase}] " : '')
10
- subject += "#{current_store.name} #{Spree.t('reimbursement_mailer.reimbursement_email.subject')} ##{@order.number}"
11
- mail(to: @order.email, from: from_address, subject: subject, store_url: current_store.storefront_url, reply_to: reply_to_address)
9
+ with_store_locale(current_store, @order.locale) do
10
+ subject = order_email_subject(current_store, Spree.t('reimbursement_mailer.reimbursement_email.subject'), @order.number, resend: resend)
11
+ mail(to: @order.email, subject: subject, store_url: current_store.storefront_url)
12
+ end
12
13
  end
13
14
  end
14
15
  end
@@ -7,9 +7,10 @@ module Spree
7
7
  @shipment = shipment.respond_to?(:id) ? shipment : Spree::Shipment.find(shipment)
8
8
  @order = @shipment.order
9
9
  current_store = @shipment.store
10
- subject = (resend ? "[#{Spree.t(:resend).upcase}] " : '')
11
- subject += "#{current_store.name} #{Spree.t('shipment_mailer.shipped_email.subject')} ##{@order.number}"
12
- mail(to: @order.email, from: from_address, subject: subject, store_url: current_store.storefront_url, reply_to: reply_to_address)
10
+ with_store_locale(current_store, @order.locale) do
11
+ subject = order_email_subject(current_store, Spree.t('shipment_mailer.shipped_email.subject'), @order.number, resend: resend)
12
+ mail(to: @order.email, subject: subject, store_url: current_store.storefront_url)
13
+ end
13
14
  end
14
15
  end
15
16
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ class CustomerEmailSubscriber < Spree::Subscriber
5
+ subscribes_to 'customer.password_reset_requested'
6
+
7
+ def handle(event)
8
+ user = Spree.user_class.find_by(email: event.payload['email'])
9
+ return unless user
10
+
11
+ store = find_store(event)
12
+ return unless store.prefers_send_consumer_transactional_emails?
13
+
14
+ CustomerMailer.password_reset_email(
15
+ user,
16
+ event.payload['reset_token'],
17
+ store,
18
+ redirect_url: event.payload['redirect_url']
19
+ ).deliver_later
20
+ end
21
+
22
+ private
23
+
24
+ def find_store(event)
25
+ Spree::Store.find_by_prefix_id(event.payload['store_id']) ||
26
+ Spree::Current.store ||
27
+ Spree::Store.default
28
+ end
29
+ end
30
+ end
@@ -1,26 +1,10 @@
1
- <h1>
2
- <%= Spree.t('customer_mailer.password_reset_email.greeting', name: @user.first_name.presence || @user.email) %>
3
- </h1>
4
- <p>
5
- <%= Spree.t('customer_mailer.password_reset_email.instructions') %>
6
- </p>
7
- <% if @reset_url %>
8
- <table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
9
- <tr>
10
- <td align="center">
11
- <a href="<%= @reset_url %>" class="button" target="_blank">
12
- <%= Spree.t('customer_mailer.password_reset_email.action') %>
13
- </a>
14
- </td>
15
- </tr>
16
- </table>
1
+ <%= render layout: 'spree/shared/mailer_hero' do %>
2
+ <h1><%= Spree.t('customer_mailer.password_reset_email.action') %></h1>
3
+ <p class="greeting"><%= Spree.t('customer_mailer.password_reset_email.greeting', name: @user.first_name.presence || @user.email) %></p>
4
+ <p><%= Spree.t('customer_mailer.password_reset_email.instructions') %></p>
5
+ <% if @reset_url %>
6
+ <%= render 'spree/shared/mailer_button', url: @reset_url, label: Spree.t('customer_mailer.password_reset_email.action') %>
7
+ <% end %>
8
+ <p class="sub"><%= Spree.t('customer_mailer.password_reset_email.expiry_notice') %></p>
9
+ <p class="sub"><%= Spree.t('customer_mailer.password_reset_email.ignore_notice') %></p>
17
10
  <% end %>
18
- <p>
19
- <%= Spree.t('customer_mailer.password_reset_email.expiry_notice') %>
20
- </p>
21
- <p>
22
- <%= Spree.t('customer_mailer.password_reset_email.ignore_notice') %>
23
- </p>
24
- <p>
25
- <%= Spree.t('order_mailer.store_team', store_name: current_store.name) %>
26
- </p>
@@ -1,23 +1,12 @@
1
- <h1><%= Spree.t('newsletter_mailer.email_confirmation.dear_customer') %></h1>
2
-
3
- <p><%= Spree.t('newsletter_mailer.email_confirmation.instructions') %></p>
4
-
5
- <p class="align-center">
6
- <%= link_to Spree.t('newsletter_mailer.email_confirmation.verify_email_address_link'), @confirm_email_url, class: 'button' %>
7
- </p>
8
-
9
- <p>
10
- <%= Spree.t('newsletter_mailer.email_confirmation.message_copy_link') %>
11
- <br>
12
- <span style="word-break: break-all;">
1
+ <%= render layout: 'spree/shared/mailer_hero' do %>
2
+ <h1><%= Spree.t('newsletter_mailer.email_confirmation.subject') %></h1>
3
+ <p class="greeting"><%= Spree.t('newsletter_mailer.email_confirmation.dear_customer') %></p>
4
+ <p><%= Spree.t('newsletter_mailer.email_confirmation.instructions') %></p>
5
+ <%= render 'spree/shared/mailer_button', url: @confirm_email_url, label: Spree.t('newsletter_mailer.email_confirmation.verify_email_address_link') %>
6
+ <p class="sub">
7
+ <%= Spree.t('newsletter_mailer.email_confirmation.message_copy_link') %>
8
+ <br>
13
9
  <%= link_to @confirm_email_url, @confirm_email_url %>
14
- </span>
15
- </p>
16
-
17
- <p><%= Spree.t('newsletter_mailer.email_confirmation.ignore_disclaimer') %></p>
18
-
19
- <p>
20
- <%= Spree.t('newsletter_mailer.email_confirmation.thanks') %>
21
- <br />
22
- <%= Spree.t('newsletter_mailer.email_confirmation.store_team', store_name: current_store.name) %>
23
- </p>
10
+ </p>
11
+ <p class="sub"><%= Spree.t('newsletter_mailer.email_confirmation.ignore_disclaimer') %></p>
12
+ <% end %>
@@ -1,24 +1,12 @@
1
- <h1>
2
- <%= Spree.t('order_mailer.cancel_email.dear_customer', name: name_for(@order)) %>
3
- </h1>
4
- <p>
5
- <%= Spree.t('order_mailer.cancel_email.instructions') %>
6
- </p>
1
+ <%= render 'spree/shared/purchased_items_styles' %>
7
2
 
8
- <table class="purchase" role="presentation">
9
- <tr>
10
- <td>
11
- <h3> <%= Spree.t('order_mailer.cancel_email.order_summary_canceled', number: @order.number) %></h3>
12
- </td>
13
- </tr>
14
- <tr>
15
- <td colspan="2">
16
- <%= render 'spree/shared/purchased_items_table', line_items: @order.line_items, order: @order %>
17
- </td>
18
- </tr>
19
- </table>
20
- <p>
21
- <%= Spree.t('order_mailer.cancel_email.thanks') %>
22
- <br />
23
- <%= Spree.t('order_mailer.store_team', store_name: current_store.name) %>
24
- </p>
3
+ <%= render layout: 'spree/shared/mailer_hero' do %>
4
+ <h1><%= Spree.t('order_mailer.cancel_email.subject') %></h1>
5
+ <p class="greeting"><%= Spree.t('order_mailer.cancel_email.dear_customer', name: name_for(@order)) %></p>
6
+ <p><%= Spree.t('order_mailer.cancel_email.instructions') %></p>
7
+ <% end %>
8
+
9
+ <%= render 'spree/shared/order_summary_section',
10
+ heading: Spree.t('order_mailer.cancel_email.order_summary_canceled', number: @order.number),
11
+ line_items: @order.line_items,
12
+ order: @order %>
@@ -1,23 +1,12 @@
1
- <h1>
2
- <%= Spree.t('order_mailer.confirm_email.dear_customer', name: name_for(@order)) %>
3
- </h1>
4
- <p>
5
- <%= Spree.t('order_mailer.confirm_email.instructions') %>
6
- </p>
7
- <table class="purchase" role="presentation">
8
- <tr>
9
- <td>
10
- <h3><%= Spree.t('order_mailer.confirm_email.order_summary', number: @order.number) %></h3>
11
- </td>
12
- </tr>
13
- <tr>
14
- <td colspan="2">
15
- <%= render 'spree/shared/purchased_items_table', line_items: @order.line_items, order: @order %>
16
- </td>
17
- </tr>
18
- </table>
19
- <p>
20
- <%= Spree.t('order_mailer.confirm_email.thanks') %>
21
- <br />
22
- <%= Spree.t('order_mailer.store_team', store_name: current_store.name) %>
23
- </p>
1
+ <%= render 'spree/shared/purchased_items_styles' %>
2
+
3
+ <%= render layout: 'spree/shared/mailer_hero' do %>
4
+ <h1><%= Spree.t('order_mailer.confirm_email.subject') %></h1>
5
+ <p class="greeting"><%= Spree.t('order_mailer.confirm_email.dear_customer', name: name_for(@order)) %></p>
6
+ <p><%= Spree.t('order_mailer.confirm_email.instructions') %></p>
7
+ <% end %>
8
+
9
+ <%= render 'spree/shared/order_summary_section',
10
+ heading: Spree.t('order_mailer.confirm_email.order_summary', number: @order.number),
11
+ line_items: @order.line_items,
12
+ order: @order %>
@@ -1,16 +1,11 @@
1
- <h1>
2
- <%= Spree.t('order_mailer.confirm_email.dear_customer', name: name_for(@order)) %>
3
- </h1>
4
- <p>
5
- <%= Spree.t('order_mailer.payment_link_email.message', store_name: @current_store.name) %>
6
- </p>
7
- <p>
8
- <%= link_to Spree.t('order_mailer.payment_link_email.pay_for_order'), @checkout_payment_url, class: 'button' %>
9
- <p>
1
+ <%= render layout: 'spree/shared/mailer_hero' do %>
2
+ <h1><%= Spree.t('order_mailer.payment_link_email.subject', number: @order.number) %></h1>
3
+ <p class="greeting"><%= Spree.t('order_mailer.confirm_email.dear_customer', name: name_for(@order)) %></p>
4
+ <p><%= Spree.t('order_mailer.payment_link_email.message', store_name: @current_store.name) %></p>
5
+ <%= render 'spree/shared/mailer_button', url: @checkout_payment_url, label: Spree.t('order_mailer.payment_link_email.pay_for_order') %>
6
+ <p class="sub">
10
7
  <%= Spree.t('order_mailer.payment_link_email.message_copy_link') %>
11
8
  <br>
12
- <span style="word-break: break-all;">
13
- <%= link_to @checkout_payment_url, @checkout_payment_url %>
14
- </span>
9
+ <%= link_to @checkout_payment_url, @checkout_payment_url %>
15
10
  </p>
16
- </p>
11
+ <% end %>
@@ -1,23 +1,11 @@
1
- <h1>
2
- <%= Spree.t('order_mailer.store_owner_notification_email.heading') %>
3
- </h1>
4
- <p>
5
- <%= Spree.t('order_mailer.store_owner_notification_email.instructions') %>
6
- </p>
7
- <table class="purchase" role="presentation">
8
- <tr>
9
- <td>
10
- <h3><%= Spree.t('order_mailer.store_owner_notification_email.order_summary', number: @order.number) %></h3>
11
- </td>
12
- </tr>
13
- <tr>
14
- <td colspan="2">
15
- <%= render 'spree/shared/purchased_items_table', line_items: @order.line_items, order: @order %>
16
- </td>
17
- </tr>
18
- </table>
19
- <p>
20
- <%= Spree.t('order_mailer.store_owner_notification_email.thanks') %>
21
- <br />
22
- <%= Spree.t('order_mailer.store_team', store_name: current_store.name) %>
23
- </p>
1
+ <%= render 'spree/shared/purchased_items_styles' %>
2
+
3
+ <%= render layout: 'spree/shared/mailer_hero' do %>
4
+ <h1><%= Spree.t('order_mailer.store_owner_notification_email.heading') %></h1>
5
+ <p><%= Spree.t('order_mailer.store_owner_notification_email.instructions') %></p>
6
+ <% end %>
7
+
8
+ <%= render 'spree/shared/order_summary_section',
9
+ heading: Spree.t('order_mailer.store_owner_notification_email.order_summary', number: @order.number),
10
+ line_items: @order.line_items,
11
+ order: @order %>
@@ -1,53 +1,47 @@
1
- <h1>
2
- <%= Spree.t('reimbursement_mailer.reimbursement_email.dear_customer', name: name_for(@order)) %>
3
- </h1>
4
- <p>
5
- <%= Spree.t('reimbursement_mailer.reimbursement_email.instructions') %>
6
- </p>
7
- <p>
8
- <%= Spree.t('reimbursement_mailer.reimbursement_email.refund_summary') %>
9
- </p>
10
- <p>
11
- <%= Spree.t('reimbursement_mailer.reimbursement_email.total_refunded', total: @reimbursement.display_total) %>
12
- </p>
13
- <% if @reimbursement.return_items.exchange_requested.present? %>
14
- <p>
15
- <%= Spree.t('reimbursement_mailer.reimbursement_email.exchange_summary') %>
16
- </p>
1
+ <%= render 'spree/shared/purchased_items_styles' %>
17
2
 
18
- <table class="purchase_content">
19
- <% @reimbursement.return_items.exchange_requested.each do |return_item| %>
20
- <tr>
21
- <td class="purchase_image">
22
- <% image = return_item.variant.primary_media || return_item.variant.product.primary_media %>
23
- <% if image.present? && image.attached? %>
24
- <%= link_to(spree_image_tag(image, variant: :mini, alt: return_item.variant.name), spree_storefront_resource_url(return_item.variant.product)) %>
25
- <% else %>
26
- <%= link_to(image_tag('noimage/small.png', alt: return_item.variant.name), spree_storefront_resource_url(return_item.variant.product)) %>
27
- <% end %>
28
- </td>
29
- <td class="purchase_item">
30
- <strong>
31
- <span class="f-fallback">
32
- <%= link_to return_item.variant.name, spree_storefront_resource_url(return_item.variant.product) %>
33
- </span>
34
- </strong>
35
- <p class="purchase_item--additional">
36
- <%= "(#{return_item.exchange_variant.options_text})" if return_item.exchange_variant.options_text.present? -%>
37
- </p>
38
- </td>
39
- </tr>
40
- <% end %>
41
- </table>
42
- <% if @reimbursement.return_items.awaiting_return.present? && Spree::Config[:expedited_exchanges] %>
43
- <p>
44
- <%= Spree.t('reimbursement_mailer.reimbursement_email.days_to_send', days: Spree::Config[:expedited_exchanges_days_window]) %>
45
- </p>
46
- <% end %>
3
+ <%= render layout: 'spree/shared/mailer_hero' do %>
4
+ <h1><%= Spree.t('reimbursement_mailer.reimbursement_email.subject') %></h1>
5
+ <p class="greeting"><%= Spree.t('reimbursement_mailer.reimbursement_email.dear_customer', name: name_for(@order)) %></p>
6
+ <p><%= Spree.t('reimbursement_mailer.reimbursement_email.instructions') %></p>
47
7
  <% end %>
48
8
 
49
- <p>
50
- <%= Spree.t('reimbursement_mailer.reimbursement_email.thanks') %>
51
- <br />
52
- <%= Spree.t('reimbursement_mailer.reimbursement_email.store_team', store_name: current_store.name) %>
53
- </p>
9
+ <table class="section" width="100%" cellpadding="0" cellspacing="0" role="presentation">
10
+ <tr>
11
+ <td>
12
+ <h3 class="f-fallback"><%= Spree.t('reimbursement_mailer.reimbursement_email.refund_summary') %></h3>
13
+ <p class="strong f-fallback"><%= Spree.t('reimbursement_mailer.reimbursement_email.total_refunded', total: @reimbursement.display_total) %></p>
14
+ </td>
15
+ </tr>
16
+ </table>
17
+
18
+ <% exchange_items = @reimbursement.return_items.exchange_requested.to_a %>
19
+ <% if exchange_items.any? %>
20
+ <table class="section" width="100%" cellpadding="0" cellspacing="0" role="presentation">
21
+ <tr>
22
+ <td>
23
+ <h3 class="f-fallback"><%= Spree.t('reimbursement_mailer.reimbursement_email.exchange_summary') %></h3>
24
+ <% exchange_items.each do |return_item| %>
25
+ <% product_url = spree_storefront_resource_url(return_item.variant.product) %>
26
+ <table class="item" width="100%" cellpadding="0" cellspacing="0" role="presentation">
27
+ <tr>
28
+ <td class="item_image" width="96" valign="middle">
29
+ <% image = return_item.variant.primary_media || return_item.variant.product.primary_media %>
30
+ <%= render 'spree/shared/item_thumbnail_link', image: image, product_url: product_url, alt: return_item.variant.name %>
31
+ </td>
32
+ <td class="item_info" valign="middle">
33
+ <%= link_to return_item.variant.name, product_url, class: 'f-fallback item_name' %>
34
+ <% if return_item.exchange_variant.options_text.present? %>
35
+ <p class="item_meta"><%= return_item.exchange_variant.options_text %></p>
36
+ <% end %>
37
+ </td>
38
+ </tr>
39
+ </table>
40
+ <% end %>
41
+ <% if @reimbursement.return_items.awaiting_return.exists? && Spree::Config[:expedited_exchanges] %>
42
+ <p class="sub f-fallback"><%= Spree.t('reimbursement_mailer.reimbursement_email.days_to_send', days: Spree::Config[:expedited_exchanges_days_window]) %></p>
43
+ <% end %>
44
+ </td>
45
+ </tr>
46
+ </table>
47
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# Rounded 80px product thumbnail linking to the product page, with a
2
+ no-image fallback. Locals: image, product_url, alt. %>
3
+ <% if image.present? && image.attached? %>
4
+ <%= link_to spree_image_tag(image, variant: :small, alt: alt, width: 80, class: 'item_thumb'), product_url %>
5
+ <% else %>
6
+ <%= link_to image_tag('noimage/small.png', alt: alt, width: 80, class: 'item_thumb'), product_url %>
7
+ <% end %>
@@ -0,0 +1,15 @@
1
+ <%# Labelled line-items + totals section shared by the order-related emails.
2
+ Locals: heading, line_items, order, optional totals (default true — pass
3
+ false when line_items is a subset of the order, e.g. one shipment's items,
4
+ so whole-order amounts aren't shown next to a partial item list). %>
5
+ <table class="section" width="100%" cellpadding="0" cellspacing="0" role="presentation">
6
+ <tr>
7
+ <td>
8
+ <h3 class="f-fallback"><%= heading %></h3>
9
+ <%= render 'spree/shared/purchased_items_table',
10
+ line_items: line_items,
11
+ order: order,
12
+ totals: local_assigns.fetch(:totals, true) %>
13
+ </td>
14
+ </tr>
15
+ </table>
@@ -1,75 +1,31 @@
1
- <table class="purchase_content">
2
- <%= render collection: line_items, partial: 'spree/shared/purchased_items_table/line_item', as: :line_item %>
1
+ <%= render collection: line_items, partial: 'spree/shared/purchased_items_table/line_item', as: :line_item %>
2
+
3
+ <% if local_assigns.fetch(:totals, true) %>
4
+ <table class="summary purchase_content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
3
5
  <%= render 'spree/shared/purchased_items_table/subtotal', order: order %>
4
6
  <% if order.line_item_adjustments.exists? %>
5
- <% if order.all_adjustments.promotion.eligible.exists? %>
6
- <% order.all_adjustments.promotion.eligible.group_by(&:label).each do |label, adjustments| %>
7
- <tr>
8
- <td></td>
9
- <td>
10
- <p class="f-fallback purchase_total purchase_total--label">
11
- <%= Spree.t(:promotion) %>:
12
- </p>
13
- <p class="f-fallback purchase_total--name purchase_total--label">
14
- <%= label %>
15
- </p>
16
- </td>
17
- <td class="purchase_total-col">
18
- <p class="f-fallback purchase_total">
19
- <%= Spree::Money.new(adjustments.sum(&:amount), currency: order.currency) %>
20
- </p>
21
- </td>
22
- </tr>
23
- <% end %>
7
+ <% order.all_adjustments.promotion.eligible.to_a.group_by(&:label).each do |label, adjustments| %>
8
+ <%= render 'spree/shared/purchased_items_table/summary_row',
9
+ label: Spree.t(:promotion),
10
+ sub: label,
11
+ value: Spree::Money.new(adjustments.sum(&:amount), currency: order.currency) %>
24
12
  <% end %>
25
13
  <% end %>
26
14
  <% order.shipments.group_by { |s| s.selected_shipping_rate&.name }.each do |name, shipments| %>
27
- <tr>
28
- <td></td>
29
- <td>
30
- <p class="f-fallback purchase_total purchase_total--label">
31
- <%= Spree.t(:shipping) %>:
32
- </p>
33
- <p class="f-fallback purchase_total--name purchase_total--label">
34
- <%= name %>
35
- </p>
36
- </td>
37
- <td class="purchase_total-col">
38
- <p class="f-fallback purchase_total">
39
- <%= Spree::Money.new(shipments.sum(&:discounted_cost), currency: order.currency) %>
40
- </p>
41
- </td>
42
- </tr>
15
+ <%= render 'spree/shared/purchased_items_table/summary_row',
16
+ label: Spree.t(:shipping),
17
+ sub: name,
18
+ value: Spree::Money.new(shipments.sum(&:discounted_cost), currency: order.currency) %>
43
19
  <% end %>
44
20
  <% if order.additional_tax_total != 0 %>
45
- <tr>
46
- <td></td>
47
- <td>
48
- <p class="f-fallback purchase_total purchase_total--label">
49
- <%= Spree.t(:tax) %>:
50
- </p>
51
- </td>
52
- <td class="purchase_total-col">
53
- <p class="f-fallback purchase_total">
54
- <%= order.display_additional_tax_total.to_html %>
55
- </p>
56
- </td>
57
- </tr>
21
+ <%= render 'spree/shared/purchased_items_table/summary_row',
22
+ label: Spree.t(:tax),
23
+ value: order.display_additional_tax_total %>
58
24
  <% end %>
59
25
  <% if order.gift_card_total.positive? %>
60
- <tr>
61
- <td></td>
62
- <td>
63
- <p class="f-fallback purchase_total purchase_total--label">
64
- <%= Spree.t(:gift_card) %>:
65
- </p>
66
- </td>
67
- <td class="purchase_total-col">
68
- <p class="f-fallback purchase_total">
69
- -<%= order.display_gift_card_total.to_html %>
70
- </p>
71
- </td>
72
- </tr>
26
+ <%= render 'spree/shared/purchased_items_table/summary_row',
27
+ label: Spree.t(:gift_card),
28
+ value: safe_join(['-', order.display_gift_card_total.to_html]) %>
73
29
  <% end %>
74
30
  <% order.adjustments.eligible.each do |adjustment| %>
75
31
  <% next if (adjustment.source_type == 'Spree::TaxRate') || (adjustment.amount == 0) %>
@@ -77,3 +33,4 @@
77
33
  <% end %>
78
34
  <%= render 'spree/shared/purchased_items_table/total', order: order %>
79
35
  </table>
36
+ <% end %>
@@ -1,13 +1,3 @@
1
- <tr>
2
- <td></td>
3
- <td>
4
- <p class="f-fallback purchase_total purchase_total--label">
5
- <%= adjustment.label %>:
6
- </p>
7
- </td>
8
- <td class="purchase_total-col">
9
- <p class="f-fallback purchase_total">
10
- <%= Spree::Money.new(adjustment.amount, currency: order.currency) %>
11
- </p>
12
- </td>
13
- </tr>
1
+ <%= render 'spree/shared/purchased_items_table/summary_row',
2
+ label: adjustment.label,
3
+ value: Spree::Money.new(adjustment.amount, currency: order.currency) %>
@@ -1,24 +1,19 @@
1
- <tr>
2
- <td class="purchase_image">
3
- <% image = line_item.variant.primary_media || line_item.product.primary_media %>
4
- <% if image.present? && image.attached? %>
5
- <%= link_to(spree_image_tag(image, variant: :mini, alt: line_item.name), spree_storefront_resource_url(line_item.product)) %>
6
- <% else %>
7
- <%= link_to(image_tag('noimage/small.png', alt: line_item.name), spree_storefront_resource_url(line_item.product)) %>
8
- <% end %>
9
- </td>
10
- <td class="purchase_item">
11
- <strong>
12
- <span class="f-fallback">
13
- <%= link_to line_item.name, spree_storefront_resource_url(line_item.product) %>
14
- </span>
15
- </strong>
16
- <p class="purchase_item--additional"><%= line_item.variant.options_text -%></p>
17
- </td>
18
- <td class="align-right" width="30%">
19
- <span class="f-fallback purchase_item_price">
20
- <%= line_item.quantity %> x <%= line_item.single_money %><br>
21
- <%= line_item.display_amount %>
22
- </span>
23
- </td>
24
- </tr>
1
+ <table class="item" width="100%" cellpadding="0" cellspacing="0" role="presentation">
2
+ <tr>
3
+ <td class="item_image" width="96" valign="middle">
4
+ <% image = line_item.variant.primary_media || line_item.product.primary_media %>
5
+ <% product_url = spree_storefront_resource_url(line_item.product) %>
6
+ <%= render 'spree/shared/item_thumbnail_link', image: image, product_url: product_url, alt: line_item.name %>
7
+ </td>
8
+ <td class="item_info" valign="middle">
9
+ <%= link_to line_item.name, product_url, class: 'f-fallback item_name' %>
10
+ <% if line_item.variant.options_text.present? %>
11
+ <p class="item_meta"><%= line_item.variant.options_text %></p>
12
+ <% end %>
13
+ </td>
14
+ <td class="item_amount" align="right" valign="middle">
15
+ <p class="item_qty f-fallback"><%= line_item.quantity %> x <%= line_item.single_money %></p>
16
+ <p class="item_price f-fallback"><%= line_item.display_amount %></p>
17
+ </td>
18
+ </tr>
19
+ </table>
@@ -1,13 +1,3 @@
1
- <tr>
2
- <td class="purchase_footer" valign="middle"></td>
3
- <td class="purchase_footer" valign="middle">
4
- <p class="f-fallback purchase_total purchase_total--label">
5
- <%= Spree.t('order_mailer.subtotal') %>
6
- </p>
7
- </td>
8
- <td class="purchase_footer" valign="middle">
9
- <p class="f-fallback purchase_total">
10
- <%= order.display_item_total %>
11
- </p>
12
- </td>
13
- </tr>
1
+ <%= render 'spree/shared/purchased_items_table/summary_row',
2
+ label: Spree.t('order_mailer.subtotal'),
3
+ value: order.display_item_total %>
@@ -0,0 +1,14 @@
1
+ <%# One label/value row of the order summary. Locals: label, value,
2
+ optional sub (secondary line under the label, e.g. the shipping rate name),
3
+ optional row_class ('summary_total' for the emphasized final row). %>
4
+ <tr class="<%= local_assigns[:row_class] %>">
5
+ <td valign="top">
6
+ <span class="f-fallback"><%= label %></span>
7
+ <% if local_assigns[:sub].present? %>
8
+ <span class="f-fallback summary_sub"><%= sub %></span>
9
+ <% end %>
10
+ </td>
11
+ <td class="summary_value" align="right" valign="top">
12
+ <span class="f-fallback"><%= value.respond_to?(:to_html) ? value.to_html : value %></span>
13
+ </td>
14
+ </tr>
@@ -1,13 +1,4 @@
1
- <tr>
2
- <td></td>
3
- <td>
4
- <p class="f-fallback purchase_total purchase_total--label">
5
- <strong><%= Spree.t('order_mailer.total') %></strong>
6
- </p>
7
- </td>
8
- <td>
9
- <p class="f-fallback purchase_total">
10
- <strong><%= order.display_total_minus_store_credits %></strong>
11
- </p>
12
- </td>
13
- </tr>
1
+ <%= render 'spree/shared/purchased_items_table/summary_row',
2
+ row_class: 'summary_total',
3
+ label: Spree.t('order_mailer.total'),
4
+ value: order.display_total_minus_store_credits %>
@@ -1,36 +1,20 @@
1
- <h1>
2
- <%= Spree.t('shipment_mailer.shipped_email.dear_customer', name: name_for(@shipment.order)) %>
3
- </h1>
4
- <p>
5
- <%= Spree.t('shipment_mailer.shipped_email.instructions', number: @shipment.order.number) %>
6
- </p>
7
- <table class="purchase" role="presentation">
8
- <tr>
9
- <td>
10
- <h3><%= Spree.t('shipment_mailer.shipped_email.shipment_summary') %></h3>
11
- </td>
12
- </tr>
13
- <tr>
14
- <td colspan="2">
15
- <%= render 'spree/shared/purchased_items_table', line_items: @shipment.manifest.map(&:line_item), order: @shipment.order %>
16
- </td>
17
- </tr>
18
- </table>
19
- <p>
20
- <%= Spree.t('shipment_mailer.shipped_email.shipping_method', shipping_method: @shipment.shipping_method.name) %>
21
- </p>
22
- <% if @shipment.tracking %>
23
- <p>
24
- <%= Spree.t('shipment_mailer.shipped_email.track_information', tracking: @shipment.tracking) %>
25
- </p>
1
+ <%= render 'spree/shared/purchased_items_styles' %>
2
+
3
+ <%= render layout: 'spree/shared/mailer_hero' do %>
4
+ <h1><%= Spree.t('shipment_mailer.shipped_email.subject') %></h1>
5
+ <p class="greeting"><%= Spree.t('shipment_mailer.shipped_email.dear_customer', name: name_for(@shipment.order)) %></p>
6
+ <p><%= Spree.t('shipment_mailer.shipped_email.instructions', number: @shipment.order.number) %></p>
7
+ <p><%= Spree.t('shipment_mailer.shipped_email.shipping_method', shipping_method: @shipment.shipping_method.name) %></p>
8
+ <% if @shipment.tracking %>
9
+ <p><%= Spree.t('shipment_mailer.shipped_email.track_information', tracking: @shipment.tracking) %></p>
10
+ <% end %>
11
+ <% if @shipment.tracking_url %>
12
+ <p><%= Spree.t('shipment_mailer.shipped_email.track_link', url: shipment_tracking_link_to(shipment: @shipment)).html_safe %></p>
13
+ <% end %>
26
14
  <% end %>
27
- <% if @shipment.tracking_url %>
28
- <p>
29
- <%= Spree.t('shipment_mailer.shipped_email.track_link', url: shipment_tracking_link_to(shipment: @shipment)).html_safe %>
30
- </p>
31
- <% end %>
32
- <p>
33
- <%= Spree.t('shipment_mailer.shipped_email.thanks') %>
34
- <br />
35
- <%= Spree.t('shipment_mailer.shipped_email.store_team', store_name: current_store.name) %>
36
- </p>
15
+
16
+ <%= render 'spree/shared/order_summary_section',
17
+ heading: Spree.t('shipment_mailer.shipped_email.shipment_summary'),
18
+ line_items: @shipment.manifest.map(&:line_item),
19
+ order: @shipment.order,
20
+ totals: false %>
@@ -4,22 +4,14 @@ require 'spree/core'
4
4
  module Spree
5
5
  module Emails
6
6
  module Generators
7
+ # Kept as a no-op so `rake test_app` and any existing `rails g spree:emails:install`
8
+ # invocations keep working. Mailer previews now ship inside the gem and are served
9
+ # automatically at /rails/mailers — there is nothing left to copy into the host app.
7
10
  class InstallGenerator < Rails::Generators::Base
8
- desc 'Installs mailers previews for Spree transactional emails'
11
+ desc 'No-op. Spree email previews are now bundled and served automatically at /rails/mailers.'
9
12
 
10
- def self.source_paths
11
- [
12
- File.expand_path('templates', __dir__)
13
- ]
14
- end
15
-
16
- def copy_mailers_previews
17
- preview_path = Rails.application&.config&.action_mailer&.preview_path.presence || 'test/mailers/previews'
18
-
19
- template 'mailers/previews/order_preview.rb', "#{preview_path}/order_preview.rb"
20
- template 'mailers/previews/shipment_preview.rb', "#{preview_path}/shipment_preview.rb"
21
- template 'mailers/previews/reimbursement_preview.rb', "#{preview_path}/reimbursement_preview.rb"
22
- template 'mailers/previews/user_preview.rb', "#{preview_path}/user_preview.rb"
13
+ def notify_previews_are_bundled
14
+ say 'Spree email previews are bundled with spree_emails and served automatically at /rails/mailers — nothing to install.'
23
15
  end
24
16
  end
25
17
  end
@@ -9,13 +9,22 @@ module Spree
9
9
  # Add app/subscribers to autoload paths
10
10
  config.paths.add 'app/subscribers', eager_load: true
11
11
 
12
+ # Register bundled ActionMailer previews so they show up at /rails/mailers
13
+ # without the host app having to copy any files.
14
+ initializer 'spree_emails.mailer_previews' do |app|
15
+ if app.config.action_mailer.show_previews
16
+ app.config.action_mailer.preview_paths << File.expand_path('previews', __dir__)
17
+ end
18
+ end
19
+
12
20
  # Add email event subscribers
13
21
  config.after_initialize do
14
22
  Spree.subscribers.concat [
15
23
  Spree::OrderEmailSubscriber,
16
24
  Spree::ShipmentEmailSubscriber,
17
25
  Spree::ReimbursementEmailSubscriber,
18
- Spree::NewsletterSubscriberEmailSubscriber
26
+ Spree::NewsletterSubscriberEmailSubscriber,
27
+ Spree::CustomerEmailSubscriber
19
28
  ]
20
29
  end
21
30
  end
@@ -0,0 +1,14 @@
1
+ require 'spree/core/previews/preview_data'
2
+
3
+ # Preview Spree customer account emails at /rails/mailers/spree/customer
4
+ class Spree::CustomerPreview < ActionMailer::Preview
5
+ include Spree::PreviewData::LocaleParam
6
+
7
+ def password_reset_email
8
+ Spree::CustomerMailer.password_reset_email(
9
+ Spree::PreviewData.customer,
10
+ 'preview-token',
11
+ Spree::PreviewData.store(locale)
12
+ )
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ require 'spree/core/previews/preview_data'
2
+
3
+ # Preview Spree newsletter emails at /rails/mailers/spree/newsletter
4
+ class Spree::NewsletterPreview < ActionMailer::Preview
5
+ include Spree::PreviewData::LocaleParam
6
+
7
+ def email_confirmation
8
+ Spree::NewsletterMailer.email_confirmation(subscriber)
9
+ end
10
+
11
+ private
12
+
13
+ def subscriber
14
+ return example_subscriber if locale.present?
15
+
16
+ Spree::NewsletterSubscriber.unverified.last || example_subscriber
17
+ end
18
+
19
+ # Build an in-memory subscriber so the preview works on a database with no
20
+ # newsletter subscribers. When the preview toolbar requests a locale, its
21
+ # store carries that locale. Never saved, so no records are created.
22
+ def example_subscriber
23
+ subscriber = Spree::NewsletterSubscriber.new(
24
+ email: 'guest@example.com',
25
+ store: Spree::PreviewData.store(locale)
26
+ )
27
+ subscriber.verification_token ||= 'preview-token'
28
+ subscriber
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ require 'spree/core/previews/preview_data'
2
+
3
+ # Preview Spree order emails at /rails/mailers/spree/order
4
+ class Spree::OrderPreview < ActionMailer::Preview
5
+ include Spree::PreviewData::LocaleParam
6
+
7
+ def confirm_email
8
+ Spree::OrderMailer.confirm_email(order)
9
+ end
10
+
11
+ def cancel_email
12
+ Spree::OrderMailer.cancel_email(order)
13
+ end
14
+
15
+ def store_owner_notification_email
16
+ Spree::OrderMailer.store_owner_notification_email(order)
17
+ end
18
+
19
+ private
20
+
21
+ # The most recent complete order, with its locale overridden in memory when the
22
+ # preview toolbar requests one (the change is never saved).
23
+ def order
24
+ order = Spree::Order.complete.last
25
+ order.locale = locale if order && locale.present?
26
+ order
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ require 'spree/core/previews/preview_data'
2
+
3
+ # Preview Spree reimbursement emails at /rails/mailers/spree/reimbursement
4
+ class Spree::ReimbursementPreview < ActionMailer::Preview
5
+ include Spree::PreviewData::LocaleParam
6
+
7
+ def reimbursement_email
8
+ reimbursement = Spree::Reimbursement.last
9
+ reimbursement.order.locale = locale if reimbursement && locale.present?
10
+ Spree::ReimbursementMailer.reimbursement_email(reimbursement)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spree/core/previews/preview_data'
2
+
3
+ # Preview Spree shipment emails at /rails/mailers/spree/shipment
4
+ class Spree::ShipmentPreview < ActionMailer::Preview
5
+ include Spree::PreviewData::LocaleParam
6
+
7
+ def shipped_email
8
+ shipment = Spree::Shipment.shipped.last
9
+ shipment.order.locale = locale if shipment && locale.present?
10
+ Spree::ShipmentMailer.shipped_email(shipment)
11
+ end
12
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_emails
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.5.3
4
+ version: 5.6.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Schofield
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2026-07-10 00:00:00.000000000 Z
13
+ date: 2026-07-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: spree
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: 5.5.3
21
+ version: 5.6.0.rc2
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: 5.5.3
28
+ version: 5.6.0.rc2
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: email_spec
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -58,10 +58,12 @@ files:
58
58
  - app/assets/images/noimage/noimage/small.png
59
59
  - app/assets/images/noimage/small.png
60
60
  - app/helpers/spree/mail_helper.rb
61
+ - app/mailers/spree/customer_mailer.rb
61
62
  - app/mailers/spree/newsletter_mailer.rb
62
63
  - app/mailers/spree/order_mailer.rb
63
64
  - app/mailers/spree/reimbursement_mailer.rb
64
65
  - app/mailers/spree/shipment_mailer.rb
66
+ - app/subscribers/spree/customer_email_subscriber.rb
65
67
  - app/subscribers/spree/newsletter_subscriber_email_subscriber.rb
66
68
  - app/subscribers/spree/order_email_subscriber.rb
67
69
  - app/subscribers/spree/reimbursement_email_subscriber.rb
@@ -79,31 +81,35 @@ files:
79
81
  - app/views/spree/order_mailer/store_owner_notification_email.text.erb
80
82
  - app/views/spree/reimbursement_mailer/reimbursement_email.html.erb
81
83
  - app/views/spree/reimbursement_mailer/reimbursement_email.text.erb
84
+ - app/views/spree/shared/_item_thumbnail_link.html.erb
85
+ - app/views/spree/shared/_order_summary_section.html.erb
82
86
  - app/views/spree/shared/_purchased_items_table.html.erb
83
87
  - app/views/spree/shared/_purchased_items_table.text.erb
84
88
  - app/views/spree/shared/purchased_items_table/_adjustment.html.erb
85
89
  - app/views/spree/shared/purchased_items_table/_line_item.html.erb
86
90
  - app/views/spree/shared/purchased_items_table/_subtotal.html.erb
91
+ - app/views/spree/shared/purchased_items_table/_summary_row.html.erb
87
92
  - app/views/spree/shared/purchased_items_table/_total.html.erb
88
93
  - app/views/spree/shipment_mailer/shipped_email.html.erb
89
94
  - app/views/spree/shipment_mailer/shipped_email.text.erb
90
95
  - config/initializers/assets.rb
91
96
  - lib/generators/spree/emails/install/install_generator.rb
92
- - lib/generators/spree/emails/install/templates/mailers/previews/order_preview.rb
93
- - lib/generators/spree/emails/install/templates/mailers/previews/reimbursement_preview.rb
94
- - lib/generators/spree/emails/install/templates/mailers/previews/shipment_preview.rb
95
- - lib/generators/spree/emails/install/templates/mailers/previews/user_preview.rb
96
97
  - lib/spree/emails.rb
97
98
  - lib/spree/emails/engine.rb
99
+ - lib/spree/emails/previews/customer_preview.rb
100
+ - lib/spree/emails/previews/newsletter_preview.rb
101
+ - lib/spree/emails/previews/order_preview.rb
102
+ - lib/spree/emails/previews/reimbursement_preview.rb
103
+ - lib/spree/emails/previews/shipment_preview.rb
98
104
  - lib/spree_emails.rb
99
105
  homepage: https://spreecommerce.org
100
106
  licenses:
101
107
  - BSD-3-Clause
102
108
  metadata:
103
109
  bug_tracker_uri: https://github.com/spree/spree/issues
104
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.5.3
110
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.6.0.rc2
105
111
  documentation_uri: https://docs.spreecommerce.org/
106
- source_code_uri: https://github.com/spree/spree/tree/v5.5.3
112
+ source_code_uri: https://github.com/spree/spree/tree/v5.6.0.rc2
107
113
  post_install_message:
108
114
  rdoc_options: []
109
115
  require_paths:
@@ -1,13 +0,0 @@
1
- class OrderPreview < ActionMailer::Preview
2
- def confirm_email
3
- Spree::OrderMailer.confirm_email(Spree::Order.complete.first)
4
- end
5
-
6
- def cancel_email
7
- Spree::OrderMailer.cancel_email(Spree::Order.complete.first)
8
- end
9
-
10
- def store_owner_notification_email
11
- Spree::OrderMailer.store_owner_notification_email(Spree::Order.complete.first)
12
- end
13
- end
@@ -1,5 +0,0 @@
1
- class ReimbursementPreview < ActionMailer::Preview
2
- def reimbursement_email
3
- Spree::ReimbursementMailer.reimbursement_email(Spree::Reimbursement.first)
4
- end
5
- end
@@ -1,7 +0,0 @@
1
- class ShipmentPreview < ActionMailer::Preview
2
- helper Spree::ShipmentHelper
3
-
4
- def shipped_email
5
- Spree::ShipmentMailer.shipped_email(Spree::Shipment.shipped.first)
6
- end
7
- end
@@ -1,11 +0,0 @@
1
- class UserPreview < ActionMailer::Preview
2
- def reset_password_instructions
3
- Spree::UserMailer.reset_password_instructions(Spree.user_class.first, 'your_token', { current_store_id: Spree::Store.default.id })
4
- end
5
-
6
- if Spree::Auth::Config[:confirmable]
7
- def confirmation_instructions
8
- Spree::UserMailer.confirmation_instructions(Spree.user_class.first, 'your_token')
9
- end
10
- end
11
- end