spree_admin 5.4.0 → 5.4.2
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/imports_controller.rb +1 -1
- data/app/controllers/spree/admin/option_types_controller.rb +16 -3
- data/app/controllers/spree/admin/products_controller.rb +9 -5
- data/app/controllers/spree/admin/promotions_controller.rb +3 -1
- data/app/helpers/spree/admin/table_helper.rb +7 -1
- data/app/subscribers/spree/admin/import_row_subscriber.rb +1 -0
- data/app/subscribers/spree/admin/import_subscriber.rb +25 -11
- data/app/views/spree/admin/imports/_loader.html.erb +5 -0
- data/app/views/spree/admin/imports/show.html.erb +14 -0
- data/app/views/spree/admin/option_types/_form.html.erb +37 -2
- 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/app/views/spree/admin/shared/_user_dropdown.html.erb +1 -1
- data/config/locales/en.yml +4 -1
- data/lib/spree/admin/runtime_configuration.rb +1 -0
- metadata +6 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2f9e9301b1be27a3349cfc4eaef27ca076dff3e8131a8a88fc926abba84b40a1
|
|
4
|
+
data.tar.gz: 49e0257fda4a3ffb5a6b8da0ea1623b2e3c323c07d2c47eafc986fd0b1485ce2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e38c5fcb1d9c9205f67203ecfbc7dd0c862fc80bae7152d918f0ebec47af68f78f0ab7141d03219e4547c3ff1633bdc05355353ef74bdbc55a7e82f10ddba5b1
|
|
7
|
+
data.tar.gz: 46fa0bd908105098e55528c5691e38ea7d275bacd780f14f09f17062c81f15d8d91ddeb2fbd2bdaa3c18ef1dcabed2f60fea28242d763e1b4402ade26c6be53d
|
|
@@ -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]
|
|
@@ -14,7 +14,7 @@ module Spree
|
|
|
14
14
|
if @object.status == 'mapping'
|
|
15
15
|
@mappings = @object.mappings
|
|
16
16
|
@mappings_options = @object.unmapped_file_columns.map { |file_column| [file_column, file_column] }
|
|
17
|
-
|
|
17
|
+
elsif !@object.large_import?
|
|
18
18
|
@rows = @object.rows.processed.includes(:item)
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
module Admin
|
|
3
3
|
class OptionTypesController < ResourceController
|
|
4
|
-
before_action :
|
|
4
|
+
before_action :setup_option_values, only: [:edit, :new]
|
|
5
5
|
|
|
6
6
|
include ProductsBreadcrumbConcern
|
|
7
7
|
add_breadcrumb Spree.t(:options), :admin_option_types_path
|
|
@@ -10,8 +10,21 @@ module Spree
|
|
|
10
10
|
|
|
11
11
|
private
|
|
12
12
|
|
|
13
|
-
def
|
|
14
|
-
|
|
13
|
+
def setup_option_values
|
|
14
|
+
per_page = Spree::Admin::RuntimeConfig.admin_option_values_per_page
|
|
15
|
+
@option_values_page = [params[:option_values_page].to_i, 1].max
|
|
16
|
+
@option_values_total = @option_type.option_values.count
|
|
17
|
+
|
|
18
|
+
if @option_values_total == 0
|
|
19
|
+
@option_type.option_values.build
|
|
20
|
+
@option_values = @option_type.option_values
|
|
21
|
+
@option_values_pages = 1
|
|
22
|
+
else
|
|
23
|
+
@option_values = @option_type.option_values.order(:position)
|
|
24
|
+
.offset((@option_values_page - 1) * per_page)
|
|
25
|
+
.limit(per_page)
|
|
26
|
+
@option_values_pages = (@option_values_total.to_f / per_page).ceil
|
|
27
|
+
end
|
|
15
28
|
end
|
|
16
29
|
|
|
17
30
|
def add_breadcrumbs
|
|
@@ -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
|
|
@@ -79,7 +79,13 @@ module Spree
|
|
|
79
79
|
def render_money_column(value, column)
|
|
80
80
|
return empty_column_placeholder if value.blank?
|
|
81
81
|
|
|
82
|
-
value.respond_to?(:display_amount)
|
|
82
|
+
if value.respond_to?(:display_amount)
|
|
83
|
+
value.display_amount
|
|
84
|
+
elsif value.is_a?(Spree::Money)
|
|
85
|
+
value.to_html
|
|
86
|
+
else
|
|
87
|
+
Spree::Money.new(value, currency: current_currency).to_html
|
|
88
|
+
end
|
|
83
89
|
end
|
|
84
90
|
|
|
85
91
|
# Render date column
|
|
@@ -4,24 +4,17 @@ module Spree
|
|
|
4
4
|
module Admin
|
|
5
5
|
# Handles Import events for the admin interface.
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
# - Updating the loader in the import view (Turbo Streams)
|
|
9
|
-
#
|
|
10
|
-
# We use async: false because the UI update should happen immediately
|
|
11
|
-
# after the import completes.
|
|
7
|
+
# We use async: false because the UI updates should happen immediately.
|
|
12
8
|
#
|
|
13
9
|
class ImportSubscriber < Spree::Subscriber
|
|
14
|
-
subscribes_to 'import.completed', async: false
|
|
10
|
+
subscribes_to 'import.completed', 'import.progress', async: false
|
|
15
11
|
|
|
16
12
|
on 'import.completed', :update_loader_in_import_view
|
|
13
|
+
on 'import.progress', :update_footer_in_import_view
|
|
17
14
|
|
|
18
15
|
def update_loader_in_import_view(event)
|
|
19
|
-
|
|
20
|
-
return unless import_id
|
|
21
|
-
|
|
22
|
-
import = Spree::Import.find_by_prefix_id(import_id)
|
|
16
|
+
import = find_import(event)
|
|
23
17
|
return unless import
|
|
24
|
-
return unless import.respond_to?(:broadcast_update_to)
|
|
25
18
|
|
|
26
19
|
import.broadcast_update_to(
|
|
27
20
|
"import_#{import.id}_loader",
|
|
@@ -30,6 +23,27 @@ module Spree
|
|
|
30
23
|
locals: { import: import }
|
|
31
24
|
)
|
|
32
25
|
end
|
|
26
|
+
|
|
27
|
+
def update_footer_in_import_view(event)
|
|
28
|
+
import = find_import(event)
|
|
29
|
+
return unless import
|
|
30
|
+
|
|
31
|
+
import.broadcast_replace_to(
|
|
32
|
+
"import_#{import.id}_footer",
|
|
33
|
+
target: 'footer',
|
|
34
|
+
partial: 'spree/admin/imports/footer',
|
|
35
|
+
locals: { import: import }
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def find_import(event)
|
|
42
|
+
import_id = event.payload['id']
|
|
43
|
+
return unless import_id
|
|
44
|
+
|
|
45
|
+
Spree::Import.find_by_prefix_id(import_id)
|
|
46
|
+
end
|
|
33
47
|
end
|
|
34
48
|
end
|
|
35
49
|
end
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
<div class="flex justify-center items-center my-12 flex-col pb-12">
|
|
3
3
|
<%= icon('check', class: 'text-green-700', style: 'font-size: 4rem;') %>
|
|
4
4
|
<p class="text-green-700 mb-3"><%= Spree.t('admin.imports.import_done') %>!</p>
|
|
5
|
+
<% if import.large_import? %>
|
|
6
|
+
<p class="text-gray-600 mb-3">
|
|
7
|
+
<%= Spree.t('admin.imports.large_import_summary', completed: import.rows.completed.count, failed: import.rows.failed.count) %>
|
|
8
|
+
</p>
|
|
9
|
+
<% end %>
|
|
5
10
|
<%= link_to_with_icon 'arrow-back-up', Spree.t('admin.back_to_dashboard'), spree.admin_path, class: 'btn btn-light mb-12' %>
|
|
6
11
|
</div>
|
|
7
12
|
<% else %>
|
|
@@ -25,6 +25,20 @@
|
|
|
25
25
|
</div>
|
|
26
26
|
|
|
27
27
|
<%= render 'spree/admin/imports/mapping_footer', import: @import %>
|
|
28
|
+
<% elsif @import.large_import? %>
|
|
29
|
+
<%= turbo_stream_from "import_#{@import.id}_footer" %>
|
|
30
|
+
<%= turbo_stream_from "import_#{@import.id}_loader" %>
|
|
31
|
+
|
|
32
|
+
<div class="p-6 text-center text-gray-600 my-8">
|
|
33
|
+
<p class="mb-2"><%= Spree.t('admin.imports.large_import_message', count: @import.rows_count) %></p>
|
|
34
|
+
<p><%= Spree.t('admin.imports.large_import_background_note') %></p>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div id="loader" data-controller="auto-scroll">
|
|
38
|
+
<%= render 'spree/admin/imports/loader', import: @import %>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<%= render 'spree/admin/imports/footer', import: @import %>
|
|
28
42
|
<% else %>
|
|
29
43
|
<%= turbo_stream_from "import_#{@import.id}_rows" %>
|
|
30
44
|
<%= turbo_stream_from "import_#{@import.id}_footer" %>
|
|
@@ -36,6 +36,11 @@
|
|
|
36
36
|
<div class="card mb-6">
|
|
37
37
|
<div class="card-header flex justify-between items-center">
|
|
38
38
|
<h5 class="card-title"><%= Spree.t(:option_values) %></h5>
|
|
39
|
+
<% if @option_values_total > 0 %>
|
|
40
|
+
<span class="text-sm text-gray-500">
|
|
41
|
+
<%= @option_values_total %> <%= 'value'.pluralize(@option_values_total) %>
|
|
42
|
+
</span>
|
|
43
|
+
<% end %>
|
|
39
44
|
</div>
|
|
40
45
|
<div class="card-body p-0">
|
|
41
46
|
<div class="table-responsive">
|
|
@@ -50,8 +55,7 @@
|
|
|
50
55
|
</tr>
|
|
51
56
|
</thead>
|
|
52
57
|
<tbody id="option_values" data-controller="sortable" data-sortable-handle-value=".move-handle" data-sortable-resource-name-value="option_value" data-sortable-response-kind-value="turbo-stream">
|
|
53
|
-
|
|
54
|
-
<%= f.fields_for :option_values do |option_value_form| %>
|
|
58
|
+
<%= f.fields_for :option_values, @option_values do |option_value_form| %>
|
|
55
59
|
<%= render partial: 'option_value_fields', locals: { f: option_value_form, option_type: @option_type } %>
|
|
56
60
|
<% end %>
|
|
57
61
|
|
|
@@ -69,5 +73,36 @@
|
|
|
69
73
|
</tbody>
|
|
70
74
|
</table>
|
|
71
75
|
</div>
|
|
76
|
+
<% if @option_values_pages > 1 %>
|
|
77
|
+
<div class="flex items-center justify-between p-3 border-t">
|
|
78
|
+
<span class="text-sm text-gray-500">
|
|
79
|
+
<% per_page = Spree::Admin::RuntimeConfig.admin_option_values_per_page %>
|
|
80
|
+
Showing <%= (@option_values_page - 1) * per_page + 1 %>-<%= [@option_values_page * per_page, @option_values_total].min %> of <%= @option_values_total %>
|
|
81
|
+
</span>
|
|
82
|
+
<div class="flex gap-1.5">
|
|
83
|
+
<% if @option_values_page > 1 %>
|
|
84
|
+
<%= link_to icon('chevron-left', class: 'text-gray-900 mr-0'),
|
|
85
|
+
spree.edit_admin_option_type_path(@option_type, option_values_page: @option_values_page - 1),
|
|
86
|
+
class: "btn btn-light p-2",
|
|
87
|
+
'aria-label': 'Previous page' %>
|
|
88
|
+
<% else %>
|
|
89
|
+
<button class="btn btn-light p-2 cursor-not-allowed opacity-50" disabled>
|
|
90
|
+
<%= icon('chevron-left', class: 'text-gray-900 mr-0') %>
|
|
91
|
+
</button>
|
|
92
|
+
<% end %>
|
|
93
|
+
|
|
94
|
+
<% if @option_values_page < @option_values_pages %>
|
|
95
|
+
<%= link_to icon('chevron-right', class: 'text-gray-900 mr-0'),
|
|
96
|
+
spree.edit_admin_option_type_path(@option_type, option_values_page: @option_values_page + 1),
|
|
97
|
+
class: "btn btn-light p-2",
|
|
98
|
+
'aria-label': 'Next page' %>
|
|
99
|
+
<% else %>
|
|
100
|
+
<button class="btn btn-light p-2 cursor-not-allowed opacity-50" disabled>
|
|
101
|
+
<%= icon('chevron-right', class: 'text-gray-900 mr-0') %>
|
|
102
|
+
</button>
|
|
103
|
+
<% end %>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
<% end %>
|
|
72
107
|
</div>
|
|
73
108
|
</div>
|
|
@@ -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}" %>
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
<%= Spree.t(:support) %>
|
|
39
39
|
</h6>
|
|
40
40
|
<%= link_to_with_icon 'book', Spree.t('admin.documentation'), 'https://spreecommerce.org/docs', class: 'dropdown-item', target: '_blank' %>
|
|
41
|
-
<%= link_to_with_icon 'brand-
|
|
41
|
+
<%= link_to_with_icon 'brand-discord', 'Discord', 'https://discord.spreecommerce.org/', class: 'dropdown-item', target: '_blank' %>
|
|
42
42
|
<%= link_to_with_icon 'message', Spree.t(:contact_us), 'https://spreecommerce.org/contact/', class: 'dropdown-item', target: '_blank' %>
|
|
43
43
|
<% end %>
|
|
44
44
|
|
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
|
|
@@ -135,6 +136,9 @@ en:
|
|
|
135
136
|
all_required_columns_mapped: Good job, all required columns are mapped!
|
|
136
137
|
field_required: Field required
|
|
137
138
|
import_done: All done!
|
|
139
|
+
large_import_background_note: You can close this page — the import will continue in the background.
|
|
140
|
+
large_import_message: This import contains %{count} rows and is too large to display individually.
|
|
141
|
+
large_import_summary: "%{completed} completed, %{failed} failed"
|
|
138
142
|
mapping_required: This field is required
|
|
139
143
|
please_map_all_required_fields: Please map all the required fields to continue.
|
|
140
144
|
waiting_for_file_to_be_processed: Waiting for file to be processed...
|
|
@@ -293,7 +297,6 @@ en:
|
|
|
293
297
|
shipment_transfer:
|
|
294
298
|
wrong_destination: Wrong destination
|
|
295
299
|
show_json: Show JSON
|
|
296
|
-
slack: Slack
|
|
297
300
|
stock_transfers:
|
|
298
301
|
add_products_tip: You need to select a destination location first
|
|
299
302
|
store_credit:
|
|
@@ -11,6 +11,7 @@ module Spree
|
|
|
11
11
|
preference :admin_records_per_page, :integer, default: DEFAULT_PER_PAGE
|
|
12
12
|
preference :admin_products_per_page, :integer, default: DEFAULT_PER_PAGE
|
|
13
13
|
preference :admin_orders_per_page, :integer, default: DEFAULT_PER_PAGE
|
|
14
|
+
preference :admin_option_values_per_page, :integer, default: 50
|
|
14
15
|
|
|
15
16
|
preference :include_application_importmap, :boolean, default: false
|
|
16
17
|
preference :legacy_sidebar_navigation, :boolean, default: false
|
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.2
|
|
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-27 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.2
|
|
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.2
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: active_link_to
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -220,20 +220,6 @@ dependencies:
|
|
|
220
220
|
- - "~>"
|
|
221
221
|
- !ruby/object:Gem::Version
|
|
222
222
|
version: 6.8.5
|
|
223
|
-
- !ruby/object:Gem::Dependency
|
|
224
|
-
name: pagy
|
|
225
|
-
requirement: !ruby/object:Gem::Requirement
|
|
226
|
-
requirements:
|
|
227
|
-
- - "~>"
|
|
228
|
-
- !ruby/object:Gem::Version
|
|
229
|
-
version: '43.0'
|
|
230
|
-
type: :runtime
|
|
231
|
-
prerelease: false
|
|
232
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
233
|
-
requirements:
|
|
234
|
-
- - "~>"
|
|
235
|
-
- !ruby/object:Gem::Version
|
|
236
|
-
version: '43.0'
|
|
237
223
|
- !ruby/object:Gem::Dependency
|
|
238
224
|
name: ruby-oembed
|
|
239
225
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -1175,9 +1161,9 @@ licenses:
|
|
|
1175
1161
|
- BSD-3-Clause
|
|
1176
1162
|
metadata:
|
|
1177
1163
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
1178
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.
|
|
1164
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.2
|
|
1179
1165
|
documentation_uri: https://docs.spreecommerce.org/
|
|
1180
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.4.
|
|
1166
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.4.2
|
|
1181
1167
|
post_install_message:
|
|
1182
1168
|
rdoc_options: []
|
|
1183
1169
|
require_paths:
|