spree_admin 5.3.3 → 5.3.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f53aab5bf5de0f40206a80c2a2375cc915973139dec1a0ca669a36f4d98a6469
4
- data.tar.gz: c3c5c6babf054c33dc7027464c9c38bc5e27eb1fcb41d7ff4891a223291dcde0
3
+ metadata.gz: 50a1165ee32d40280a53a301cc00059012380a2c0fd27e5ef6933ee074bd50b8
4
+ data.tar.gz: 4282e3887a4f1a32e13ec9611cf9d02377c5fd98ec153361d0f635bbd25e64b0
5
5
  SHA512:
6
- metadata.gz: 30e6161df15f8ba37bfe8b41c7920f63352f344cf7176941a44ce0d43952347ac22aca27d2ddb9209e6423bebb5f089b0b9c9cf51238752ff25552e9ca8440f6
7
- data.tar.gz: 6a14594a4adf0b59a58f0dcae7607e0e65bc945bd99134895889ba312e26a56702712f25f148879b48d250d2edb27c026f89d9ad2b3824a6aac50930852d9c77
6
+ metadata.gz: 74520ef7ba4d6f284ecf05f024bdfb835ccfa27b91fb564330bd5d45c42c857527d24adc0aa76e54403685d3387280ebfc431205544f59e34cc1318575ad3adc
7
+ data.tar.gz: d1fc1d04175d7baed961400407b43a9efa040a79f7e94d3902597bce0712258df8418737a4ba9539409350ed73933e9d435c4c65f6339c50a2a68df727a7c660
@@ -230,7 +230,7 @@ module Spree
230
230
  # @return [String] JSON string
231
231
  def query_builder_fields_json(table)
232
232
  query_builder = Spree::Admin::Table::QueryBuilder.new(table)
233
- query_builder.available_fields.to_json
233
+ query_builder.available_fields(self).to_json
234
234
  end
235
235
 
236
236
  # Build available operators JSON for Stimulus controller
@@ -79,21 +79,16 @@ export default class extends Controller {
79
79
  this.boundHandleBeforeUnload = this.handleBeforeUnload.bind(this)
80
80
  this.boundHandleMouseUp = this.handleMouseUp.bind(this)
81
81
  this.boundHandleMouseMove = this.handleMouseMove.bind(this)
82
- this.boundNormalizeBeforeSubmit = this.normalizeBeforeSubmit.bind(this)
83
82
 
84
83
  window.addEventListener('beforeunload', this.boundHandleBeforeUnload)
85
84
  document.addEventListener('mouseup', this.boundHandleMouseUp)
86
85
  document.addEventListener('mousemove', this.boundHandleMouseMove)
87
-
88
- // Listen for form submission to normalize values
89
- this.element.addEventListener('submit', this.boundNormalizeBeforeSubmit)
90
86
  }
91
87
 
92
88
  disconnect() {
93
89
  window.removeEventListener('beforeunload', this.boundHandleBeforeUnload)
94
90
  document.removeEventListener('mouseup', this.boundHandleMouseUp)
95
91
  document.removeEventListener('mousemove', this.boundHandleMouseMove)
96
- this.element.removeEventListener('submit', this.boundNormalizeBeforeSubmit)
97
92
  }
98
93
 
99
94
  // ==================== Fill Handle ====================
@@ -783,85 +778,4 @@ export default class extends Controller {
783
778
  return this.dirtyInputs.size > 0
784
779
  }
785
780
 
786
- // ==================== Locale-aware Number Handling ====================
787
-
788
- /**
789
- * Normalizes a locale-formatted number string to standard decimal format
790
- * e.g., "1.234,56" (German) -> "1234.56"
791
- * e.g., "1,234.56" (English) -> "1234.56"
792
- * @param {string} value - The locale-formatted number string
793
- * @returns {string} The normalized number string with "." as decimal separator
794
- */
795
- normalizeNumber(value) {
796
- if (value === null || value === undefined) return ''
797
-
798
- let stringValue = String(value).trim()
799
- if (stringValue === '') return ''
800
-
801
- // Detect the decimal separator by finding the last separator character
802
- // This handles both "1,234.56" (en) and "1.234,56" (de/pl) formats
803
- const lastComma = stringValue.lastIndexOf(',')
804
- const lastDot = stringValue.lastIndexOf('.')
805
-
806
- let decimalSeparator = '.'
807
- let thousandsSeparator = ','
808
-
809
- // If comma comes after dot, comma is the decimal separator (European format)
810
- // Also treat comma as decimal if there's no dot and comma has 1-2 digits after it
811
- if (lastComma > lastDot) {
812
- decimalSeparator = ','
813
- thousandsSeparator = '.'
814
- } else if (lastDot === -1 && lastComma !== -1) {
815
- // No dot present, check if comma looks like a decimal separator
816
- // (has 1-3 digits after it, typical for currency)
817
- const afterComma = stringValue.substring(lastComma + 1)
818
- if (/^\d{1,3}$/.test(afterComma)) {
819
- decimalSeparator = ','
820
- thousandsSeparator = '.'
821
- }
822
- }
823
-
824
- // Remove thousands separators
825
- stringValue = stringValue.split(thousandsSeparator).join('')
826
-
827
- // Replace decimal separator with standard "."
828
- if (decimalSeparator !== '.') {
829
- stringValue = stringValue.replace(decimalSeparator, '.')
830
- }
831
-
832
- // Remove any non-numeric characters except "." and "-"
833
- stringValue = stringValue.replace(/[^0-9.\-]/g, '')
834
-
835
- return stringValue
836
- }
837
-
838
- /**
839
- * Formats a number for display using the configured locale
840
- * @param {number|string} value - The number to format
841
- * @returns {string} The formatted number string
842
- */
843
- formatNumber(value) {
844
- if (value === null || value === undefined || value === '') return ''
845
-
846
- const number = parseFloat(value)
847
- if (!Number.isFinite(number)) return ''
848
-
849
- return number.toLocaleString(this.localeValue, {
850
- minimumFractionDigits: 2,
851
- maximumFractionDigits: 2,
852
- useGrouping: false
853
- })
854
- }
855
-
856
- /**
857
- * Normalizes all cell values before form submission
858
- * @param {Event} event - The form submit event
859
- */
860
- normalizeBeforeSubmit(event) {
861
- this.cellTargets.forEach((cell) => {
862
- if (cell.value) {
863
- cell.value = this.normalizeNumber(cell.value)
864
- }
865
- })
866
- }
867
781
  }
@@ -4,11 +4,10 @@ import { Controller } from '@hotwired/stimulus'
4
4
  * MoneyFieldController
5
5
  *
6
6
  * A Stimulus controller for locale-aware money/price input fields.
7
- * Handles formatting for display and normalizing values before form submission.
7
+ * Handles formatting values for display in the user's locale format.
8
8
  *
9
9
  * Features:
10
10
  * - Displays amounts in the user's locale format (e.g., "1.234,56" for German, "1,234.56" for English)
11
- * - Normalizes values to standard decimal format (with "." as decimal separator) before form submission
12
11
  * - Supports optional currency symbol display
13
12
  *
14
13
  * Usage:
@@ -32,23 +31,10 @@ export default class extends Controller {
32
31
  }
33
32
 
34
33
  connect() {
35
- this.form = this.element.closest('form')
36
-
37
- if (this.form) {
38
- this.boundNormalizeBeforeSubmit = this.normalizeBeforeSubmit.bind(this)
39
- this.form.addEventListener('submit', this.boundNormalizeBeforeSubmit)
40
- }
41
-
42
34
  // Format the initial value for display
43
35
  this.formatForDisplay()
44
36
  }
45
37
 
46
- disconnect() {
47
- if (this.form && this.boundNormalizeBeforeSubmit) {
48
- this.form.removeEventListener('submit', this.boundNormalizeBeforeSubmit)
49
- }
50
- }
51
-
52
38
  /**
53
39
  * Called on blur to format the value for display
54
40
  */
@@ -139,12 +125,4 @@ export default class extends Controller {
139
125
  return stringValue
140
126
  }
141
127
 
142
- /**
143
- * Normalizes the value before form submission
144
- * @param {Event} event - The form submit event
145
- */
146
- normalizeBeforeSubmit(event) {
147
- const normalizedValue = this.normalizeValue(this.element.value)
148
- this.element.value = normalizedValue
149
- }
150
128
  }
@@ -33,7 +33,6 @@ export default class extends CheckboxSelectAll {
33
33
  prices: Object,
34
34
  currentCurrency: String,
35
35
  currencies: Array,
36
- currencyFormats: Object,
37
36
  variantIds: Object,
38
37
  currentStockLocationId: String,
39
38
  stockLocations: Array,
@@ -71,19 +70,6 @@ export default class extends CheckboxSelectAll {
71
70
  }
72
71
 
73
72
  this.inventoryFormTarget = document.querySelector('.inventory-form');
74
-
75
- // Add form submit listener to normalize price inputs before submission
76
- this.form = this.element.closest('form')
77
- if (this.form) {
78
- this.boundNormalizePricesBeforeSubmit = this.normalizePricesBeforeSubmit.bind(this)
79
- this.form.addEventListener('submit', this.boundNormalizePricesBeforeSubmit)
80
- }
81
- }
82
-
83
- disconnect() {
84
- if (this.form && this.boundNormalizePricesBeforeSubmit) {
85
- this.form.removeEventListener('submit', this.boundNormalizePricesBeforeSubmit)
86
- }
87
73
  }
88
74
 
89
75
  toggleQuantityTracked() {
@@ -387,6 +373,16 @@ export default class extends CheckboxSelectAll {
387
373
  }
388
374
  }
389
375
 
376
+ formatPrice(event) {
377
+ const value = event.target.value
378
+ if (value === '' || value === null) return
379
+
380
+ const number = this.parseLocaleNumber(value)
381
+ if (!Number.isFinite(number)) return
382
+
383
+ event.target.value = this.formatNumber(number)
384
+ }
385
+
390
386
  replaceBlankWithZero(event) {
391
387
  if (event.target.value === '') {
392
388
  event.target.value = 0
@@ -1100,13 +1096,13 @@ export default class extends CheckboxSelectAll {
1100
1096
  if (existingPrice) {
1101
1097
  return {
1102
1098
  ...existingPrice,
1103
- amount: existingPrice.amount ? parseFloat(existingPrice.amount) : existingPrice.amount
1099
+ amount: existingPrice.amount ? this.parseLocaleNumber(existingPrice.amount) : existingPrice.amount
1104
1100
  }
1105
1101
  } else {
1106
1102
  const parentName = variantName.split('/')[0]
1107
1103
  const parentPrices = Object.entries(this.pricesValue)
1108
1104
  .filter(([internalName, prices]) => internalName.startsWith(parentName) && prices[currency.toLowerCase()] !== undefined)
1109
- .map(([_key, prices]) => parseFloat(prices[currency.toLowerCase()].amount))
1105
+ .map(([_key, prices]) => this.parseLocaleNumber(prices[currency.toLowerCase()].amount))
1110
1106
  .sort((priceAmountA, priceAmountB) => priceAmountA - priceAmountB)
1111
1107
 
1112
1108
  return {
@@ -1124,7 +1120,7 @@ export default class extends CheckboxSelectAll {
1124
1120
  ...this.pricesValue[variantName],
1125
1121
  [currency.toLowerCase()]: {
1126
1122
  ...existingPrice,
1127
- amount: parseFloat(newPrice)
1123
+ amount: this.parseLocaleNumber(newPrice)
1128
1124
  }
1129
1125
  }
1130
1126
  }
@@ -1148,23 +1144,13 @@ export default class extends CheckboxSelectAll {
1148
1144
  }
1149
1145
  }
1150
1146
 
1151
- formatNumber(value, currency = null) {
1147
+ formatNumber(value) {
1152
1148
  if (value === null) return ''
1153
1149
  if (typeof value === 'string' && value.trim() === '') return ''
1154
1150
 
1155
1151
  const number = Number(value)
1156
1152
  if (!Number.isFinite(number)) return ''
1157
1153
 
1158
- // Use currency-specific decimal mark if available
1159
- const currencyCode = currency || this.currentCurrencyValue
1160
- const currencyFormat = this.currencyFormatsValue?.[currencyCode]
1161
-
1162
- if (currencyFormat?.decimal_mark) {
1163
- // Format with 2 decimal places and replace . with currency's decimal mark
1164
- return number.toFixed(2).replace('.', currencyFormat.decimal_mark)
1165
- }
1166
-
1167
- // Fallback to locale-based formatting
1168
1154
  return number.toLocaleString(this.localeValue, {
1169
1155
  minimumFractionDigits: 2,
1170
1156
  maximumFractionDigits: 2,
@@ -1172,70 +1158,22 @@ export default class extends CheckboxSelectAll {
1172
1158
  })
1173
1159
  }
1174
1160
 
1175
- /**
1176
- * Normalizes a locale-formatted number string to standard decimal format
1177
- * e.g., "1.234,56" (German) -> "1234.56"
1178
- * e.g., "30,99" (Polish) -> "30.99"
1179
- * @param {string} value - The locale-formatted number string
1180
- * @returns {string} The normalized number string with "." as decimal separator
1181
- */
1182
- normalizeNumber(value) {
1183
- if (value === null || value === undefined) return ''
1184
-
1185
- let stringValue = String(value).trim()
1186
- if (stringValue === '') return ''
1187
-
1188
- // Detect the decimal separator by finding the last separator character
1189
- // This handles both "1,234.56" (en) and "1.234,56" (de/pl) formats
1190
- const lastComma = stringValue.lastIndexOf(',')
1191
- const lastDot = stringValue.lastIndexOf('.')
1192
-
1193
- let decimalSeparator = '.'
1194
- let thousandsSeparator = ','
1195
-
1196
- // If comma comes after dot, comma is the decimal separator (European format)
1197
- // Also treat comma as decimal if there's no dot and comma has 1-3 digits after it
1198
- if (lastComma > lastDot) {
1199
- decimalSeparator = ','
1200
- thousandsSeparator = '.'
1201
- } else if (lastDot === -1 && lastComma !== -1) {
1202
- // No dot present, check if comma looks like a decimal separator
1203
- // (has 1-3 digits after it, typical for currency)
1204
- const afterComma = stringValue.substring(lastComma + 1)
1205
- if (/^\d{1,3}$/.test(afterComma)) {
1206
- decimalSeparator = ','
1207
- thousandsSeparator = '.'
1208
- }
1209
- }
1161
+ parseLocaleNumber(value) {
1162
+ if (value === null || value === undefined) return NaN
1210
1163
 
1211
- // Remove thousands separators
1212
- stringValue = stringValue.split(thousandsSeparator).join('')
1164
+ let str = String(value).trim()
1165
+ if (str === '') return NaN
1213
1166
 
1214
- // Replace decimal separator with standard "."
1215
- if (decimalSeparator !== '.') {
1216
- stringValue = stringValue.replace(decimalSeparator, '.')
1217
- }
1167
+ const lastComma = str.lastIndexOf(',')
1168
+ const lastDot = str.lastIndexOf('.')
1218
1169
 
1219
- // Remove any non-numeric characters except "." and "-"
1220
- stringValue = stringValue.replace(/[^0-9.\-]/g, '')
1170
+ if (lastComma > lastDot) {
1171
+ str = str.replace(/\./g, '').replace(',', '.')
1172
+ } else if (lastDot === -1 && lastComma !== -1 && /^\d{1,3}$/.test(str.substring(lastComma + 1))) {
1173
+ str = str.replace(',', '.')
1174
+ }
1221
1175
 
1222
- return stringValue
1176
+ return parseFloat(str)
1223
1177
  }
1224
1178
 
1225
- /**
1226
- * Normalizes all price inputs in the variants form before submission
1227
- * @param {Event} event - The form submit event
1228
- */
1229
- normalizePricesBeforeSubmit(event) {
1230
- // Find all price inputs in the variants container
1231
- const priceInputs = this.variantsContainerTarget.querySelectorAll(
1232
- 'input[data-slot*="[prices_attributes]"][data-slot*="[amount]_input"]'
1233
- )
1234
-
1235
- priceInputs.forEach((input) => {
1236
- if (input.value) {
1237
- input.value = this.normalizeNumber(input.value)
1238
- }
1239
- })
1240
- }
1241
1179
  }
@@ -42,7 +42,7 @@ module Spree
42
42
  attribute :ransack_attribute, :string
43
43
  attribute :operators, default: -> { [] }
44
44
  attribute :value_options
45
- attribute :search_url, :string
45
+ attribute :search_url
46
46
  attribute :sort_scope_asc
47
47
  attribute :sort_scope_desc
48
48
 
@@ -70,8 +70,9 @@ module Spree
70
70
  end
71
71
 
72
72
  # Get available fields for filtering based on table configuration
73
+ # @param view_context [ActionView::Base] optional view context for resolving dynamic URLs
73
74
  # @return [Array<Hash>]
74
- def available_fields
75
+ def available_fields(view_context = nil)
75
76
  @table.filterable_columns.map do |column|
76
77
  {
77
78
  key: column.ransack_attribute,
@@ -79,7 +80,7 @@ module Spree
79
80
  type: column.filter_type.to_s,
80
81
  operators: column.operators.map(&:to_s),
81
82
  value_options: format_value_options(column.value_options),
82
- search_url: column.search_url
83
+ search_url: resolve_search_url(column.search_url, view_context)
83
84
  }
84
85
  end
85
86
  end
@@ -92,6 +93,10 @@ module Spree
92
93
 
93
94
  private
94
95
 
96
+ def resolve_search_url(search_url, view_context)
97
+ search_url.is_a?(Proc) ? search_url.call(view_context) : search_url
98
+ end
99
+
95
100
  def format_value_options(options)
96
101
  return nil if options.blank?
97
102
 
@@ -5,21 +5,11 @@
5
5
  </div>
6
6
  <% option_types_for_select = @option_types.pluck(:presentation, :id) %>
7
7
  <div class="card-body p-0">
8
- <%# Build currency format info for JavaScript %>
9
- <% currency_formats = supported_currencies.each_with_object({}) do |currency, hash|
10
- currency_obj = ::Money::Currency.find(currency)
11
- hash[currency.to_s] = {
12
- decimal_mark: currency_obj.decimal_mark,
13
- thousands_separator: currency_obj.thousands_separator,
14
- symbol: currency_obj.symbol
15
- }
16
- end %>
17
8
  <div
18
9
  data-controller="variants-form"
19
10
  class="variants-form"
20
11
  data-action="product-form:toggle-quantity-tracked@window->variants-form#toggleQuantityTracked"
21
12
  data-variants-form-locale-value="<%= I18n.locale %>"
22
- data-variants-form-currency-formats-value="<%= currency_formats.to_json %>"
23
13
  <% if @product.persisted? %> data-variants-form-product-id-value="<%= @product.slug %>" <% end %>
24
14
  data-variants-form-current-currency-value="<%= current_currency %>"
25
15
  data-variants-form-currencies-value="<%= supported_currencies.map(&:to_s).to_json %>"
@@ -18,7 +18,7 @@
18
18
  <div class="variants-table__body__cell column-price mr-2">
19
19
  <% supported_currencies.each_with_index do |currency, i| %>
20
20
  <div class="input-group price-input-container <%= current_currency != currency ? 'hidden' : 'flex' %>" <%= !can_manage_prices ? 'readonly' : '' %>>
21
- <%= 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', currency: currency.to_s }, readonly: !can_manage_prices %>
21
+ <%= 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 %>
22
22
  <span class="px-3"><%= currency_symbol(currency) %></span>
23
23
  </div>
24
24
  <%= hidden_field_tag "product[variants_attributes][prices_attributes][#{i}][currency]", currency, data: {slot: "[prices_attributes][#{currency}][currency]_input"} %>
@@ -6,11 +6,10 @@
6
6
  <% search_placeholder = (table.respond_to?(:search_placeholder) && table.search_placeholder) || [Spree.t(:search), controller_name.humanize.downcase].join(' ') %>
7
7
  <% date_range_param = table.date_range_param %>
8
8
 
9
- <% if export_type.present? %>
10
- <%= render 'spree/admin/shared/export_modal', export_type: export_type %>
11
- <% end %>
12
-
13
9
  <%= turbo_frame_tag frame_name, data: { turbo_action: 'advance' } do %>
10
+ <% if export_type.present? %>
11
+ <%= render 'spree/admin/shared/export_modal', export_type: export_type %>
12
+ <% end %>
14
13
  <div class="<%= local_assigns[:container_class] || 'card-lg' %>" data-controller="table" data-table-url-value="<%= request.path %>">
15
14
  <div class="p-3 border-b border-gray-200">
16
15
  <div class="flex flex-col lg:flex-row gap-3 items-start lg:items-center justify-between">
@@ -111,7 +111,7 @@ Rails.application.config.after_initialize do
111
111
  position: 80,
112
112
  ransack_attribute: 'taxons_id',
113
113
  operators: %i[in],
114
- search_url: '/admin/taxons/select_options.json',
114
+ search_url: ->(view_context) { view_context.spree.admin_taxons_select_options_path(format: :json) },
115
115
  method: ->(product) { product.taxons.pluck(:pretty_name).to_sentence if product.classification_count.positive? }
116
116
 
117
117
  # Tags - displayed as comma-separated list, filtered via autocomplete
@@ -125,14 +125,14 @@ Rails.application.config.after_initialize do
125
125
  position: 85,
126
126
  ransack_attribute: 'tags_name',
127
127
  operators: %i[in],
128
- search_url: '/admin/tags/select_options.json?taggable_type=Spree::Product',
128
+ search_url: ->(view_context) { view_context.spree.admin_tags_select_options_path(format: :json, taggable_type: 'Spree::Product') },
129
129
  method: ->(product) { product.tag_list.to_sentence }
130
130
 
131
131
  # Products bulk actions
132
132
  Spree.admin.tables.products.add_bulk_action :set_active,
133
133
  label: 'admin.bulk_ops.products.title.set_active',
134
134
  icon: 'circle-check',
135
- action_path: '/admin/products/bulk_status_update?status=active',
135
+ action_path: ->(view_context) { view_context.spree.bulk_status_update_admin_products_path(status: 'active') },
136
136
  body: 'admin.bulk_ops.products.body.set_active',
137
137
  position: 10,
138
138
  condition: -> { can?(:activate, Spree::Product) }
@@ -140,21 +140,21 @@ Rails.application.config.after_initialize do
140
140
  Spree.admin.tables.products.add_bulk_action :set_draft,
141
141
  label: 'admin.bulk_ops.products.title.set_draft',
142
142
  icon: 'circle-dotted',
143
- action_path: '/admin/products/bulk_status_update?status=draft',
143
+ action_path: ->(view_context) { view_context.spree.bulk_status_update_admin_products_path(status: 'draft') },
144
144
  body: 'admin.bulk_ops.products.body.set_draft',
145
145
  position: 20
146
146
 
147
147
  Spree.admin.tables.products.add_bulk_action :set_archived,
148
148
  label: 'admin.bulk_ops.products.title.set_archived',
149
149
  icon: 'archive',
150
- action_path: '/admin/products/bulk_status_update?status=archived',
150
+ action_path: ->(view_context) { view_context.spree.bulk_status_update_admin_products_path(status: 'archived') },
151
151
  body: 'admin.bulk_ops.products.body.set_archived',
152
152
  position: 30
153
153
 
154
154
  Spree.admin.tables.products.add_bulk_action :add_to_taxons,
155
155
  label: 'admin.bulk_ops.products.title.add_to_taxons',
156
156
  icon: 'category-plus',
157
- action_path: '/admin/products/bulk_add_to_taxons',
157
+ action_path: ->(view_context) { view_context.spree.bulk_add_to_taxons_admin_products_path },
158
158
  body: 'admin.bulk_ops.products.body.add_to_taxons',
159
159
  form_partial: 'spree/admin/bulk_operations/forms/taxon_picker',
160
160
  position: 40,
@@ -163,7 +163,7 @@ Rails.application.config.after_initialize do
163
163
  Spree.admin.tables.products.add_bulk_action :remove_from_taxons,
164
164
  label: 'admin.bulk_ops.products.title.remove_from_taxons',
165
165
  icon: 'category-minus',
166
- action_path: '/admin/products/bulk_remove_from_taxons',
166
+ action_path: ->(view_context) { view_context.spree.bulk_remove_from_taxons_admin_products_path },
167
167
  body: 'admin.bulk_ops.products.body.remove_from_taxons',
168
168
  form_partial: 'spree/admin/bulk_operations/forms/taxon_picker',
169
169
  position: 50,
@@ -172,7 +172,7 @@ Rails.application.config.after_initialize do
172
172
  Spree.admin.tables.products.add_bulk_action :add_tags,
173
173
  label: 'admin.bulk_ops.products.title.add_tags',
174
174
  icon: 'tag-plus',
175
- action_path: '/admin/products/bulk_add_tags',
175
+ action_path: ->(view_context) { view_context.spree.bulk_add_tags_admin_products_path },
176
176
  body: 'admin.bulk_ops.products.body.add_tags',
177
177
  form_partial: 'spree/admin/bulk_operations/forms/tag_picker',
178
178
  form_partial_locals: { allow_create: true },
@@ -182,7 +182,7 @@ Rails.application.config.after_initialize do
182
182
  Spree.admin.tables.products.add_bulk_action :remove_tags,
183
183
  label: 'admin.bulk_ops.products.title.remove_tags',
184
184
  icon: 'tag-minus',
185
- action_path: '/admin/products/bulk_remove_tags',
185
+ action_path: ->(view_context) { view_context.spree.bulk_remove_tags_admin_products_path },
186
186
  body: 'admin.bulk_ops.products.body.remove_tags',
187
187
  form_partial: 'spree/admin/bulk_operations/forms/tag_picker',
188
188
  form_partial_locals: { allow_create: false },
@@ -348,7 +348,7 @@ Rails.application.config.after_initialize do
348
348
  position: 150,
349
349
  ransack_attribute: 'promotions_id',
350
350
  operators: %i[in],
351
- search_url: '/admin/promotions/select_options.json'
351
+ search_url: ->(view_context) { view_context.spree.select_options_admin_promotions_path(format: :json) }
352
352
 
353
353
  # Register Checkouts table (draft orders)
354
354
  Spree.admin.tables.register(:checkouts, model_class: Spree::Order, search_param: :multi_search, date_range_param: :created_at, new_resource: false)
@@ -462,7 +462,7 @@ Rails.application.config.after_initialize do
462
462
  position: 30,
463
463
  ransack_attribute: 'addresses_country_name',
464
464
  operators: %i[eq],
465
- search_url: '/admin/countries/select_options.json',
465
+ search_url: ->(view_context) { view_context.spree.admin_countries_select_options_path(format: :json) },
466
466
  partial: 'spree/admin/tables/columns/user_location'
467
467
 
468
468
  # Number of orders
@@ -533,13 +533,13 @@ Rails.application.config.after_initialize do
533
533
  position: 90,
534
534
  ransack_attribute: 'tags_name',
535
535
  operators: %i[in],
536
- search_url: '/admin/tags/select_options.json?taggable_type=Spree::User'
536
+ search_url: ->(view_context) { view_context.spree.admin_tags_select_options_path(format: :json, taggable_type: 'Spree::User') }
537
537
 
538
538
  # Users bulk actions
539
539
  Spree.admin.tables.users.add_bulk_action :add_tags,
540
540
  label: 'admin.bulk_ops.users.title.add_tags',
541
541
  icon: 'tag-plus',
542
- action_path: '/admin/users/bulk_add_tags',
542
+ action_path: ->(view_context) { view_context.spree.bulk_add_tags_admin_users_path },
543
543
  body: 'admin.bulk_ops.users.body.add_tags',
544
544
  form_partial: 'spree/admin/bulk_operations/forms/tag_picker',
545
545
  form_partial_locals: { allow_create: true },
@@ -550,7 +550,7 @@ Rails.application.config.after_initialize do
550
550
  Spree.admin.tables.users.add_bulk_action :remove_tags,
551
551
  label: 'admin.bulk_ops.users.title.remove_tags',
552
552
  icon: 'tag-minus',
553
- action_path: '/admin/users/bulk_remove_tags',
553
+ action_path: ->(view_context) { view_context.spree.bulk_remove_tags_admin_users_path },
554
554
  body: 'admin.bulk_ops.users.body.remove_tags',
555
555
  form_partial: 'spree/admin/bulk_operations/forms/tag_picker',
556
556
  form_partial_locals: { allow_create: false },
@@ -1080,7 +1080,7 @@ Rails.application.config.after_initialize do
1080
1080
  position: 70,
1081
1081
  ransack_attribute: 'user_id',
1082
1082
  operators: %i[eq],
1083
- search_url: '/admin/users/select_options.json',
1083
+ search_url: ->(view_context) { view_context.spree.admin_users_select_options_path(format: :json) },
1084
1084
  method: ->(gc) { gc.user&.email }
1085
1085
 
1086
1086
  Spree.admin.tables.gift_cards.add :created_at,
@@ -1125,7 +1125,7 @@ Rails.application.config.after_initialize do
1125
1125
  position: 20,
1126
1126
  ransack_attribute: 'stock_location_id',
1127
1127
  operators: %i[eq],
1128
- search_url: '/admin/stock_locations/select_options.json',
1128
+ search_url: ->(view_context) { view_context.spree.admin_stock_locations_select_options_path(format: :json) },
1129
1129
  partial: 'spree/admin/tables/columns/stock_item_location'
1130
1130
 
1131
1131
  # Backorderable (inline editable checkbox)
@@ -1198,7 +1198,7 @@ Rails.application.config.after_initialize do
1198
1198
  position: 20,
1199
1199
  method: ->(post) { post.post_category_title },
1200
1200
  ransack_attribute: 'post_category_id',
1201
- search_url: '/admin/post_categories/select_options.json'
1201
+ search_url: ->(view_context) { view_context.spree.select_options_admin_post_categories_path(format: :json) }
1202
1202
 
1203
1203
  Spree.admin.tables.posts.add :author,
1204
1204
  label: :author,
@@ -1210,7 +1210,7 @@ Rails.application.config.after_initialize do
1210
1210
  position: 30,
1211
1211
  method: ->(post) { post.author_name },
1212
1212
  ransack_attribute: 'author_id',
1213
- search_url: '/admin/admin_users/select_options.json'
1213
+ search_url: ->(view_context) { view_context.spree.select_options_admin_admin_users_path(format: :json) }
1214
1214
 
1215
1215
  Spree.admin.tables.posts.add :published_at,
1216
1216
  label: :published_at,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.3
4
+ version: 5.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vendo Connect Inc.
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 5.3.3
18
+ version: 5.3.4
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 5.3.3
25
+ version: 5.3.4
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: active_link_to
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -1257,9 +1257,9 @@ licenses:
1257
1257
  - AGPL-3.0-or-later
1258
1258
  metadata:
1259
1259
  bug_tracker_uri: https://github.com/spree/spree/issues
1260
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.3.3
1260
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.3.4
1261
1261
  documentation_uri: https://docs.spreecommerce.org/
1262
- source_code_uri: https://github.com/spree/spree/tree/v5.3.3
1262
+ source_code_uri: https://github.com/spree/spree/tree/v5.3.4
1263
1263
  rdoc_options: []
1264
1264
  require_paths:
1265
1265
  - lib