spree_admin 5.4.0 → 5.4.1
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/app/controllers/spree/admin/base_controller.rb +18 -0
- data/app/controllers/spree/admin/products_controller.rb +9 -5
- data/app/controllers/spree/admin/promotions_controller.rb +3 -1
- data/app/views/spree/admin/products/form/_status.html.erb +19 -3
- data/app/views/spree/admin/products/form/_variants.html.erb +1 -1
- data/app/views/spree/admin/products/form/variants/_variant_template.html.erb +6 -6
- data/app/views/spree/admin/promotions/form/_settings.html.erb +13 -2
- data/config/locales/en.yml +1 -0
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 26df0b31a098e6532b1f1ce9a0d9c93e5775eabfdb0aae25d97ddc2cad9817f7
|
|
4
|
+
data.tar.gz: d9a8d58ad5854ae05313f113ad57530aaa1a7b70d75bb4d19c20f7fc0904a71b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 142a56b2d97a37fd72ec7230a0d35bc83a3ea1e56b31c36c536a1e33a5714c1148c4e69d6e779348fa10cef3f8157e0e14909641a9472419c95bd09da52bd48d
|
|
7
|
+
data.tar.gz: f29b088464374c13ae4bbc77a549f15524cd6661fedc3ac6e3d3f484c3dba47b91bd1e0d643031ddf953c156949f7fdf54ed889cc026096ca701df6b9e6db0e3
|
|
@@ -88,6 +88,24 @@ module Spree
|
|
|
88
88
|
@current_timezone ||= current_store.preferred_timezone
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
+
# datetime-local inputs submit values without timezone information. Interpret
|
|
92
|
+
# them in the store's timezone so they match what the admin sees in the form.
|
|
93
|
+
def parse_datetime_in_store_timezone(attrs, *fields)
|
|
94
|
+
zone = ActiveSupport::TimeZone[current_timezone] || Time.zone
|
|
95
|
+
|
|
96
|
+
fields.each do |field|
|
|
97
|
+
value = attrs[field]
|
|
98
|
+
next if value.blank?
|
|
99
|
+
|
|
100
|
+
parsed_value = begin
|
|
101
|
+
zone.parse(value.to_s)
|
|
102
|
+
rescue ArgumentError
|
|
103
|
+
nil
|
|
104
|
+
end
|
|
105
|
+
attrs[field] = parsed_value if parsed_value.present?
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
91
109
|
def current_currency
|
|
92
110
|
@current_currency ||= if params[:currency].present? && supported_currency?(params[:currency])
|
|
93
111
|
params[:currency]
|
|
@@ -304,11 +304,15 @@ module Spree
|
|
|
304
304
|
end
|
|
305
305
|
|
|
306
306
|
def permitted_resource_params
|
|
307
|
-
@permitted_resource_params ||=
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
307
|
+
@permitted_resource_params ||= begin
|
|
308
|
+
attrs = if cannot?(:activate, @product) && @new_status&.to_sym == :active
|
|
309
|
+
params.require(:product).permit(permitted_product_attributes).except(:status, :make_active_at)
|
|
310
|
+
else
|
|
311
|
+
params.require(:product).permit(permitted_product_attributes)
|
|
312
|
+
end
|
|
313
|
+
parse_datetime_in_store_timezone(attrs, :available_on, :discontinue_on, :make_active_at)
|
|
314
|
+
attrs
|
|
315
|
+
end
|
|
312
316
|
end
|
|
313
317
|
end
|
|
314
318
|
end
|
|
@@ -48,7 +48,9 @@ module Spree
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def permitted_resource_params
|
|
51
|
-
params.require(:promotion).permit(permitted_promotion_attributes)
|
|
51
|
+
attrs = params.require(:promotion).permit(permitted_promotion_attributes)
|
|
52
|
+
parse_datetime_in_store_timezone(attrs, :starts_at, :expires_at)
|
|
53
|
+
attrs
|
|
52
54
|
end
|
|
53
55
|
end
|
|
54
56
|
end
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
<%# datetime-local inputs have no timezone; render values in the store's timezone so admins see and submit values in the store's local time. %>
|
|
2
|
+
<%
|
|
3
|
+
store_timezone = ActiveSupport::TimeZone[current_store.preferred_timezone] || Time.zone
|
|
4
|
+
to_store_local = ->(value) { value&.in_time_zone(store_timezone)&.strftime('%Y-%m-%dT%H:%M') }
|
|
5
|
+
make_active_at_local = to_store_local.call(@product.make_active_at)
|
|
6
|
+
available_on_local = to_store_local.call(@product.available_on)
|
|
7
|
+
discontinue_on_local = to_store_local.call(@product.discontinue_on)
|
|
8
|
+
tz_help = Spree.t('admin.datetime_field_timezone_help', zone: store_timezone.name)
|
|
9
|
+
%>
|
|
10
|
+
|
|
1
11
|
<div class="card mb-6">
|
|
2
12
|
<div class="card-body">
|
|
3
13
|
<div class="grid grid-cols-12 gap-6 mb-6">
|
|
@@ -14,21 +24,27 @@
|
|
|
14
24
|
<div class="col-span-6 <%= 'hidden' if @product.active? %>" data-product-form-target="makeActiveAt">
|
|
15
25
|
<% if can?(:activate, @product) %>
|
|
16
26
|
<%= f.spree_datetime_field :make_active_at,
|
|
27
|
+
value: make_active_at_local,
|
|
28
|
+
help: tz_help,
|
|
17
29
|
help_bubble: Spree.t('admin.products.status_form.make_active_at'),
|
|
18
|
-
max:
|
|
30
|
+
max: discontinue_on_local %>
|
|
19
31
|
<% end %>
|
|
20
32
|
</div>
|
|
21
33
|
</div>
|
|
22
34
|
<div class="grid grid-cols-12 gap-6">
|
|
23
35
|
<div data-product-form-target="availableOn" class="col-span-6">
|
|
24
36
|
<%= f.spree_datetime_field :available_on,
|
|
37
|
+
value: available_on_local,
|
|
38
|
+
help: tz_help,
|
|
25
39
|
help_bubble: Spree.t('admin.products.status_form.available_on'),
|
|
26
|
-
max:
|
|
40
|
+
max: discontinue_on_local %>
|
|
27
41
|
</div>
|
|
28
42
|
<div data-product-form-target="discontinueOn" class="col-span-6">
|
|
29
43
|
<%= f.spree_datetime_field :discontinue_on,
|
|
44
|
+
value: discontinue_on_local,
|
|
45
|
+
help: tz_help,
|
|
30
46
|
help_bubble: Spree.t('admin.products.status_form.discontinue_on'),
|
|
31
|
-
min:
|
|
47
|
+
min: make_active_at_local %>
|
|
32
48
|
</div>
|
|
33
49
|
</div>
|
|
34
50
|
</div>
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
<div class="variants-table__body" data-variants-form-target="variantsContainer" data-test-id="product-variants-table">
|
|
168
168
|
</div>
|
|
169
169
|
<div class="variants-table__footer text-sm rounded-b-2xl">
|
|
170
|
-
<%= Spree.t('admin.variants_form.total_inventory_html', stock_location:
|
|
170
|
+
<%= Spree.t('admin.variants_form.total_inventory_html', stock_location: default_stock_location_for_product(@product).name, count: raw("<span data-variants-form-target='stockItemsCount'>#{@product.total_on_hand}</span>") )%>
|
|
171
171
|
</div>
|
|
172
172
|
</div>
|
|
173
173
|
</div>
|
|
@@ -21,18 +21,18 @@
|
|
|
21
21
|
<div class="variants-table__body__cell column-price mr-2">
|
|
22
22
|
<% supported_currencies.each_with_index do |currency, i| %>
|
|
23
23
|
<div class="input-group price-input-container <%= current_currency != currency ? 'hidden' : 'flex' %>" <%= !can_manage_prices ? 'readonly' : '' %>>
|
|
24
|
-
<%= text_field_tag "product[variants_attributes][prices_attributes][#{i}][amount]", '', class: 'border-0 focus:ring-0 focus:outline-none', data: { slot: "[prices_attributes][#{currency}][amount]_input", action: 'variants-form#updatePrice blur->variants-form#formatPrice', currency: currency.to_s }, readonly: !can_manage_prices %>
|
|
24
|
+
<%= text_field_tag "product[variants_attributes][prices_attributes][#{i}][amount]", '', id: nil, class: 'border-0 focus:ring-0 focus:outline-none', data: { slot: "[prices_attributes][#{currency}][amount]_input", action: 'variants-form#updatePrice blur->variants-form#formatPrice', currency: currency.to_s }, readonly: !can_manage_prices %>
|
|
25
25
|
<span class="px-3"><%= currency_symbol(currency) %></span>
|
|
26
26
|
</div>
|
|
27
|
-
<%= hidden_field_tag "product[variants_attributes][prices_attributes][#{i}][currency]", currency, data: {slot: "[prices_attributes][#{currency}][currency]_input"} %>
|
|
28
|
-
<%= hidden_field_tag "product[variants_attributes][prices_attributes][#{i}][id]", "", data: {slot: "[prices_attributes][#{currency}][id]_input"} %>
|
|
27
|
+
<%= hidden_field_tag "product[variants_attributes][prices_attributes][#{i}][currency]", currency, id: nil, data: {slot: "[prices_attributes][#{currency}][currency]_input"} %>
|
|
28
|
+
<%= hidden_field_tag "product[variants_attributes][prices_attributes][#{i}][id]", "", id: nil, data: {slot: "[prices_attributes][#{currency}][id]_input"} %>
|
|
29
29
|
<% end %>
|
|
30
30
|
</div>
|
|
31
31
|
<div class="variants-table__body__cell column-quantity">
|
|
32
32
|
<% available_stock_locations_for_product(@product).ids.each_with_index do |id, i| %>
|
|
33
|
-
<%= number_field_tag "product[variants_attributes][stock_items_attributes][#{i}][count_on_hand]", 0, class: class_names('form-input', default_stock_location.id == id ? 'block' : 'hidden'), data: {slot: "[stock_items_attributes][#{id}][count_on_hand]_input", stock_location_id: id, action: "variants-form#updateCountOnHand blur->variants-form#replaceBlankWithZero" }, readonly: !can_manage_stock %>
|
|
34
|
-
<%= hidden_field_tag "product[variants_attributes][stock_items_attributes][#{i}][stock_location_id]", id, data: { slot: "[stock_items_attributes][#{id}][stock_location_id]_input" } %>
|
|
35
|
-
<%= hidden_field_tag "product[variants_attributes][stock_items_attributes][#{i}][id]", "", data: { slot: "[stock_items_attributes][#{id}][id]_input" } %>
|
|
33
|
+
<%= number_field_tag "product[variants_attributes][stock_items_attributes][#{i}][count_on_hand]", 0, id: nil, class: class_names('form-input', default_stock_location.id == id ? 'block' : 'hidden'), data: {slot: "[stock_items_attributes][#{id}][count_on_hand]_input", stock_location_id: id, action: "variants-form#updateCountOnHand blur->variants-form#replaceBlankWithZero" }, readonly: !can_manage_stock %>
|
|
34
|
+
<%= hidden_field_tag "product[variants_attributes][stock_items_attributes][#{i}][stock_location_id]", id, id: nil, data: { slot: "[stock_items_attributes][#{id}][stock_location_id]_input" } %>
|
|
35
|
+
<%= hidden_field_tag "product[variants_attributes][stock_items_attributes][#{i}][id]", "", id: nil, data: { slot: "[stock_items_attributes][#{id}][id]_input" } %>
|
|
36
36
|
<% end %>
|
|
37
37
|
</div>
|
|
38
38
|
<% if can?(:manage, @product.default_variant) %>
|
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
<%= f.spree_number_field :usage_limit, min: 0, step: 1, help: 'Leave this field blank for unlimited usage.' %>
|
|
3
3
|
<% end %>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<%# datetime-local inputs have no timezone; render values in the store's timezone so admins see and submit values in the store's local time. %>
|
|
6
|
+
<%
|
|
7
|
+
store_timezone = ActiveSupport::TimeZone[current_store.preferred_timezone] || Time.zone
|
|
8
|
+
to_store_local = ->(value) { value&.in_time_zone(store_timezone)&.strftime('%Y-%m-%dT%H:%M') }
|
|
9
|
+
starts_at_local = to_store_local.call(@promotion.starts_at)
|
|
10
|
+
expires_at_local = to_store_local.call(@promotion.expires_at)
|
|
11
|
+
tz_help = Spree.t('admin.datetime_field_timezone_help', zone: store_timezone.name)
|
|
12
|
+
%>
|
|
6
13
|
|
|
7
|
-
<%= f.spree_datetime_field :
|
|
14
|
+
<%= f.spree_datetime_field :starts_at, value: starts_at_local, help: tz_help %>
|
|
15
|
+
|
|
16
|
+
<%= f.spree_datetime_field :expires_at,
|
|
17
|
+
value: expires_at_local,
|
|
18
|
+
help: "Leave this field blank for no expiration. #{tz_help}" %>
|
data/config/locales/en.yml
CHANGED
|
@@ -100,6 +100,7 @@ en:
|
|
|
100
100
|
top_products: Top products
|
|
101
101
|
view_report: View report
|
|
102
102
|
whats_happening_on_html: Here's what's happening on <strong>%{store_name}</strong> today.
|
|
103
|
+
datetime_field_timezone_help: 'Time zone: %{zone}'
|
|
103
104
|
digital_shipment_fulfillment_note: This shipment will be marked as fulfilled once the user downloads the digital product
|
|
104
105
|
display_on_options:
|
|
105
106
|
back_end: Only on admin panel
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_admin
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.4.
|
|
4
|
+
version: 5.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vendo Connect Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: spree
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 5.4.
|
|
19
|
+
version: 5.4.1
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 5.4.
|
|
26
|
+
version: 5.4.1
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: active_link_to
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -1175,9 +1175,9 @@ licenses:
|
|
|
1175
1175
|
- BSD-3-Clause
|
|
1176
1176
|
metadata:
|
|
1177
1177
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
1178
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.
|
|
1178
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.1
|
|
1179
1179
|
documentation_uri: https://docs.spreecommerce.org/
|
|
1180
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.4.
|
|
1180
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.4.1
|
|
1181
1181
|
post_install_message:
|
|
1182
1182
|
rdoc_options: []
|
|
1183
1183
|
require_paths:
|