spree_admin 5.0.3 → 5.0.5

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree/admin/dashboard_controller.rb +11 -12
  3. data/app/controllers/spree/admin/orders_controller.rb +1 -1
  4. data/app/controllers/spree/admin/products_controller.rb +4 -4
  5. data/app/controllers/spree/admin/webhooks_subscribers_controller.rb +32 -13
  6. data/app/helpers/spree/admin/base_helper.rb +1 -1
  7. data/app/helpers/spree/admin/navigation_helper.rb +1 -1
  8. data/app/helpers/spree/admin/orders_filters_helper.rb +1 -1
  9. data/app/helpers/spree/admin/orders_helper.rb +3 -1
  10. data/app/helpers/spree/admin/payments_helper.rb +0 -5
  11. data/app/javascript/spree/admin/application.js +0 -2
  12. data/app/javascript/spree/admin/controllers/active_storage_upload_controller.js +2 -11
  13. data/app/javascript/spree/admin/controllers/asset_uploader_controller.js +3 -2
  14. data/app/javascript/spree/admin/controllers/multi_tom_select_controller.js +3 -2
  15. data/app/javascript/spree/admin/controllers/variants_form_controller.js +25 -18
  16. data/app/javascript/spree/admin/helpers/trix/video_embed.js +2 -2
  17. data/app/javascript/spree/admin/helpers/uppy_active_storage.js +15 -3
  18. data/app/views/active_storage/_upload_form.html.erb +2 -2
  19. data/app/views/spree/admin/dashboard/_top_products.html.erb +1 -1
  20. data/app/views/spree/admin/orders/_filters.html.erb +11 -1
  21. data/app/views/spree/admin/orders/_return_authorizations.html.erb +3 -1
  22. data/app/views/spree/admin/orders/_summary.html.erb +1 -1
  23. data/app/views/spree/admin/page_blocks/forms/_image.html.erb +9 -0
  24. data/app/views/spree/admin/page_builder/_sidebar_block.html.erb +10 -9
  25. data/app/views/spree/admin/page_builder/_sidebar_sections_toolbar.html.erb +152 -39
  26. data/app/views/spree/admin/page_sections/forms/_featured_posts.html.erb +0 -5
  27. data/app/views/spree/admin/payment_methods/_form.html.erb +1 -1
  28. data/app/views/spree/admin/payments/source_forms/_gateway.html.erb +1 -1
  29. data/app/views/spree/admin/preferences/_password_field.html.erb +2 -2
  30. data/app/views/spree/admin/products/_form.html.erb +2 -1
  31. data/app/views/spree/admin/products/form/_tax.html.erb +12 -0
  32. data/app/views/spree/admin/products/form/_variants.html.erb +1 -0
  33. data/app/views/spree/admin/shared/_head.html.erb +6 -1
  34. data/app/views/spree/admin/shared/_tax_nav.html.erb +1 -0
  35. data/app/views/spree/admin/shared/sidebar/_store_nav.html.erb +3 -2
  36. data/app/views/spree/admin/shared/sidebar/_storefront_nav.html.erb +2 -0
  37. data/app/views/spree/admin/stores/form/_basic.html.erb +1 -1
  38. data/app/views/spree/admin/translations/edit.html.erb +1 -1
  39. data/app/views/spree/admin/users/_form.html.erb +1 -1
  40. data/app/views/spree/admin/users/index.html.erb +3 -3
  41. data/app/views/spree/admin/variants/_variant.html.erb +2 -2
  42. data/app/views/spree/admin/variants/form/_basic.html.erb +4 -4
  43. data/app/views/spree/admin/variants/form/_media.html.erb +1 -0
  44. data/app/views/spree/admin/webhooks_subscribers/_form.html.erb +37 -19
  45. data/app/views/spree/admin/webhooks_subscribers/_webhooks_subscriber.html.erb +12 -6
  46. data/app/views/spree/admin/webhooks_subscribers/edit.html.erb +2 -2
  47. data/app/views/spree/admin/webhooks_subscribers/show.html.erb +58 -47
  48. data/config/importmap.rb +2 -2
  49. data/config/locales/en.yml +0 -1
  50. data/lib/spree/admin/engine.rb +9 -1
  51. data/vendor/javascript/bootstrap--dist--js--bootstrap.bundle.min.js.js +4 -4
  52. data/vendor/javascript/dompurify.js +24 -24
  53. metadata +9 -9
  54. data/app/javascript/spree/admin/controllers/webhook_subscriber_events_controller.js +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2314972e804657e3746e099913f84a2ffe364d955005ecd2ad0f441f6d38f44c
4
- data.tar.gz: b5b4bc046008b7f3077c12dccb7571f5fc965f2196d3a1d077f044d911da0dd2
3
+ metadata.gz: 274d9668ae1ea544815eb385842f5556570acb9c999fe65ab07a6b639bb42b06
4
+ data.tar.gz: 706699d5694ae8d8e2ea3df88b4b1a27c7196474efdf9928ebbbb27fba3b1828
5
5
  SHA512:
6
- metadata.gz: 0f823382a162659d30e565ff7dfc2299f4c8b5ce4e73e11c7b3a146dc0560ebadd289653d09b6c40eb33e30300f4d2032b91389b2a2eebad43657c236d2065df
7
- data.tar.gz: 7e104c97735e15737d3b9d209a632ac7cdd8c53b0229e8482225e57e023d44d74228833fef8cb7f2fd54c1f56e696b634fff5d7d289bc6a3bdb5d2e14aa56c23
6
+ metadata.gz: 227638a7b026550f3cdfb9b0549798c91ae1a4feeefe7b97c7984d4005c74b1fc1a1d180707ebe2037af02d90b912bd7508d74fd291b5c29c520cbfe62f28691
7
+ data.tar.gz: f1ef07a89426530a25d0db9a50bed68eebd9af552a9d639f0b5bc138201deca3ae626d01032fa147f167bc82ebb714a71c470dadabbccac66dfe9eb02dff2716
@@ -111,9 +111,11 @@ module Spree
111
111
  @audience_growth_rate = calc_growth_rate(@audience_total, previous_audience_total)
112
112
 
113
113
  @audience = if same_day?
114
- @audience_scope.group_by_hour(:created_at, range: analytics_time_range, time_zone: current_store.preferred_timezone, default_value: 0)
114
+ @audience_scope.group_by_hour(:created_at, range: analytics_time_range, time_zone: current_store.preferred_timezone,
115
+ default_value: 0)
115
116
  else
116
- @audience_scope.group_by_day(:created_at, range: analytics_time_range, time_zone: current_store.preferred_timezone, default_value: 0)
117
+ @audience_scope.group_by_day(:created_at, range: analytics_time_range, time_zone: current_store.preferred_timezone,
118
+ default_value: 0)
117
119
  end
118
120
 
119
121
  return unless defined?(Ahoy)
@@ -123,25 +125,22 @@ module Spree
123
125
  previous_visits_total = Ahoy::Visit.where(started_at: previous_analytics_time_range).count
124
126
  @visits_growth_rate = calc_growth_rate(@visits_total, previous_visits_total)
125
127
 
126
- @visits_scope = Ahoy::Visit.where(started_at: analytics_time_range)
127
- @visits_total = @visits_scope.count
128
- previous_visits_total = Ahoy::Visit.where(started_at: previous_analytics_time_range).count
129
- @visits_growth_rate = calc_growth_rate(@visits_total, previous_visits_total)
130
-
131
128
  @visits = if same_day?
132
- @visits_scope.group_by_hour(:started_at, range: analytics_time_range, time_zone: current_store.preferred_timezone, default_value: 0)
129
+ @visits_scope.group_by_hour(:started_at, range: analytics_time_range, time_zone: current_store.preferred_timezone,
130
+ default_value: 0)
133
131
  else
134
- @visits_scope.group_by_day(:started_at, range: analytics_time_range, time_zone: current_store.preferred_timezone, default_value: 0)
132
+ @visits_scope.group_by_day(:started_at, range: analytics_time_range, time_zone: current_store.preferred_timezone,
133
+ default_value: 0)
135
134
  end
136
135
 
137
- @top_landing_pages = @visits_scope.where.not(landing_page_title: [nil, '']).top(:landing_page_title, 10)
136
+ @top_landing_pages = @visits_scope.where.not(landing_page: [nil, '']).top(:landing_page, 10)
138
137
  @top_referrers = @visits_scope.where.not(referring_domain: current_store.custom_domains.pluck(:url) << current_store.url).top(
139
138
  :referring_domain, 10
140
139
  )
141
140
  @top_locations = @visits_scope.top(:country, 10)
142
141
  @top_devices = @visits_scope.group(:device_type).count.transform_keys do |device|
143
- device.nil? ? 'N/A' : device
144
- end.map { |series| [series.first, (series.second.to_f / @visits_scope.count) * 100] }
142
+ device.nil? ? 'N/A' : device
143
+ end.map { |series| [series.first, (series.second.to_f / @visits_scope.count) * 100] }
145
144
  end
146
145
  end
147
146
  end
@@ -70,7 +70,7 @@ module Spree
70
70
  @payments = @order.payments.includes(:payment_method, :source).order(:created_at)
71
71
  @refunds = @order.refunds
72
72
 
73
- @return_authorizations = @order.return_authorizations
73
+ @return_authorizations = @order.return_authorizations.includes(:return_items)
74
74
  @customer_returns = @order.customer_returns.distinct
75
75
  end
76
76
 
@@ -151,7 +151,7 @@ module Spree
151
151
  protected
152
152
 
153
153
  def find_resource
154
- current_store.products.accessible_by(current_ability, :manage).with_deleted.friendly.find(params[:id])
154
+ current_store.products.accessible_by(current_ability, :manage).friendly.find(params[:id])
155
155
  end
156
156
 
157
157
  def load_data
@@ -179,10 +179,10 @@ module Spree
179
179
  @product_options[option_type.id.to_s] = {
180
180
  name: option_type.presentation,
181
181
  position: index + 1,
182
- values: option_values.pluck(:presentation).uniq
182
+ values: option_values.pluck(:name, :presentation).uniq.map { |name, presentation| { value: name, text: presentation } }
183
183
  }
184
184
 
185
- @product_available_options[option_type.id.to_s] = option_type.option_values.to_tom_select_json
185
+ @product_available_options[option_type.id.to_s] = option_type.option_values.pluck(:name, :presentation).uniq.map { |name, presentation| { id: name, name: presentation } }
186
186
  end
187
187
 
188
188
  @product_stock = {}
@@ -273,7 +273,7 @@ module Spree
273
273
  for_ordering_with_translations(model_class, :name).
274
274
  includes(product_includes).
275
275
  page(params[:page]).
276
- per(params[:per_page] || ENV.fetch('ADMIN_PRODUCTS_PER_PAGE', 25))
276
+ per(params[:per_page] || Spree::Admin::RuntimeConfig.admin_products_per_page)
277
277
 
278
278
  @collection
279
279
  end
@@ -1,20 +1,11 @@
1
1
  module Spree
2
2
  module Admin
3
3
  class WebhooksSubscribersController < ResourceController
4
+ before_action :set_supported_events, except: [:index, :show]
5
+
4
6
  create.before :process_subscriptions
5
7
  update.before :process_subscriptions
6
8
 
7
- def index
8
- params[:q] ||= {}
9
- params[:q][:s] ||= 'created_at desc'
10
-
11
- search = Webhooks::Subscriber.accessible_by(current_ability).ransack(params[:q])
12
- @webhooks_subscribers = search.result.
13
- includes(:events).
14
- page(params[:page]).
15
- per(params[:per_page])
16
- end
17
-
18
9
  def show
19
10
  @webhooks_subscriber = Webhooks::Subscriber.find(params[:id])
20
11
  @events = @webhooks_subscriber.events.order(created_at: :desc).page(params[:page]).per(params[:per_page])
@@ -26,7 +17,19 @@ module Spree
26
17
  @resource ||= Spree::Admin::Resource.new 'spree/admin/webhooks/subscribers', 'subscribers', nil
27
18
  end
28
19
 
20
+ def collection
21
+ params[:q] ||= {}
22
+ params[:q][:s] ||= 'created_at desc'
23
+
24
+ @search = Webhooks::Subscriber.accessible_by(current_ability).ransack(params[:q])
25
+ @collection = @search.result.
26
+ page(params[:page]).
27
+ per(params[:per_page])
28
+ end
29
+
29
30
  def process_subscriptions
31
+ return if params[:webhooks_subscriber].blank?
32
+
30
33
  params[:webhooks_subscriber][:subscriptions] = if params[:subscribe_to_all_events] == 'true'
31
34
  ['*']
32
35
  else
@@ -37,12 +40,28 @@ module Spree
37
40
  end
38
41
 
39
42
  def selected_events
40
- supported_events.select { |resource, _events| params[:webhooks_subscriber][resource] == 'true' }.values.flatten
43
+ @supported_events.select { |resource, _events| params[:webhooks_subscriber][resource] == 'true' }.values.flatten
41
44
  end
42
45
 
43
- def supported_events
46
+ def set_supported_events
44
47
  @supported_events ||= Spree::Webhooks::Subscriber.supported_events
45
48
  end
49
+
50
+ def supported_events
51
+ @supported_events
52
+ end
53
+
54
+ def permitted_resource_params
55
+ params.require(:webhooks_subscriber).permit(:url, :active, subscriptions: [])
56
+ end
57
+
58
+ def location_after_create
59
+ location_after_save
60
+ end
61
+
62
+ def location_after_save
63
+ spree.admin_webhooks_subscriber_path(@object)
64
+ end
46
65
  end
47
66
  end
48
67
  end
@@ -10,7 +10,7 @@ module Spree
10
10
  end
11
11
 
12
12
  def enterprise_edition?
13
- defined?(Vendo)
13
+ defined?(SpreeEnterprise)
14
14
  end
15
15
 
16
16
  def spree_updater
@@ -190,7 +190,7 @@ module Spree
190
190
  # @return [String] the badge with the icon
191
191
  def active_badge(condition, options = {})
192
192
  label = options[:label]
193
- label ||= condition ? Spree.t(:say_yes) : Spree.t(:say_no)
193
+ label ||= condition ? Spree.t(:say_yes).to_s : Spree.t(:say_no).to_s
194
194
  label = icon('check') + label if condition
195
195
 
196
196
  css_class = condition ? 'badge-active' : 'badge-inactive'
@@ -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
@@ -25,8 +25,10 @@ module Spree
25
25
  icon('credit-card-refund') + Spree.t('payment_states.refunded')
26
26
  elsif order.partially_refunded?
27
27
  icon('credit-card-refund') + Spree.t('payment_states.partially_refunded')
28
- elsif order.payment_state == 'failed' || order.payment_state == 'void'
28
+ elsif order.payment_state == 'failed'
29
29
  icon('cancel') + Spree.t('payment_states.failed')
30
+ elsif order.payment_state == 'void'
31
+ icon('cancel') + Spree.t('payment_states.void')
30
32
  elsif order.payment_state == 'paid'
31
33
  icon('check') + Spree.t('payment_states.paid')
32
34
  else
@@ -11,11 +11,6 @@ module Spree
11
11
  end
12
12
  end
13
13
 
14
- def payment_method_icon_tag(payment_method, opts = {})
15
- image_tag "payment_icons/#{payment_method}.svg", opts
16
- rescue Sprockets::Rails::Helper::AssetNotFound
17
- end
18
-
19
14
  def available_payment_methods
20
15
  @available_payment_methods ||= Spree::PaymentMethod.providers.map { |provider| provider.name.constantize.new }.delete_if { |payment_method| !payment_method.show_in_admin? || current_store.payment_methods.pluck(:type).include?(payment_method.type) }.sort_by(&:name)
21
16
  end
@@ -78,7 +78,6 @@ import StockTransferController from 'spree/admin/controllers/stock_transfer_cont
78
78
  import StoreFormController from 'spree/admin/controllers/store_form_controller'
79
79
  import UnitSystemController from 'spree/admin/controllers/unit_system_controller'
80
80
  import VariantsFormController from 'spree/admin/controllers/variants_form_controller'
81
- import WebhooksSubscriberEventsController from 'spree/admin/controllers/webhook_subscriber_events_controller'
82
81
  import AddressAutocompleteController from 'spree/core/controllers/address_autocomplete_controller'
83
82
  import AddressFormController from 'spree/core/controllers/address_form_controller'
84
83
  import EnableButtonController from 'spree/core/controllers/enable_button_controller'
@@ -131,7 +130,6 @@ application.register('tabs', Tabs)
131
130
  application.register('textarea-autogrow', TextareaAutogrow)
132
131
  application.register('unit-system', UnitSystemController)
133
132
  application.register('variants-form', VariantsFormController)
134
- application.register('webhooks-subscriber-events', WebhooksSubscriberEventsController)
135
133
 
136
134
  LocalTime.start()
137
135
 
@@ -29,7 +29,8 @@ export default class extends Controller {
29
29
  })
30
30
 
31
31
  this.uppy.use(ActiveStorageUpload, {
32
- directUploadUrl: document.querySelector("meta[name='direct-upload-url']").getAttribute('content')
32
+ directUploadUrl: document.querySelector("meta[name='direct-upload-url']").getAttribute('content'),
33
+ crop: this.cropValue
33
34
  })
34
35
 
35
36
  let dashboardOptions = {}
@@ -55,16 +56,6 @@ export default class extends Controller {
55
56
 
56
57
  this.uppy.on('file-editor:complete', (updatedFile) => {
57
58
  console.log('File editing complete:', updatedFile)
58
- // Remove the old file from Uppy's file list
59
- this.uppy.removeFile(updatedFile.id)
60
- // Add the updated file to Uppy
61
- this.uppy.addFile({
62
- name: updatedFile.name,
63
- type: updatedFile.type,
64
- data: updatedFile.data,
65
- source: 'local',
66
- isRemote: false
67
- })
68
59
 
69
60
  this.handleUI(updatedFile)
70
61
 
@@ -11,7 +11,8 @@ export default class extends Controller {
11
11
  viewableType: String,
12
12
  multiple: { type: Boolean, default: false },
13
13
  type: { type: String, default: 'image' },
14
- allowedFileTypes: { type: Array, default: [] }
14
+ allowedFileTypes: { type: Array, default: [] },
15
+ adminAssetsPath: String
15
16
  }
16
17
 
17
18
  connect() {
@@ -43,7 +44,7 @@ export default class extends Controller {
43
44
  }
44
45
 
45
46
  handleSuccessResult(response) {
46
- post('/admin/assets', {
47
+ post(this.adminAssetsPathValue, {
47
48
  body: JSON.stringify({
48
49
  asset: {
49
50
  type: this.assetClassValue,
@@ -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() {
@@ -37,7 +37,8 @@ export default class extends CheckboxSelectAll {
37
37
  currentStockLocationId: String,
38
38
  stockLocations: Array,
39
39
  optionValuesSelectOptions: Array,
40
- locale: String
40
+ locale: String,
41
+ adminPath: String
41
42
  }
42
43
 
43
44
  connect() {
@@ -128,7 +129,7 @@ export default class extends CheckboxSelectAll {
128
129
  const nestingLevel = internalName.split('/').length
129
130
  if (nestingLevel === 1) {
130
131
  const firstOptionKey = Object.keys(this.optionsValue)[0]
131
- const newOptionValues = this.optionsValue[firstOptionKey].values.filter((value) => value !== internalName)
132
+ const newOptionValues = this.optionsValue[firstOptionKey].values.filter((value) => value.text !== internalName)
132
133
  if (newOptionValues.length === 0) {
133
134
  const newOptionsValue = this.optionsValue
134
135
  delete newOptionsValue[firstOptionKey]
@@ -264,12 +265,12 @@ export default class extends CheckboxSelectAll {
264
265
  let name = ''
265
266
  let internalName = name
266
267
  if (i === 0) {
267
- name = variant[keys[i]]
268
+ name = variant[keys[i]].text
268
269
  internalName = name
269
270
  } else {
270
- const namesPath = keys.slice(1, keys.length).map((key) => variant[key])
271
+ const namesPath = keys.slice(1, keys.length).map((key) => variant[key].text)
271
272
  name = namesPath.join(' / ')
272
- internalName = `${variant[keys[0]]}/${namesPath.join('/')}`
273
+ internalName = `${variant[keys[0]].text}/${namesPath.join('/')}`
273
274
  }
274
275
 
275
276
  return { name, internalName }
@@ -571,12 +572,12 @@ export default class extends CheckboxSelectAll {
571
572
  refreshParentInputs() {
572
573
  const firstOption = Object.values(this.optionsValue)[0]
573
574
  if (firstOption) {
574
- firstOption.values.forEach((name) => {
575
+ firstOption.values.forEach((option) => {
575
576
  this.currenciesValue.forEach((currency) => {
576
- this.updateParentPriceRange(name, currency)
577
+ this.updateParentPriceRange(option.text, currency)
577
578
  })
578
579
  this.stockLocationsValue.forEach((stockLocationId) => {
579
- this.updateParentStockSum(name, stockLocationId)
580
+ this.updateParentStockSum(option.text, stockLocationId)
580
581
  })
581
582
  this.updateShopLocationCountOnHand()
582
583
  })
@@ -614,11 +615,17 @@ export default class extends CheckboxSelectAll {
614
615
  .find((option) => option.name === key).position
615
616
  inputs.push(positionInput)
616
617
 
617
- const valueInput = document.createElement('input')
618
- valueInput.type = 'hidden'
619
- valueInput.name = `product[variants_attributes][${i}][options][][value]`
620
- valueInput.value = variant[key]
621
- 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)
622
629
  })
623
630
 
624
631
  return inputs
@@ -724,7 +731,7 @@ export default class extends CheckboxSelectAll {
724
731
  this.lastOptionNameId = targetInput.value
725
732
 
726
733
  if (this.lastOptionNameId) {
727
- const response = await get(`/admin/option_types/${this.lastOptionNameId}/option_values/select_options`)
734
+ const response = await get(`${this.adminPathValue}/option_types/${this.lastOptionNameId}/option_values/select_options`)
728
735
 
729
736
  if (response.ok) {
730
737
  this.currentOptionValues[this.lastOptionNameId] = await response.json
@@ -923,8 +930,8 @@ export default class extends CheckboxSelectAll {
923
930
  const optionValuesSelectContainer = template.querySelector('[data-slot="optionValuesSelectContainer"]')
924
931
  const tomSelectOptionValues = optionValues.map((optionValue) => {
925
932
  return {
926
- id: availableOptions.find((availableOption) => availableOption.name === optionValue)?.id,
927
- name: optionValue
933
+ id: optionValue.value,
934
+ name: optionValue.text,
928
935
  }
929
936
  })
930
937
 
@@ -947,8 +954,8 @@ export default class extends CheckboxSelectAll {
947
954
  values.forEach((value) => {
948
955
  const template = this.optionValueTemplateTarget.content.cloneNode(true)
949
956
  const optionValueNameEl = template.querySelector('[data-slot="optionValueName"]')
950
- optionValueNameEl.textContent = value
951
- optionValueNameEl.dataset.name = value
957
+ optionValueNameEl.textContent = value.text
958
+ optionValueNameEl.dataset.name = value.text
952
959
 
953
960
  templates.push(template)
954
961
  })
@@ -90,7 +90,7 @@ document.addEventListener("trix-attachment-remove", async function(event) {
90
90
  const { attachment } = event
91
91
  const { sgid } = attachment.attachment.attributes.values
92
92
 
93
- destroy(`/admin/action_text/video_embeds/${sgid}`, { responseKind: 'json' })
93
+ destroy(`${Spree.adminPath}/action_text/video_embeds/${sgid}`, { responseKind: 'json' })
94
94
  })
95
95
 
96
96
  function initializeTrixEditor(editor) {
@@ -129,7 +129,7 @@ function initializeTrixEditor(editor) {
129
129
 
130
130
  errorMessage.innerHTML = ''
131
131
 
132
- const response = await post('/admin/action_text/video_embeds', { body: JSON.stringify({ url: input.value }), responseKind: 'json' })
132
+ const response = await post(`${Spree.adminPath}/action_text/video_embeds`, { body: JSON.stringify({ url: input.value }), responseKind: 'json' })
133
133
 
134
134
  if (response.ok) {
135
135
  const { sgid, content } = await response.json
@@ -20,7 +20,8 @@ export default class ActiveStorageUpload extends BasePlugin {
20
20
  limit: 0,
21
21
  timeout: 30 * 1000,
22
22
  directUploadUrl: null,
23
- headers: {}
23
+ headers: {},
24
+ crop: false
24
25
  }
25
26
 
26
27
  this.opts = Object.assign({}, defaultOptions, opts)
@@ -37,10 +38,19 @@ export default class ActiveStorageUpload extends BasePlugin {
37
38
 
38
39
  install() {
39
40
  this.uppy.addUploader(this.handleUpload)
41
+ this.uppy.on('file-editor:complete', this.onEditorComplete)
40
42
  }
41
43
 
42
44
  uninstall() {
43
45
  this.uppy.removeUploader(this.handleUpload)
46
+ this.uppy.off('file-editor:complete', this.onEditorComplete)
47
+ }
48
+
49
+ onEditorComplete = (updatedFile) => {
50
+ this.handleUpload([updatedFile.id])
51
+
52
+ // call directly upload method after editing image
53
+ return this.uploadFiles([updatedFile])
44
54
  }
45
55
 
46
56
  handleUpload(fileIDs) {
@@ -48,6 +58,10 @@ export default class ActiveStorageUpload extends BasePlugin {
48
58
  this.uppy.log("[ActiveStorage] No files to upload!")
49
59
  return Promise.resolve()
50
60
  }
61
+ // do not upload before editing is done
62
+ if (this.opts.crop) {
63
+ return Promise.resolve()
64
+ }
51
65
 
52
66
  this.uppy.log("[ActiveStorage] Uploading...")
53
67
  const files = fileIDs.map(fileID => this.uppy.getFile(fileID))
@@ -115,8 +129,6 @@ export default class ActiveStorageUpload extends BasePlugin {
115
129
  directUploadSignedId: blob.signed_id,
116
130
  }
117
131
 
118
- this.uppy.setFileState(file.id, { response })
119
-
120
132
  this.uppy.emit("upload-success", file, blob)
121
133
 
122
134
  return resolve(file)
@@ -2,7 +2,7 @@
2
2
  <% height ||= 300 %>
3
3
  <% crop ||= false unless defined?(crop) %>
4
4
  <% auto_submit ||= false %>
5
- <% can_delete ||= true unless defined?(can_delete) %>
5
+ <% show_delete_button = defined?(can_delete) ? can_delete : true %>
6
6
  <% css ||= '' %>
7
7
 
8
8
  <% if field_name && form %>
@@ -48,7 +48,7 @@
48
48
  <%= Spree.t('actions.select_file') %>
49
49
  </button>
50
50
 
51
- <% if can_delete %>
51
+ <% if show_delete_button %>
52
52
  <button type="button" class="btn btn-danger ml-auto" data-action="active-storage-upload#remove" data-turbo-confirm="<%= Spree.t(:are_you_sure) %>">
53
53
  <%= icon('trash') %>
54
54
 
@@ -45,7 +45,7 @@
45
45
  <%= product.name %>
46
46
  <% end %>
47
47
  </td>
48
- <% if enterprise_edition? && defined?(vendor_logo_link) && !@vendor %>
48
+ <% if defined?(vendor_logo_link) && !@vendor %>
49
49
  <td>
50
50
  <%= vendor_logo_link(product.vendor) if product.vendor.present? %>
51
51
  </td>
@@ -1,7 +1,17 @@
1
1
  <% frame_name ||= nil %>
2
2
 
3
+ <% search_form_path = if @user.present?
4
+ spree.admin_user_orders_path(@user)
5
+ elsif @vendor.present? && spree.respond_to?(:admin_vendor_orders_path)
6
+ spree.admin_vendor_orders_path(@vendor)
7
+ elsif controller_name == 'checkouts'
8
+ spree.admin_checkouts_path
9
+ else
10
+ spree.admin_orders_path
11
+ end %>
12
+
3
13
  <%= search_form_for [:admin, @vendor || @user, @search],
4
- url: controller_name == 'checkouts' ? spree.admin_checkouts_path : nil,
14
+ url: search_form_path,
5
15
  class: "filter-wrap",
6
16
  data: {
7
17
  controller: "filters reveal",
@@ -17,7 +17,9 @@
17
17
  </tr>
18
18
  </thead>
19
19
  <tbody>
20
- <%= render partial: 'spree/admin/orders/return_authorizations/return_authorization', collection: @return_authorizations, cached: spree_base_cache_scope %>
20
+ <%= render partial: "spree/admin/orders/return_authorizations/return_authorization",
21
+ collection: @return_authorizations,
22
+ cached: ->(r) { [spree_base_cache_key, r.cache_key_with_version, r.return_items.maximum(:updated_at)] } %>
21
23
  </tbody>
22
24
  </table>
23
25
  </div>
@@ -74,7 +74,7 @@
74
74
  <%= render 'tax_lines', tax_lines: tax_lines, id: 'tax-lines-additional' %>
75
75
  </li>
76
76
 
77
- <%= render_admin_partials(:order_page_body_partials, order: @order) %>
77
+ <%= render_admin_partials(:order_page_summary_partials, order: @order) %>
78
78
 
79
79
  <li class="list-group-item d-flex justify-content-between align-items-center border-0">
80
80
  <span data-hook='admin_order_tab_total_title'><%= Spree.t(:total) %></span>
@@ -1 +1,10 @@
1
1
  <%= render 'active_storage/upload_form', form: f, field_name: :asset, width: 512, height: 512, auto_submit: true %>
2
+
3
+ <% content_for(:design_tab) do %>
4
+ <%= render 'spree/admin/page_builder/labeled_range_input',
5
+ f: f, field: :preferred_height, min: 1, max: 1024, unit: 'px', _label: 'Max image height on desktop'
6
+ %>
7
+ <%= render 'spree/admin/page_builder/labeled_range_input',
8
+ f: f, field: :preferred_mobile_height, min: 1, max: 512, unit: 'px', _label: 'Max image height on mobile'
9
+ %>
10
+ <% end %>
@@ -7,15 +7,16 @@
7
7
  } do %>
8
8
  <div class="d-flex align-items-center justify-content-between sidebar-block-title p-1 rounded-sm">
9
9
  <div class="d-flex align-items-center flex-fill">
10
- <%= icon "#{block.icon_name}", class: 'mr-2' if block.icon_name.present? %>
11
- <%= link_to block.display_name, edit_admin_page_section_block_path(block.section, block),
12
- class: 'block-edit-link flex-fill text-dark',
13
- data: {
14
- turbo_frame: :page_sidebar,
15
- action: 'click->page-builder#makeOverlayActive',
16
- page_builder_editor_id_param: "block-#{block.id}"
17
- }
18
- %>
10
+ <%= link_to(edit_admin_page_section_block_path(block.section, block),
11
+ class: 'block-edit-link flex-fill text-dark',
12
+ data: {
13
+ turbo_frame: :page_sidebar,
14
+ action: 'click->page-builder#makeOverlayActive',
15
+ page_builder_editor_id_param: "block-#{block.id}"
16
+ }) do %>
17
+ <%= icon "#{block.icon_name}", class: 'mr-2' if block.icon_name.present? %>
18
+ <%= block.display_name %>
19
+ <% end %>
19
20
  </div>
20
21
  <div class="d-flex align-items-center d-none">
21
22
  <% if block.section.can_sort_blocks? %>