spree_admin 5.1.0.beta2 → 5.1.0.beta4

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/spree/admin/components/_cards.scss +1 -7
  3. data/app/assets/stylesheets/spree/admin/components/_main.scss +1 -1
  4. data/app/assets/stylesheets/spree/admin/global/_variables.scss +4 -4
  5. data/app/assets/stylesheets/spree/admin/shared/_base.scss +6 -0
  6. data/app/controllers/concerns/spree/admin/order_breadcrumb_concern.rb +12 -0
  7. data/app/controllers/spree/admin/orders_controller.rb +2 -4
  8. data/app/controllers/spree/admin/page_blocks_controller.rb +3 -1
  9. data/app/controllers/spree/admin/page_sections_controller.rb +5 -1
  10. data/app/controllers/spree/admin/payment_methods_controller.rb +6 -4
  11. data/app/controllers/spree/admin/post_categories_controller.rb +6 -0
  12. data/app/controllers/spree/admin/posts_controller.rb +4 -0
  13. data/app/controllers/spree/admin/products_controller.rb +4 -4
  14. data/app/controllers/spree/admin/refunds_controller.rb +4 -0
  15. data/app/controllers/spree/admin/shipments_controller.rb +2 -2
  16. data/app/helpers/spree/admin/navigation_helper.rb +1 -1
  17. data/app/helpers/spree/admin/orders_filters_helper.rb +1 -1
  18. data/app/javascript/spree/admin/controllers/multi_tom_select_controller.js +3 -2
  19. data/app/javascript/spree/admin/controllers/variants_form_controller.js +22 -16
  20. data/app/views/spree/admin/orders/_special_instructions.html.erb +14 -0
  21. data/app/views/spree/admin/orders/edit.html.erb +1 -0
  22. data/app/views/spree/admin/payments/_payment.html.erb +2 -1
  23. data/app/views/spree/admin/preferences/_password_field.html.erb +2 -2
  24. data/app/views/spree/admin/products/_form.html.erb +2 -1
  25. data/app/views/spree/admin/products/_list.html.erb +5 -2
  26. data/app/views/spree/admin/products/form/_tax.html.erb +12 -0
  27. data/app/views/spree/admin/refunds/new.html.erb +2 -4
  28. data/app/views/spree/admin/shared/_content_header.html.erb +1 -1
  29. data/app/views/spree/admin/shared/_filter_badge_template.erb +1 -1
  30. data/app/views/spree/admin/shared/sidebar/_orders_nav.html.erb +1 -1
  31. data/app/views/spree/admin/stores/edit.html.erb +3 -3
  32. data/app/views/spree/admin/stores/form/_checkout.html.erb +25 -5
  33. data/app/views/spree/admin/variants/_variant.html.erb +2 -2
  34. data/app/views/spree/admin/variants/form/_basic.html.erb +4 -4
  35. data/config/locales/en.yml +6 -0
  36. data/lib/spree/admin/testing_support/tom_select.rb +17 -0
  37. metadata +12 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9de1e5e85e6639aa2f1798ff7d6c6d77116a702da71c872463a882157a22209
4
- data.tar.gz: 067c530bc16335b4a43d086de3269aec4dd0d5381ebb518219cde01bea6097f3
3
+ metadata.gz: 3f5759966c4d6a61b9c2b51e85b01e209cefabf35fb2ec0934623d21f1937e23
4
+ data.tar.gz: '0994653a7d251af2746bde91daf82e7ea397063821f4f8019face626deb733d6'
5
5
  SHA512:
6
- metadata.gz: e57033091798721e3017a6748f52ffb6a6384f25bc456294089bdf97625a8c78b1827e9bd70896114a789c5eb68ef4c6d2d8b1b695323765cdd6c6d584a0f535
7
- data.tar.gz: '015298e7d0b7032889630f8a150405e6f9ee5bb568da96f30415da0d9d066b13bce38dee9e54cbe8abd3e669ca5c090868b3096d013c48b46398eacf4033003d'
6
+ metadata.gz: 55e5ffcfc30c9238cbe32909defe509b7a9dd919d80589cafcc24031acbd6559bd05c56aea57bd62dbbc06ae496b6787a087b3ac9a5306b141924884b6e5896a
7
+ data.tar.gz: 838eba52a5b8bc939c4c7ac5a541cc621f1f347f43f0354a591c973a13c33fea7a2cc79ea18e88f1f1bf0d41c4e34a27bebf418640bc1e5a8a4cb5fdbe3f1748
@@ -42,14 +42,11 @@
42
42
  .card-header, .card-footer {
43
43
  background-color: transparent;
44
44
  }
45
- .card-header, .card-footer, .card-body {
46
- border-top: 0 none;
47
- }
48
45
  .card-header {
49
46
  display: flex;
50
47
  align-items: center;
51
48
  height: 50px;
52
- border-bottom-color: $gray-50;
49
+ border-bottom: 1px solid $gray-50;
53
50
 
54
51
  .card-title {
55
52
  margin-bottom: 0;
@@ -125,7 +122,4 @@
125
122
  .card-body {
126
123
  border-top: 1px solid $gray-50;
127
124
  }
128
- .card-header {
129
- border: 0 none;
130
- }
131
125
  }
@@ -16,7 +16,7 @@
16
16
  display: flex;
17
17
  align-items: center;
18
18
  justify-content: space-between;
19
- padding-left: 0.75rem;
19
+ padding-left: 0.5rem;
20
20
  padding-right: 0.75rem;
21
21
  background-color: $sidebar-bg;
22
22
  width: $sidebar-width;
@@ -1,8 +1,8 @@
1
1
  // https://github.com/twbs/bootstrap/blob/v4.6.2/scss/_variables.scss
2
2
 
3
- $gray-25: #F9F9F9;
3
+ $gray-25: #FAFAFA;
4
4
  $gray-50: #F3F3F3;
5
- $gray-100: #E7E5E4 !default;
5
+ $gray-100: #EAEAEA !default;
6
6
  $gray-200: #D5D5D5 !default;
7
7
  $gray-300: #B3B3B3 !default;
8
8
  $gray-400: #999999 !default;
@@ -27,9 +27,9 @@ $container-max-widths: (
27
27
  sm: 540px,
28
28
  md: 720px,
29
29
  lg: 960px,
30
- xl: 1240px
30
+ xl: 1272px
31
31
  ) !default;
32
-
32
+ $grid-gutter-width: 16px !default;
33
33
 
34
34
  $theme-colors: (
35
35
  "white": $white,
@@ -171,6 +171,9 @@ strong {
171
171
  .cursor-not-allowed {
172
172
  cursor: not-allowed !important;
173
173
  }
174
+ .cursor-help {
175
+ cursor: help;
176
+ }
174
177
 
175
178
  .active {
176
179
  color: theme-color('primary');
@@ -445,6 +448,9 @@ small,
445
448
  .opacity-50 {
446
449
  opacity: 0.5;
447
450
  }
451
+ .opacity-75 {
452
+ opacity: 0.75;
453
+ }
448
454
  .opacity-0 {
449
455
  opacity: 0;
450
456
  }
@@ -0,0 +1,12 @@
1
+ module Spree
2
+ module Admin
3
+ module OrderBreadcrumbConcern
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ add_breadcrumb Spree.t(:orders), :admin_orders_path
8
+ add_breadcrumb_icon 'inbox'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -3,6 +3,7 @@ module Spree
3
3
  class OrdersController < Spree::Admin::BaseController
4
4
  include Spree::Admin::OrderConcern
5
5
  include Spree::Admin::OrdersFiltersHelper
6
+ include Spree::Admin::OrderBreadcrumbConcern
6
7
 
7
8
  before_action :initialize_order_events
8
9
  before_action :load_order, only: %i[edit cancel resend]
@@ -11,9 +12,6 @@ module Spree
11
12
 
12
13
  helper_method :model_class
13
14
 
14
- add_breadcrumb Spree.t(:orders), :admin_orders_path
15
- add_breadcrumb_icon 'inbox'
16
-
17
15
  def create
18
16
  @order = Spree::Order.create(created_by: try_spree_current_user, store: current_store)
19
17
 
@@ -66,7 +64,7 @@ module Spree
66
64
 
67
65
  def order_params
68
66
  params[:created_by_id] = try_spree_current_user.try(:id)
69
- params.permit(:created_by_id, :user_id, :store_id, :channel)
67
+ params.permit(:created_by_id, :user_id, :store_id, :channel, tag_list: [])
70
68
  end
71
69
 
72
70
  def load_order
@@ -47,7 +47,9 @@ module Spree
47
47
 
48
48
  def permitted_resource_params
49
49
  params.require(:page_block).permit(
50
- permitted_page_block_attributes + @object.preferences.keys.map { |key| "preferred_#{key}" }
50
+ permitted_page_block_attributes +
51
+ [link_attributes: permitted_page_link_attributes + [:id]] +
52
+ @object.preferences.keys.map { |key| "preferred_#{key}" }
51
53
  )
52
54
  end
53
55
  end
@@ -71,7 +71,11 @@ module Spree
71
71
  end
72
72
 
73
73
  def permitted_resource_params
74
- params.require(:page_section).permit(permitted_page_section_attributes + @object.preferences.keys.map { |key| "preferred_#{key}" })
74
+ params.require(:page_section).permit(
75
+ permitted_page_section_attributes +
76
+ [link_attributes: permitted_page_link_attributes + [:id]] +
77
+ @object.preferences.keys.map { |key| "preferred_#{key}" }
78
+ )
75
79
  end
76
80
  end
77
81
  end
@@ -14,10 +14,10 @@ module Spree
14
14
  if params[:payment_method].present?
15
15
  payment_type = params[:payment_method].delete(:type)
16
16
  # Find the actual class from our allowed types rather than using constantize
17
- payment_class = allowed_payment_types.find { |type| type.to_s == payment_type }
17
+ payment_class = allowed_payment_types.find { |type| type == payment_type }
18
18
 
19
- if payment_class
20
- @object = payment_class.new
19
+ if payment_class.present?
20
+ @object = payment_class.constantize.new
21
21
  end
22
22
  end
23
23
  end
@@ -45,7 +45,9 @@ module Spree
45
45
  end
46
46
 
47
47
  def allowed_payment_types
48
- Rails.application.config.spree.payment_methods
48
+ # We need to map to strings, otherwise some weird things happen with STI
49
+ # where Rails can't find the ancestor class when we try to save the payment method.
50
+ Rails.application.config.spree.payment_methods.map(&:to_s)
49
51
  end
50
52
 
51
53
  def permitted_resource_params
@@ -4,6 +4,12 @@ module Spree
4
4
  include StorefrontBreadcrumbConcern
5
5
  add_breadcrumb Spree.t(:posts), :admin_posts_path
6
6
  add_breadcrumb Spree.t(:categories), :admin_post_categories_path
7
+
8
+ private
9
+
10
+ def permitted_resource_params
11
+ params.require(:post_category).permit(permitted_post_category_attributes)
12
+ end
7
13
  end
8
14
  end
9
15
  end
@@ -35,6 +35,10 @@ module Spree
35
35
 
36
36
  add_breadcrumb @post.title, spree.edit_admin_post_path(@post)
37
37
  end
38
+
39
+ def permitted_resource_params
40
+ params.require(:post).permit(permitted_post_attributes)
41
+ end
38
42
  end
39
43
  end
40
44
  end
@@ -152,7 +152,7 @@ module Spree
152
152
  protected
153
153
 
154
154
  def find_resource
155
- current_store.products.accessible_by(current_ability, :manage).with_deleted.friendly.find(params[:id])
155
+ current_store.products.accessible_by(current_ability, :manage).friendly.find(params[:id])
156
156
  end
157
157
 
158
158
  def load_data
@@ -180,10 +180,10 @@ module Spree
180
180
  @product_options[option_type.id.to_s] = {
181
181
  name: option_type.presentation,
182
182
  position: index + 1,
183
- values: option_values.pluck(:presentation).uniq
183
+ values: option_values.pluck(:name, :presentation).uniq.map { |name, presentation| { value: name, text: presentation } }
184
184
  }
185
185
 
186
- @product_available_options[option_type.id.to_s] = option_type.option_values.to_tom_select_json
186
+ @product_available_options[option_type.id.to_s] = option_type.option_values.pluck(:name, :presentation).uniq.map { |name, presentation| { id: name, name: presentation } }
187
187
  end
188
188
 
189
189
  @product_stock = {}
@@ -274,7 +274,7 @@ module Spree
274
274
  for_ordering_with_translations(model_class, :name).
275
275
  includes(product_includes).
276
276
  page(params[:page]).
277
- per(params[:per_page] || ENV.fetch('ADMIN_PRODUCTS_PER_PAGE', 25))
277
+ per(params[:per_page] || Spree::Admin::RuntimeConfig.admin_products_per_page)
278
278
 
279
279
  @collection
280
280
  end
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  module Admin
3
3
  class RefundsController < ResourceController
4
+ include Spree::Admin::OrderBreadcrumbConcern
5
+
4
6
  belongs_to 'spree/payment', find_by: :number
5
7
 
6
8
  before_action :load_order
@@ -18,6 +20,8 @@ module Spree
18
20
 
19
21
  def load_order
20
22
  @order = @payment.order if @payment
23
+
24
+ add_breadcrumb @order.number, spree.edit_admin_order_path(@order)
21
25
  end
22
26
 
23
27
  def refund_reasons
@@ -11,7 +11,7 @@ module Spree
11
11
  before_action :refresh_shipping_rates, only: :edit
12
12
 
13
13
  def update
14
- @result = Spree::Dependencies.shipment_update_service.constantize.call(shipment: @shipment, shipment_attributes: shipment_params)
14
+ @result = Spree::Dependencies.shipment_update_service.constantize.call(shipment: @shipment, shipment_attributes: permitted_resource_params)
15
15
  flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:shipment)) if @result.success?
16
16
 
17
17
  redirect_back fallback_location: spree.edit_admin_order_path(@order)
@@ -94,7 +94,7 @@ module Spree
94
94
  @variant = current_store.variants.accessible_by(current_ability, :manage).find(params[:variant_id])
95
95
  end
96
96
 
97
- def shipment_params
97
+ def permitted_resource_params
98
98
  params.require(:shipment).permit(permitted_shipment_attributes)
99
99
  end
100
100
  end
@@ -263,7 +263,7 @@ module Spree
263
263
  # @param css [String] the css class of the help bubble
264
264
  # @return [String] the help bubble with the icon
265
265
  def help_bubble(text = '', placement = 'bottom', css: nil)
266
- css ||= 'text-muted'
266
+ css ||= 'text-muted opacity-75 cursor-help'
267
267
  content_tag :small, icon('info-square-rounded', class: css), data: { placement: placement }, class: "with-tip #{css}", title: text
268
268
  end
269
269
 
@@ -57,7 +57,7 @@ module Spree
57
57
  # lazy loading other models here (via includes) may result in an invalid query
58
58
  # e.g. SELECT DISTINCT DISTINCT "spree_orders".id, "spree_orders"."created_at" AS alias_0 FROM "spree_orders"
59
59
  # see https://github.com/spree/spree/pull/3919
60
- @orders = @search.result(distinct: true).page(params[:page]).per(params[:per_page])
60
+ @orders = @search.result(distinct: true).page(params[:page]).per(params[:per_page] || Spree::Admin::RuntimeConfig.admin_orders_per_page)
61
61
  end
62
62
 
63
63
  def load_user
@@ -26,8 +26,9 @@ export default class extends Controller {
26
26
  values() {
27
27
  return this.selectTargets
28
28
  .map((selectTarget) => selectTarget.querySelector('select'))
29
- .map((select) => select.options[select.selectedIndex].text)
30
- .filter((text) => text?.length > 0)
29
+ .map((select) => select.options[select.selectedIndex])
30
+ .filter((option) => option.value.length > 0)
31
+ .map((option) => ({ text: option.text, value: option.value}))
31
32
  }
32
33
 
33
34
  setValues() {
@@ -129,7 +129,7 @@ export default class extends CheckboxSelectAll {
129
129
  const nestingLevel = internalName.split('/').length
130
130
  if (nestingLevel === 1) {
131
131
  const firstOptionKey = Object.keys(this.optionsValue)[0]
132
- const newOptionValues = this.optionsValue[firstOptionKey].values.filter((value) => value !== internalName)
132
+ const newOptionValues = this.optionsValue[firstOptionKey].values.filter((value) => value.text !== internalName)
133
133
  if (newOptionValues.length === 0) {
134
134
  const newOptionsValue = this.optionsValue
135
135
  delete newOptionsValue[firstOptionKey]
@@ -265,12 +265,12 @@ export default class extends CheckboxSelectAll {
265
265
  let name = ''
266
266
  let internalName = name
267
267
  if (i === 0) {
268
- name = variant[keys[i]]
268
+ name = variant[keys[i]].text
269
269
  internalName = name
270
270
  } else {
271
- const namesPath = keys.slice(1, keys.length).map((key) => variant[key])
271
+ const namesPath = keys.slice(1, keys.length).map((key) => variant[key].text)
272
272
  name = namesPath.join(' / ')
273
- internalName = `${variant[keys[0]]}/${namesPath.join('/')}`
273
+ internalName = `${variant[keys[0]].text}/${namesPath.join('/')}`
274
274
  }
275
275
 
276
276
  return { name, internalName }
@@ -572,12 +572,12 @@ export default class extends CheckboxSelectAll {
572
572
  refreshParentInputs() {
573
573
  const firstOption = Object.values(this.optionsValue)[0]
574
574
  if (firstOption) {
575
- firstOption.values.forEach((name) => {
575
+ firstOption.values.forEach((option) => {
576
576
  this.currenciesValue.forEach((currency) => {
577
- this.updateParentPriceRange(name, currency)
577
+ this.updateParentPriceRange(option.text, currency)
578
578
  })
579
579
  this.stockLocationsValue.forEach((stockLocationId) => {
580
- this.updateParentStockSum(name, stockLocationId)
580
+ this.updateParentStockSum(option.text, stockLocationId)
581
581
  })
582
582
  this.updateShopLocationCountOnHand()
583
583
  })
@@ -615,11 +615,17 @@ export default class extends CheckboxSelectAll {
615
615
  .find((option) => option.name === key).position
616
616
  inputs.push(positionInput)
617
617
 
618
- const valueInput = document.createElement('input')
619
- valueInput.type = 'hidden'
620
- valueInput.name = `product[variants_attributes][${i}][options][][value]`
621
- valueInput.value = variant[key]
622
- inputs.push(valueInput)
618
+ const optionNameInput = document.createElement('input')
619
+ optionNameInput.type = 'hidden'
620
+ optionNameInput.name = `product[variants_attributes][${i}][options][][option_value_name]`
621
+ optionNameInput.value = variant[key].value
622
+ inputs.push(optionNameInput)
623
+
624
+ const optionIdInput = document.createElement('input')
625
+ optionIdInput.type = 'hidden'
626
+ optionIdInput.name = `product[variants_attributes][${i}][options][][option_value_presentation]`
627
+ optionIdInput.value = variant[key].text
628
+ inputs.push(optionIdInput)
623
629
  })
624
630
 
625
631
  return inputs
@@ -924,8 +930,8 @@ export default class extends CheckboxSelectAll {
924
930
  const optionValuesSelectContainer = template.querySelector('[data-slot="optionValuesSelectContainer"]')
925
931
  const tomSelectOptionValues = optionValues.map((optionValue) => {
926
932
  return {
927
- id: availableOptions.find((availableOption) => availableOption.name === optionValue)?.id,
928
- name: optionValue
933
+ id: optionValue.value,
934
+ name: optionValue.text,
929
935
  }
930
936
  })
931
937
 
@@ -948,8 +954,8 @@ export default class extends CheckboxSelectAll {
948
954
  values.forEach((value) => {
949
955
  const template = this.optionValueTemplateTarget.content.cloneNode(true)
950
956
  const optionValueNameEl = template.querySelector('[data-slot="optionValueName"]')
951
- optionValueNameEl.textContent = value
952
- optionValueNameEl.dataset.name = value
957
+ optionValueNameEl.textContent = value.text
958
+ optionValueNameEl.dataset.name = value.text
953
959
 
954
960
  templates.push(template)
955
961
  })
@@ -0,0 +1,14 @@
1
+ <% if @order.special_instructions.present? %>
2
+ <div class="card mb-4">
3
+ <div class="card-header">
4
+ <h5 class="card-title">
5
+ <%= I18n.t('activerecord.attributes.spree/order.special_instructions') %>
6
+ </h5>
7
+ </div>
8
+ <div class="card-body">
9
+ <div class="card-text">
10
+ <%= simple_format(@order.special_instructions) %>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ <% end %>
@@ -15,6 +15,7 @@
15
15
  </div>
16
16
  <div class="col-lg-4">
17
17
  <%= render 'customer' %>
18
+ <%= render 'special_instructions' %>
18
19
  <%= render_admin_partials(:order_page_sidebar_partials, order: @order) %>
19
20
  </div>
20
21
  </div>
@@ -33,7 +33,8 @@
33
33
  <%= link_to_with_icon 'credit-card-refund', Spree.t(:refund), spree.new_admin_order_payment_refund_path(@order, payment), class: 'dropdown-item' %>
34
34
  <% end %>
35
35
  <% if can?(:cancel, payment) && payment.pending? %>
36
- <%= link_to_with_icon 'cancel', Spree.t(:void), spree.void_admin_order_payment_path(@order, payment), class: 'dropdown-item', data: { turbo_method: :put, turbo_confirm: Spree.t(:are_you_sure) } %>
36
+ <div class="dropdown-divider"></div>
37
+ <%= link_to_with_icon 'cancel', Spree.t(:void), spree.void_admin_order_payment_path(@order, payment), class: 'dropdown-item btn-danger', data: { turbo_method: :put, turbo_confirm: Spree.t(:are_you_sure) } %>
37
38
  <% end %>
38
39
  <% if can?(:destroy, payment) && payment.can_be_deleted? %>
39
40
  <div class="dropdown-divider"></div>
@@ -3,7 +3,7 @@
3
3
  <div data-replace-target="from">
4
4
  <div readonly class="form-control d-flex align-items-center justify-content-between pr-1">
5
5
  <span class="text-muted">
6
- ...<%= form.object.send(field).last(4) %>
6
+ ...<%= form.object.send(field)&.last(4) %>
7
7
  </span>
8
8
  <button class="btn btn-sm btn-light" type="button" data-action="click->replace#replace">
9
9
  <%= icon 'edit', class: 'mr-2' %>
@@ -23,4 +23,4 @@
23
23
  <% else %>
24
24
  <%= form.password_field(field, preference_field_options(options)) %>
25
25
  <% end %>
26
- </div>
26
+ </div>
@@ -7,13 +7,14 @@
7
7
  <% end unless @product.has_variants? %>
8
8
  <%= render 'spree/admin/products/form/variants', f: f %>
9
9
  <%= render 'spree/admin/products/form/inventory', f: f unless @product.has_variants? %>
10
- <%= render 'spree/admin/products/form/shipping', f: f %>
11
10
  <%= render 'spree/admin/products/form/properties', f: f %>
12
11
  <%= render_admin_partials(:product_form_partials, f: f, product: @product) %>
13
12
  </div>
14
13
  <div class="col-md-4">
15
14
  <%= render 'spree/admin/products/form/status', f: f %>
16
15
  <%= render 'spree/admin/products/form/categorization', f: f %>
16
+ <%= render 'spree/admin/products/form/shipping', f: f %>
17
+ <%= render 'spree/admin/products/form/tax', f: f %>
17
18
  <%= render 'spree/admin/products/form/stores', f: f if available_stores.count > 1 %>
18
19
  <%= render_admin_partials(:product_form_sidebar_partials, f: f, product: @product) %>
19
20
 
@@ -15,8 +15,11 @@
15
15
  <%= sort_link @search,
16
16
  :name,
17
17
  Spree.t(:name),
18
- { default_order: "desc" },
19
- { title: "admin_products_listing_name_title" } %>
18
+ {
19
+ default_order: "desc",
20
+ title: "admin_products_listing_name_title"
21
+ }
22
+ %>
20
23
  </th>
21
24
  <th scope="col" class="text-center">
22
25
  <%= Spree.t(:status) %>
@@ -0,0 +1,12 @@
1
+ <div class="card mb-4">
2
+ <div class="card-header">
3
+ <h5 class="card-title"><%= Spree.t(:tax) %></h5>
4
+ </div>
5
+ <div class="card-body">
6
+ <div class="form-group">
7
+ <%= f.label :tax_category_id, Spree.t(:tax_category) %>
8
+ <%= f.select(:tax_category_id, @tax_categories.pluck(:name, :id), { include_blank: false }, { class: 'custom-select' }) %>
9
+ <%= f.error_message_on :tax_category %>
10
+ </div>
11
+ </div>
12
+ </div>
@@ -1,7 +1,5 @@
1
- <%= render 'spree/admin/orders/header' %>
2
-
3
- <div class="row">
4
- <div class="col-lg-6">
1
+ <div class="row mt-4">
2
+ <div class="col-lg-6 offset-lg-3">
5
3
  <%= render 'spree/admin/shared/error_messages', target: @refund %>
6
4
 
7
5
  <%= form_for [:admin, @refund.payment.order, @refund.payment, @refund] do |f| %>
@@ -11,7 +11,7 @@
11
11
  <h3 class="page-header-title mb-0 d-flex align-items-center gap-3">
12
12
  <%= yield :page_title %>
13
13
  </h3>
14
- <div id="page_actions" class="ml-auto page-actions d-flex align-items-center gap-3">
14
+ <div id="page_actions" class="ml-auto page-actions d-flex align-items-center gap-2">
15
15
  <% if action_name == 'index' && defined?(model_class) && model_class && Spree::Export.available_models.include?(model_class) && can?(:create, Spree::Export) %>
16
16
  <span data-toggle="modal" data-target="#modal">
17
17
  <%= link_to spree.new_admin_export_path(export: { search_params: params[:q]&.to_json, type: Spree::Export.type_for_model(model_class) }), class: 'btn btn-light bg-transparent with-tip', title: 'Download records as CSV file', data: { turbo_frame: :dialog_modal } do %>
@@ -1,3 +1,3 @@
1
1
  <template data-filters-target="badgeTemplate">
2
- <span class="badge py-1 px-2 bg-light text-dark d-flex-inline align-items-center mb-0">LABEL<a href="DELETE_URL" class="btn-close ml-2" title="Remove"></a></span>
2
+ <span class="badge py-0 pl-2 pr-0 bg-light text-dark d-flex-inline align-items-center mb-0">LABEL<a href="DELETE_URL" class="btn-close ml-2" title="<%= Spree.t('actions.remove') %>"></a></span>
3
3
  </template>
@@ -1,4 +1,4 @@
1
- <% orders_active = %[orders checkouts].include?(controller_name) || @order %>
1
+ <% orders_active = %[orders checkouts].include?(controller_name) || @order&.present? || @parent&.is_a?(Spree::Order) %>
2
2
  <% if can?(:manage, Spree::Order) %>
3
3
  <% orders_label = Spree.t(:orders) %>
4
4
  <% if ready_to_ship_orders_count&.positive? %>
@@ -1,6 +1,6 @@
1
- <% content_for :head do %>
2
- <script type="text/javascript" src="https://cdn.goentri.com/entri.js"></script>
3
- <% end if entri_enabled? %>
1
+ <%= content_for :page_actions do %>
2
+ <%= turbo_save_button_tag Spree.t('actions.update'), class: 'btn btn-primary', form: "edit_store_#{current_store.id}" %>
3
+ <% end %>
4
4
 
5
5
  <%= render partial: 'spree/admin/shared/error_messages', locals: { target: @store }, class: 'mb-5 pb-5' %>
6
6
 
@@ -31,18 +31,38 @@
31
31
  <div class="col-lg-5">
32
32
  <div class="card mb-4">
33
33
  <div class="card-header">
34
- <h5 class="card-title"><%= Spree.t(:guest_checkout) %></h5>
34
+ <h5 class="card-title"><%= Spree.t(:settings) %></h5>
35
35
  </div>
36
36
 
37
37
  <div class="card-body">
38
- <p class="text-muted">
39
- <%= Spree.t('admin.checkout_settings.guest_checkout.description') %>
40
- </p>
41
-
42
38
  <div class="custom-control custom-checkbox mb-3">
43
39
  <%= f.check_box :preferred_guest_checkout, class: "custom-control-input" %>
44
40
  <%= f.label :preferred_guest_checkout, Spree.t('admin.checkout_settings.guest_checkout.label'), class: "custom-control-label" %>
45
41
  <%= f.error_message_on :preferred_guest_checkout %>
42
+
43
+ <p class="text-muted mt-1">
44
+ <%= Spree.t('admin.checkout_settings.guest_checkout.description') %>
45
+ </p>
46
+ </div>
47
+
48
+ <div class="custom-control custom-checkbox mb-3">
49
+ <%= f.check_box :preferred_company_field_enabled, class: "custom-control-input" %>
50
+ <%= f.label :preferred_company_field_enabled, Spree.t('admin.store_form.company_field.label'), class: "custom-control-label" %>
51
+ <%= f.error_message_on :preferred_company_field_enabled %>
52
+
53
+ <div class="text-muted mt-1">
54
+ <%= Spree.t('admin.store_form.company_field.description') %>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="custom-control custom-checkbox">
59
+ <%= f.check_box :preferred_special_instructions_enabled, class: "custom-control-input" %>
60
+ <%= f.label :preferred_special_instructions_enabled, Spree.t('admin.checkout_settings.special_instructions.label'), class: "custom-control-label" %>
61
+ <%= f.error_message_on :preferred_special_instructions_enabled %>
62
+
63
+ <p class="text-muted mt-1">
64
+ <%= Spree.t('admin.checkout_settings.special_instructions.description') %>
65
+ </p>
46
66
  </div>
47
67
  </div>
48
68
  </div>
@@ -1,12 +1,12 @@
1
1
  <% cache variant do %>
2
- <% if variant.is_master? %>
2
+ <% if variant.is_master? || variant.product.deleted? %>
3
3
  <% variant_url = spree.edit_admin_product_path(variant.product) %>
4
4
  <% else %>
5
5
  <% variant_url = spree.edit_admin_product_variant_path(variant.product, variant) %>
6
6
  <% end %>
7
7
 
8
8
  <%= link_to variant_url, id: spree_dom_id(variant), data: { turbo_permanent: true, turbo_frame: :_top }, class: 'd-flex align-items-center justify-content-start text-decoration-none' do %>
9
- <%= render 'spree/admin/shared/product_image', object: variant %>
9
+ <%= render "spree/admin/shared/product_image", object: variant %>
10
10
  <div class="ml-3">
11
11
  <strong><%= variant.name %></strong>
12
12
  <% if variant.options_text.present? %>
@@ -5,22 +5,22 @@
5
5
  </h5>
6
6
  </div>
7
7
  <div class="card-body">
8
- <div class="form-group" data-hook="sku">
8
+ <div class="form-group">
9
9
  <%= f.label :sku, Spree.t(:sku) %>
10
10
  <%= f.text_field :sku, class: 'form-control' %>
11
11
  </div>
12
12
 
13
- <div class="form-group" data-hook="sku">
13
+ <div class="form-group">
14
14
  <%= f.label :barcode, Spree.t(:barcode) %>
15
15
  <%= f.text_field :barcode, class: 'form-control' %>
16
16
  </div>
17
17
 
18
- <div class="form-group" data-hook="tax_category">
18
+ <div class="form-group">
19
19
  <%= f.label :tax_category_id, Spree.t(:tax_category) %>
20
20
  <%= f.collection_select(:tax_category_id, @tax_categories, :id, :name, { include_blank: Spree.t('match_choices.none') }, { data: { controller: 'autocomplete-select' } }) %>
21
21
  </div>
22
22
 
23
- <div class="form-group" data-hook="discontinue_on">
23
+ <div class="form-group">
24
24
  <%= f.label :discontinue_on, Spree.t(:discontinue_on) %>
25
25
  <%= f.error_message_on :discontinue_on %>
26
26
  <%= f.date_field :discontinue_on, class: 'form-control' %>
@@ -43,6 +43,9 @@ en:
43
43
  description: Allow customers to checkout without creating an account.
44
44
  label: Allow guest checkout
45
45
  policy_copy: Checkout footer links are added automatically based on the %{policies_link} content.
46
+ special_instructions:
47
+ description: Allow customers to add special instructions to their order.
48
+ label: Display the special instructions field
46
49
  copied: Copied!
47
50
  copy_payment_link: Copy Payment Link
48
51
  copy_to_clipboard: Copy to clipboard
@@ -193,6 +196,9 @@ en:
193
196
  store_credit:
194
197
  amount_remaining_of_total: "<strong>%{amount}</strong> remaining (<strong>%{total}</strong> total)"
195
198
  store_form:
199
+ company_field:
200
+ description: It shows the company field on the address form in the My Account section and on the checkout address step.
201
+ label: Display the company address field
196
202
  customer_support_email_help: This email is visible to your Store visitors in the Footer section
197
203
  new_order_notifications_email_help: If you want to receive an email notification every time someone places an Order please provide an email address for that notification to be sent to
198
204
  store_setup_tasks:
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ module Admin
3
+ module TestingSupport
4
+ module TomSelect
5
+ def tom_select(value, from:, create: false)
6
+ fill_in(from, with: value, visible: false)
7
+
8
+ if create
9
+ first('.ts-dropdown .ts-dropdown-content .create.active').click
10
+ else
11
+ first('.ts-dropdown .ts-dropdown-content .option', text: /#{Regexp.quote(value)}/i).click
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
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.1.0.beta2
4
+ version: 5.1.0.beta4
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: 2025-05-22 00:00:00.000000000 Z
11
+ date: 2025-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree_core
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 5.1.0.beta2
19
+ version: 5.1.0.beta4
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.1.0.beta2
26
+ version: 5.1.0.beta4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: spree_api
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 5.1.0.beta2
33
+ version: 5.1.0.beta4
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 5.1.0.beta2
40
+ version: 5.1.0.beta4
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: active_link_to
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -328,6 +328,7 @@ files:
328
328
  - app/controllers/concerns/spree/admin/analytics_concern.rb
329
329
  - app/controllers/concerns/spree/admin/breadcrumb_concern.rb
330
330
  - app/controllers/concerns/spree/admin/bulk_operations_concern.rb
331
+ - app/controllers/concerns/spree/admin/order_breadcrumb_concern.rb
331
332
  - app/controllers/concerns/spree/admin/order_concern.rb
332
333
  - app/controllers/concerns/spree/admin/page_builder_concern.rb
333
334
  - app/controllers/concerns/spree/admin/preferences_concern.rb
@@ -601,6 +602,7 @@ files:
601
602
  - app/views/spree/admin/orders/_shipment.html.erb
602
603
  - app/views/spree/admin/orders/_shipment_manifest_item.html.erb
603
604
  - app/views/spree/admin/orders/_shipments.html.erb
605
+ - app/views/spree/admin/orders/_special_instructions.html.erb
604
606
  - app/views/spree/admin/orders/_summary.html.erb
605
607
  - app/views/spree/admin/orders/_summary_custom.html.erb
606
608
  - app/views/spree/admin/orders/_table_filter_dropdown.html.erb
@@ -789,6 +791,7 @@ files:
789
791
  - app/views/spree/admin/products/form/_shipping.html.erb
790
792
  - app/views/spree/admin/products/form/_status.html.erb
791
793
  - app/views/spree/admin/products/form/_stores.html.erb
794
+ - app/views/spree/admin/products/form/_tax.html.erb
792
795
  - app/views/spree/admin/products/form/_variants.html.erb
793
796
  - app/views/spree/admin/products/form/variants/_option_template.html.erb
794
797
  - app/views/spree/admin/products/form/variants/_variant_template.html.erb
@@ -1083,6 +1086,7 @@ files:
1083
1086
  - lib/spree/admin/engine.rb
1084
1087
  - lib/spree/admin/runtime_configuration.rb
1085
1088
  - lib/spree/admin/testing_support/capybara_utils.rb
1089
+ - lib/spree/admin/testing_support/tom_select.rb
1086
1090
  - lib/spree_admin.rb
1087
1091
  - vendor/javascript/@easepick--base-plugin.js
1088
1092
  - vendor/javascript/@easepick--core.js
@@ -1115,9 +1119,9 @@ licenses:
1115
1119
  - AGPL-3.0-or-later
1116
1120
  metadata:
1117
1121
  bug_tracker_uri: https://github.com/spree/spree/issues
1118
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.1.0.beta2
1122
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.1.0.beta4
1119
1123
  documentation_uri: https://docs.spreecommerce.org/
1120
- source_code_uri: https://github.com/spree/spree/tree/v5.1.0.beta2
1124
+ source_code_uri: https://github.com/spree/spree/tree/v5.1.0.beta4
1121
1125
  post_install_message:
1122
1126
  rdoc_options: []
1123
1127
  require_paths: