spree_admin 5.1.4 → 5.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/spree/admin/components/_variants_form.scss +5 -1
- data/app/assets/stylesheets/spree/admin/shared/_forms.scss +4 -0
- data/app/controllers/spree/admin/custom_domains_controller.rb +0 -4
- data/app/controllers/spree/admin/line_items_controller.rb +5 -1
- data/app/controllers/spree/admin/products_controller.rb +1 -1
- data/app/controllers/spree/admin/resource_controller.rb +1 -1
- data/app/controllers/spree/admin/taxonomies_controller.rb +4 -0
- data/app/controllers/spree/admin/taxons_controller.rb +4 -0
- data/app/helpers/spree/admin/stores_helper.rb +1 -1
- data/app/javascript/spree/admin/controllers/admin_controller.js +8 -2
- data/app/javascript/spree/admin/controllers/select_controller.js +0 -6
- data/app/javascript/spree/admin/controllers/variants_form_controller.js +77 -31
- data/app/views/spree/admin/custom_domains/_custom_domain.html.erb +4 -6
- data/app/views/spree/admin/custom_domains/_custom_domains.html.erb +4 -9
- data/app/views/spree/admin/custom_domains/index.html.erb +31 -17
- data/app/views/spree/admin/invitations/show.html.erb +2 -2
- data/app/views/spree/admin/orders/_header.html.erb +2 -1
- data/app/views/spree/admin/page_builder/_pages_dropdown.html.erb +1 -1
- data/app/views/spree/admin/page_links/_list.html.erb +1 -1
- data/app/views/spree/admin/products/_list.html.erb +6 -4
- data/app/views/spree/admin/products/_product.html.erb +2 -0
- data/app/views/spree/admin/products/edit.html.erb +1 -0
- data/app/views/spree/admin/products/form/_variants.html.erb +2 -3
- data/app/views/spree/admin/shared/_head.html.erb +2 -0
- data/app/views/spree/admin/shared/_new_item_dropdown.html.erb +1 -1
- data/app/views/spree/admin/shared/sidebar/_store_nav.html.erb +9 -7
- data/app/views/spree/admin/stores/form/_emails.html.erb +17 -0
- data/app/views/spree/admin/tax_rates/_form.html.erb +7 -5
- data/app/views/spree/admin/taxonomies/_taxonomy.html.erb +2 -2
- data/app/views/spree/admin/taxonomies/update.turbo_stream.erb +1 -0
- data/app/views/spree/admin/taxons/_form.html.erb +1 -1
- data/app/views/spree/admin/taxons/update.turbo_stream.erb +7 -0
- data/config/importmap.rb +0 -1
- data/config/locales/en.yml +1 -0
- data/lib/spree/admin/engine.rb +3 -0
- metadata +10 -11
- data/app/helpers/spree/admin/custom_domains_helper.rb +0 -9
- data/app/views/spree/admin/custom_domains/create.turbo_stream.erb +0 -3
- data/vendor/javascript/stimulus-textarea-autogrow.js +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ced4e88139c2415b6773c33a5a61745fd66c3785038bd2bedbf393e2123eaed6
|
|
4
|
+
data.tar.gz: 9e3017a0cb8ded68fe31d44f0031fae27ae11eee6a85e299467434086a449f47
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 031ac7b75b3e3ae2d1772d1a85f09f6ad0de3fedb198199e49799868cb8d037b44a6c0267448eba5dbc920b944680ccff9f685fb3afe8b4307dae2b5ca3849aa
|
|
7
|
+
data.tar.gz: 2836282801798b9f0a493002735342e31f387af928158566bf8c7773776ebf36de0a579bb5898ce86873fa257752b7dc9df0043991fead981ac7a3bee142b0e5
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
&__option {
|
|
28
28
|
display: flex;
|
|
29
29
|
border-bottom: 1px solid $border-color;
|
|
30
|
-
padding: 1rem
|
|
30
|
+
padding: 0.5rem 0.5rem 1rem 0;
|
|
31
|
+
margin-bottom: 0.5rem;
|
|
31
32
|
|
|
32
33
|
.label {
|
|
33
34
|
margin-bottom: 0.5rem;
|
|
@@ -57,6 +58,9 @@
|
|
|
57
58
|
|
|
58
59
|
&--new {
|
|
59
60
|
padding-left: calc(1.13px + 3.25rem);
|
|
61
|
+
border-bottom: none;
|
|
62
|
+
margin-bottom: 0;
|
|
63
|
+
padding-bottom: 0.5rem;
|
|
60
64
|
|
|
61
65
|
.values-inputs {
|
|
62
66
|
display: flex;
|
|
@@ -6,7 +6,7 @@ module Spree
|
|
|
6
6
|
layout 'turbo_rails/frame'
|
|
7
7
|
|
|
8
8
|
def create
|
|
9
|
-
@variant =
|
|
9
|
+
@variant = variant_scope.find(params.dig(:line_item, :variant_id))
|
|
10
10
|
|
|
11
11
|
@order.transaction do
|
|
12
12
|
line_item_result = create_service.call(order: @order, line_item_attributes: permitted_resource_params)
|
|
@@ -120,6 +120,10 @@ module Spree
|
|
|
120
120
|
def permitted_resource_params
|
|
121
121
|
params.require(:line_item).permit(permitted_line_item_attributes)
|
|
122
122
|
end
|
|
123
|
+
|
|
124
|
+
def variant_scope
|
|
125
|
+
Spree::Variant.accessible_by(current_ability, :manage)
|
|
126
|
+
end
|
|
123
127
|
end
|
|
124
128
|
end
|
|
125
129
|
end
|
|
@@ -173,7 +173,7 @@ module Spree
|
|
|
173
173
|
joins(option_type: :product_option_types).
|
|
174
174
|
includes(option_type: :option_values).
|
|
175
175
|
merge(@product.product_option_types).
|
|
176
|
-
reorder("#{Spree::ProductOptionType.table_name}.position").
|
|
176
|
+
reorder("#{Spree::ProductOptionType.table_name}.position", "#{Spree::Variant.table_name}.position").
|
|
177
177
|
uniq.group_by(&:option_type).each_with_index do |option, index|
|
|
178
178
|
option_type, option_values = option
|
|
179
179
|
|
|
@@ -145,7 +145,7 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
|
145
145
|
# call authorize! a third time (called twice already in Admin::BaseController)
|
|
146
146
|
# this time we pass the actual instance so fine-grained abilities can control
|
|
147
147
|
# access to individual records, not just entire models.
|
|
148
|
-
authorize! action, @object
|
|
148
|
+
authorize! action, @object if @object.present?
|
|
149
149
|
|
|
150
150
|
instance_variable_set("@#{resource.object_name}", @object)
|
|
151
151
|
else
|
|
@@ -4,7 +4,7 @@ module Spree
|
|
|
4
4
|
include Spree::ImagesHelper
|
|
5
5
|
|
|
6
6
|
def available_stores
|
|
7
|
-
@available_stores ||= Spree::Store.accessible_by(current_ability).includes(:logo_attachment, :favicon_image_attachment, :default_custom_domain)
|
|
7
|
+
@available_stores ||= Spree::Store.accessible_by(current_ability, :manage).includes(:logo_attachment, :favicon_image_attachment, :default_custom_domain)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
DEFAULT_ICON_SIZE = 40
|
|
@@ -3,16 +3,22 @@ import { Controller } from '@hotwired/stimulus'
|
|
|
3
3
|
export default class extends Controller {
|
|
4
4
|
static targets = ['close', 'save']
|
|
5
5
|
|
|
6
|
-
close() {
|
|
6
|
+
close(event) {
|
|
7
|
+
// https://github.com/hotwired/stimulus/issues/743
|
|
8
|
+
if (event.type == "keydown" && !(event instanceof KeyboardEvent)) return
|
|
9
|
+
|
|
7
10
|
if (this.hasCloseTarget) {
|
|
8
11
|
window.Turbo.visit(this.closeTarget.href)
|
|
9
12
|
}
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
save(event) {
|
|
16
|
+
// https://github.com/hotwired/stimulus/issues/743
|
|
17
|
+
if (event.type == "keydown" && !(event instanceof KeyboardEvent)) return
|
|
18
|
+
|
|
13
19
|
if (this.hasSaveTarget) {
|
|
14
20
|
event.preventDefault()
|
|
15
21
|
this.saveTarget.click()
|
|
16
22
|
}
|
|
17
23
|
}
|
|
18
|
-
}
|
|
24
|
+
}
|
|
@@ -128,25 +128,29 @@ export default class extends CheckboxSelectAll {
|
|
|
128
128
|
|
|
129
129
|
const nestingLevel = internalName.split('/').length
|
|
130
130
|
if (nestingLevel === 1) {
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
131
|
+
const sortedOptions = Object.entries(this.optionsValue).sort((a, b) => a[1].position - b[1].position)
|
|
132
|
+
const firstOptionKey = sortedOptions[0]?.[0]
|
|
133
|
+
|
|
134
|
+
if (firstOptionKey !== undefined) {
|
|
135
|
+
const newOptionValues = this.optionsValue[firstOptionKey].values.filter((value) => value.text !== internalName)
|
|
136
|
+
if (newOptionValues.length === 0) {
|
|
137
|
+
const newOptionsValue = this.optionsValue
|
|
138
|
+
delete newOptionsValue[firstOptionKey]
|
|
139
|
+
this.optionsValue = newOptionsValue
|
|
140
|
+
this.removeOption(firstOptionKey)
|
|
141
|
+
} else {
|
|
142
|
+
this.optionsValue = {
|
|
143
|
+
...this.optionsValue,
|
|
144
|
+
[firstOptionKey]: {
|
|
145
|
+
...this.optionsValue[firstOptionKey],
|
|
146
|
+
values: newOptionValues
|
|
147
|
+
}
|
|
144
148
|
}
|
|
145
|
-
}
|
|
146
149
|
|
|
147
|
-
|
|
150
|
+
this.optionsContainerTarget.querySelector(`#option-${firstOptionKey} [data-name="${internalName}"]`).remove()
|
|
151
|
+
}
|
|
152
|
+
checkbox.checked = false
|
|
148
153
|
}
|
|
149
|
-
checkbox.checked = false
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
delete newStockValue[internalName]
|
|
@@ -463,25 +467,42 @@ export default class extends CheckboxSelectAll {
|
|
|
463
467
|
this.variantsTableTarget.classList.remove('d-none')
|
|
464
468
|
|
|
465
469
|
const nestingLevel = Math.min(keys.length, 2)
|
|
466
|
-
|
|
470
|
+
|
|
471
|
+
// This is the index for the product variant attributes
|
|
472
|
+
// We only want to count nested options if we have more than one option type
|
|
473
|
+
let idx
|
|
474
|
+
if (nestingLevel > 1) {
|
|
475
|
+
idx = this.variantsContainerTarget.querySelectorAll('.nested').length
|
|
476
|
+
} else {
|
|
477
|
+
idx = this.variantsContainerTarget.querySelectorAll('[data-variants-form-target="variant"]').length
|
|
478
|
+
}
|
|
467
479
|
|
|
468
480
|
for (let i = 0; i < nestingLevel; i++) {
|
|
469
481
|
this.variantsValue.forEach((variant) => {
|
|
470
482
|
const { name, internalName } = this.calculateVariantName(variant, keys, i)
|
|
471
483
|
if (currentVariants.has(internalName) || this.ignoredVariants.has(internalName)) {
|
|
472
|
-
idx++
|
|
473
484
|
return
|
|
474
485
|
}
|
|
475
486
|
currentVariants.add(internalName)
|
|
476
487
|
|
|
477
488
|
const existingVariant = this.variantsContainerTarget.querySelector(`[data-variant-name="${internalName}"]`)
|
|
478
489
|
if (existingVariant) {
|
|
479
|
-
if (i === 0
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
490
|
+
if (i === 0) {
|
|
491
|
+
if (nestingLevel > 1) {
|
|
492
|
+
existingVariant.querySelectorAll("input[type='hidden']").forEach((input) => input.remove())
|
|
493
|
+
|
|
494
|
+
this.prepareParentVariant(existingVariant, internalName)
|
|
495
|
+
} else if (nestingLevel === 1) {
|
|
496
|
+
// We need to generate hidden inputs when we only have a single option left
|
|
497
|
+
// And there are no inputs already
|
|
498
|
+
if (existingVariant.querySelectorAll("input[type='hidden']").length === 0) {
|
|
499
|
+
const inputs = this.createInputsForVariant(keys, variant, idx)
|
|
500
|
+
inputs.forEach((input) => existingVariant.appendChild(input))
|
|
501
|
+
idx++
|
|
502
|
+
}
|
|
503
|
+
}
|
|
483
504
|
}
|
|
484
|
-
|
|
505
|
+
|
|
485
506
|
return
|
|
486
507
|
}
|
|
487
508
|
|
|
@@ -537,10 +558,10 @@ export default class extends CheckboxSelectAll {
|
|
|
537
558
|
}
|
|
538
559
|
|
|
539
560
|
this.preparePriceInputs(variantTarget, internalName, idx)
|
|
540
|
-
|
|
541
561
|
this.prepareStockInputs(variantTarget, internalName, idx)
|
|
562
|
+
|
|
563
|
+
idx++
|
|
542
564
|
}
|
|
543
|
-
idx++
|
|
544
565
|
|
|
545
566
|
variantNameContainer.textContent = name
|
|
546
567
|
if (previousVariant) {
|
|
@@ -570,7 +591,9 @@ export default class extends CheckboxSelectAll {
|
|
|
570
591
|
}
|
|
571
592
|
|
|
572
593
|
refreshParentInputs() {
|
|
573
|
-
const
|
|
594
|
+
const sortedOptions = Object.entries(this.optionsValue).sort((a, b) => a[1].position - b[1].position)
|
|
595
|
+
const firstOption = sortedOptions[0]?.[1]
|
|
596
|
+
|
|
574
597
|
if (firstOption) {
|
|
575
598
|
firstOption.values.forEach((option) => {
|
|
576
599
|
this.currenciesValue.forEach((currency) => {
|
|
@@ -899,12 +922,25 @@ export default class extends CheckboxSelectAll {
|
|
|
899
922
|
let { optionId } = event.params
|
|
900
923
|
optionId = String(optionId)
|
|
901
924
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
925
|
+
this.removeOption(optionId)
|
|
926
|
+
|
|
927
|
+
const newOptionsValue = {}
|
|
928
|
+
Object.entries(this.optionsValue).filter((option) => option[0] !== optionId).forEach((option) => {
|
|
929
|
+
newOptionsValue[option[0]] = option[1]
|
|
930
|
+
})
|
|
931
|
+
|
|
932
|
+
this.optionsValue = newOptionsValue
|
|
905
933
|
this.refreshParentInputs()
|
|
906
934
|
}
|
|
907
935
|
|
|
936
|
+
removeOption(optionId) {
|
|
937
|
+
const option = this.optionsContainerTarget.querySelector(`#option-${optionId}`)
|
|
938
|
+
if (option) option.remove()
|
|
939
|
+
|
|
940
|
+
const optionTypeInput = this.optionsContainerTarget.querySelector(`#product_option_type_ids_${optionId}`)
|
|
941
|
+
if (optionTypeInput) optionTypeInput.remove()
|
|
942
|
+
}
|
|
943
|
+
|
|
908
944
|
optionFormTemplate(optionName, optionValues, id, availableOptions) {
|
|
909
945
|
const template = this.optionFormTemplateTarget.content.cloneNode(true)
|
|
910
946
|
|
|
@@ -1045,14 +1081,24 @@ export default class extends CheckboxSelectAll {
|
|
|
1045
1081
|
|
|
1046
1082
|
priceForVariant(variantName, currency) {
|
|
1047
1083
|
const existingPrice = this.pricesValue[variantName]?.[currency.toLowerCase()]
|
|
1084
|
+
|
|
1048
1085
|
if (existingPrice) {
|
|
1049
1086
|
return {
|
|
1050
1087
|
...existingPrice,
|
|
1051
1088
|
amount: existingPrice.amount ? parseFloat(existingPrice.amount) : existingPrice.amount
|
|
1052
1089
|
}
|
|
1053
|
-
}
|
|
1090
|
+
} else {
|
|
1091
|
+
const parentName = variantName.split('/')[0]
|
|
1092
|
+
const parentPrices = Object.entries(this.pricesValue)
|
|
1093
|
+
.filter(([internalName, prices]) => internalName.startsWith(parentName) && prices[currency.toLowerCase()] !== undefined)
|
|
1094
|
+
.map(([_key, prices]) => parseFloat(prices[currency.toLowerCase()].amount))
|
|
1095
|
+
.sort((priceAmountA, priceAmountB) => priceAmountA - priceAmountB)
|
|
1054
1096
|
|
|
1055
|
-
|
|
1097
|
+
return {
|
|
1098
|
+
amount: parentPrices[0] ?? null,
|
|
1099
|
+
id: null
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1056
1102
|
}
|
|
1057
1103
|
|
|
1058
1104
|
updatePriceForVariant(variantName, newPrice, currency) {
|
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
<%= active_badge(custom_domain.active?) %>
|
|
5
5
|
</td>
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
</td>
|
|
12
|
-
<% end %>
|
|
7
|
+
<td><%= active_badge(custom_domain.default?) %></td>
|
|
8
|
+
<td class="actions">
|
|
9
|
+
<%= link_to_edit(custom_domain, no_text: true, url: spree.edit_admin_custom_domain_path(custom_domain), data: { turbo: false }) %>
|
|
10
|
+
</td>
|
|
13
11
|
</tr>
|
|
@@ -4,12 +4,9 @@
|
|
|
4
4
|
<thead>
|
|
5
5
|
<tr>
|
|
6
6
|
<th><%= Spree.t(:name) %></th>
|
|
7
|
-
<th
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
<th>Default</th>
|
|
11
|
-
<th></th>
|
|
12
|
-
<% end %>
|
|
7
|
+
<th><%= Spree.t(:active) %>?</th>
|
|
8
|
+
<th><%= Spree.t(:default) %>?</th>
|
|
9
|
+
<th></th>
|
|
13
10
|
</tr>
|
|
14
11
|
</thead>
|
|
15
12
|
<tbody>
|
|
@@ -18,7 +15,5 @@
|
|
|
18
15
|
</table>
|
|
19
16
|
</div>
|
|
20
17
|
<% else %>
|
|
21
|
-
|
|
22
|
-
You don't have any custom domains set yet.
|
|
23
|
-
</div>
|
|
18
|
+
<%= render 'spree/admin/shared/no_resource_found' %>
|
|
24
19
|
<% end %>
|
|
@@ -6,42 +6,56 @@
|
|
|
6
6
|
<%= render_admin_partials(:custom_domains_actions_partials) %>
|
|
7
7
|
<% end %>
|
|
8
8
|
|
|
9
|
+
<%= render_admin_partials(:custom_domains_header_partials) %>
|
|
10
|
+
|
|
9
11
|
<div class="card-lg p-4">
|
|
10
12
|
<h5 class="mb-3">Internal URL</h5>
|
|
11
13
|
<div class="row mb-4">
|
|
12
14
|
<div class="col-lg-4">
|
|
13
15
|
<p class="text-muted">
|
|
14
|
-
This is your internal URL.
|
|
16
|
+
This is your internal Admin URL.
|
|
15
17
|
</p>
|
|
16
18
|
</div>
|
|
17
19
|
<div class="col-lg-7 offset-lg-1">
|
|
18
|
-
<%= form_for current_store, url: spree.admin_store_path
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
<%= form_for current_store, url: spree.admin_store_path, data: { turbo: false, controller: 'enable-button', 'enable-button-disable-when-not-changed-value': true } do |f| %>
|
|
21
|
+
<% if Spree.root_domain.present? %>
|
|
22
|
+
<div class="d-flex align-items-center gap-3">
|
|
23
|
+
<div class="form-control d-flex align-items-center py-0 focus-shadow focus-border pr-2 gap-1 <% if current_store.custom_domains.any? %>disabled<% end %>">
|
|
24
|
+
<span class="text-muted">https://</span>
|
|
25
|
+
<%= f.text_field :code, class: 'form-control-plaintext pl-0', data: { enable_button_target: 'input' }, required: true, disabled: current_store.custom_domains.any? %>
|
|
26
|
+
<span>.<%= Spree.root_domain %></span>
|
|
27
|
+
|
|
28
|
+
<%= clipboard_component(current_store.formatted_url) %>
|
|
29
|
+
</div>
|
|
30
|
+
<% unless current_store.custom_domains.any? %>
|
|
31
|
+
<%= turbo_save_button_tag %>
|
|
32
|
+
<% end %>
|
|
33
|
+
</div>
|
|
34
|
+
<% else %>
|
|
35
|
+
<div class="d-flex align-items-center gap-3">
|
|
36
|
+
<div class="form-control d-flex align-items-center py-0 focus-shadow focus-border pr-2 gap-1">
|
|
37
|
+
<span class="text-muted">https://</span>
|
|
38
|
+
<%= f.text_field :url, class: 'form-control-plaintext pl-0', required: true, data: { enable_button_target: 'input' } %>
|
|
39
|
+
<%= clipboard_component(current_store.formatted_url) %>
|
|
40
|
+
</div>
|
|
41
|
+
<%= turbo_save_button_tag %>
|
|
42
|
+
</div>
|
|
25
43
|
<% end %>
|
|
26
44
|
<% end %>
|
|
27
45
|
</div>
|
|
28
46
|
</div>
|
|
29
47
|
<hr class="my-5" />
|
|
30
|
-
<h5
|
|
48
|
+
<h5><%= Spree.t(:custom_domains) %></h5>
|
|
31
49
|
<div class="row">
|
|
32
50
|
<div class="col-lg-4">
|
|
33
51
|
<p class="text-muted">
|
|
34
|
-
Connect your domain or subdomain to your
|
|
52
|
+
Connect your domain or subdomain to your storefront.
|
|
35
53
|
</p>
|
|
36
54
|
</div>
|
|
37
55
|
<div class="col-lg-7 offset-lg-1">
|
|
38
|
-
|
|
39
|
-
<%=
|
|
40
|
-
|
|
41
|
-
<div class="text-right">
|
|
42
|
-
<%= link_to Spree.t(:new_domain), spree.new_admin_custom_domain_path, class: "btn btn-primary" %>
|
|
43
|
-
</div>
|
|
44
|
-
<% end %>
|
|
56
|
+
<div class="text-right">
|
|
57
|
+
<%= link_to Spree.t(:new_domain), spree.new_admin_custom_domain_path, class: "btn btn-primary" %>
|
|
58
|
+
</div>
|
|
45
59
|
|
|
46
60
|
<%= turbo_frame_tag 'admin_custom_domains_index' do %>
|
|
47
61
|
<%= render 'custom_domains' %>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div class="d-flex align-items-center gap-2">
|
|
1
|
+
<div class="d-flex align-items-center gap-2 mb-4">
|
|
2
2
|
<div>
|
|
3
3
|
<%= render_avatar(@invitation.inviter, height: 32, width: 32) %>
|
|
4
4
|
</div>
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
<strong><%= @invitation.inviter.name %></strong> has invited you to join <strong><%= @invitation.resource.name %></strong>
|
|
7
7
|
</div>
|
|
8
8
|
</div>
|
|
9
|
-
<%= link_to Spree.t(:accept), spree.accept_admin_invitation_path(@invitation), class: 'btn btn-primary
|
|
9
|
+
<%= link_to Spree.t(:accept), spree.accept_admin_invitation_path(@invitation), class: 'btn btn-primary mx-auto px-5', data: { turbo_method: :put } %>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<% content_for :page_title do %>
|
|
2
2
|
<% if controller_name == 'orders' %>
|
|
3
|
-
|
|
3
|
+
<% back_url = @order.present? && !@order.completed? ? spree.admin_checkouts_path : spree.admin_orders_path %>
|
|
4
|
+
<%= page_header_back_button back_url, @order %>
|
|
4
5
|
<% else %>
|
|
5
6
|
<%= page_header_back_button spree.edit_admin_order_path(@order) %>
|
|
6
7
|
<% end %>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</button>
|
|
9
9
|
<div class="dropdown-menu" style="min-width: 300px">
|
|
10
10
|
<% @theme.pages.standard.order(name: :asc).find_all(&:customizable?).each do |page| %>
|
|
11
|
-
<%= active_link_to spree.edit_admin_theme_path(@theme, theme_preview_id: @theme_preview.id, page_id: page.id), class: 'dropdown-item', active: @page == page do %>
|
|
11
|
+
<%= active_link_to spree.edit_admin_theme_path(@theme, theme_preview_id: @theme_preview.id, page_id: page.id), class: 'dropdown-item', active: @page == page, data: { turbo_prefetch: false } do %>
|
|
12
12
|
<%= icon page.icon_name, class: 'mr-2' %>
|
|
13
13
|
<%= page.display_name %>
|
|
14
14
|
<% end %>
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
<% add_url = spree.admin_page_section_block_links_path(parent.section, parent) %>
|
|
32
32
|
<% end %>
|
|
33
33
|
|
|
34
|
-
<%= link_to_with_icon 'plus',
|
|
34
|
+
<%= link_to_with_icon 'plus', Spree.t(:add_link), add_url, class: 'btn btn-primary w-100', data: { turbo_method: :post } if add_url && can?(:create, Spree::PageLink.new(parent: parent)) %>
|
|
35
35
|
<% end %>
|
|
36
36
|
</div>
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
<%= sort_link @search,
|
|
16
16
|
:name,
|
|
17
17
|
Spree.t(:name),
|
|
18
|
-
{
|
|
19
|
-
default_order: "desc",
|
|
20
|
-
title: "admin_products_listing_name_title"
|
|
21
|
-
}
|
|
18
|
+
{
|
|
19
|
+
default_order: "desc",
|
|
20
|
+
title: "admin_products_listing_name_title"
|
|
21
|
+
}
|
|
22
22
|
%>
|
|
23
23
|
</th>
|
|
24
24
|
<th scope="col" class="text-center">
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
<th scope="col" class="d-vendor"><%= Spree.t(:vendor) %></th>
|
|
31
31
|
<% end %>
|
|
32
32
|
<th scope="col"><%= Spree.t(:price) %></th>
|
|
33
|
+
|
|
34
|
+
<%= render_admin_partials(:products_table_header_partials) %>
|
|
33
35
|
</tr>
|
|
34
36
|
</thead>
|
|
35
37
|
<tbody>
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
<div data-variants-form-target="optionsContainer" class="options-creator__options_container">
|
|
28
28
|
<% @product.product_option_types.includes(:option_type).reorder('spree_product_option_types.position').each do |product_option_type| %>
|
|
29
29
|
<% option_type = product_option_type.option_type %>
|
|
30
|
-
<%= hidden_field_tag "product[option_type_ids][]", option_type.id %>
|
|
31
30
|
<div class="options-creator__option" data-variants-form-target="option" id="option-<%= option_type.id %>">
|
|
32
31
|
<% if can?(:manage_option_types, @product) %>
|
|
33
32
|
<button class="draggable" type="button">
|
|
@@ -35,7 +34,7 @@
|
|
|
35
34
|
</button>
|
|
36
35
|
<% end%>
|
|
37
36
|
<div class="w-100">
|
|
38
|
-
<div class="d-flex justify-content-between">
|
|
37
|
+
<div class="d-flex justify-content-between align-items-center">
|
|
39
38
|
<h6 data-slot="optionName"><%= option_type.presentation %></h6>
|
|
40
39
|
<% if can?(:manage_option_types, @product) %>
|
|
41
40
|
<button class="btn btn-light btn-sm" type="button" data-action="variants-form#editOption" data-variants-form-option-id-param="<%= option_type.id %>"><%= Spree.t(:edit) %></button>
|
|
@@ -161,7 +160,7 @@
|
|
|
161
160
|
</div>
|
|
162
161
|
</div>
|
|
163
162
|
<%= render 'spree/admin/products/form/variants/variant_template', default_stock_location: default_stock_location_for_product(@product) %>
|
|
164
|
-
<div class="variants-table__body" data-variants-form-target="variantsContainer">
|
|
163
|
+
<div class="variants-table__body" data-variants-form-target="variantsContainer" data-test-id="product-variants-table">
|
|
165
164
|
</div>
|
|
166
165
|
<div class="variants-table__footer">
|
|
167
166
|
<%= Spree.t('admin.variants_form.total_inventory_html', stock_location: current_store.default_stock_location.name, count: raw("<span data-variants-form-target='stockItemsCount'>#{@product.total_on_hand}</span>") )%>
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
<%= tinymce_assets %>
|
|
38
38
|
<link rel="stylesheet" type="text/css" href="https://unpkg.com/trix@2.1.12/dist/trix.css">
|
|
39
39
|
|
|
40
|
+
<script async src="https://ga.jspm.io/npm:es-module-shims@1.8.2/dist/es-module-shims.js" data-turbo-track="reload"></script>
|
|
41
|
+
|
|
40
42
|
<%= javascript_importmap_tags 'application-spree-admin', importmap: Rails.application.config.spree_admin.importmap %>
|
|
41
43
|
|
|
42
44
|
<%= yield :head %>
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
<%= invite_vendor_button(class: 'dropdown-item') if defined?(invite_vendor_button) %>
|
|
23
23
|
|
|
24
|
-
<% if can?(:create, Spree::Store) %>
|
|
24
|
+
<% if can?(:create, Spree::Store) && Spree.root_domain.present? %>
|
|
25
25
|
<div class="dropdown-divider"></div>
|
|
26
26
|
|
|
27
27
|
<span data-toggle="modal" data-target="#modal-lg">
|
|
@@ -66,13 +66,15 @@
|
|
|
66
66
|
</ul>
|
|
67
67
|
<% else %>
|
|
68
68
|
<ul class="nav flex-column">
|
|
69
|
-
<%
|
|
70
|
-
|
|
71
|
-
<%= icon 'map' %>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
<% if can?(:manage, current_store) %>
|
|
70
|
+
<% unless current_store.setup_completed? %>
|
|
71
|
+
<%= nav_item(nil, spree.admin_getting_started_path, icon: 'map') do %>
|
|
72
|
+
<%= icon 'map' %>
|
|
73
|
+
<%= Spree.t('admin.getting_started') %>
|
|
74
|
+
<span class="badge ml-auto badge-info">
|
|
75
|
+
<%= current_store.setup_tasks_done %><span class="opacity-50">/<%= current_store.setup_tasks_total %></span>
|
|
76
|
+
</span>
|
|
77
|
+
<% end %>
|
|
76
78
|
<% end %>
|
|
77
79
|
<% end %>
|
|
78
80
|
|
|
@@ -4,6 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
<div class="row">
|
|
6
6
|
<div class="col-lg-6 offset-lg-3">
|
|
7
|
+
<div class="card mb-4">
|
|
8
|
+
<div class="card-header">
|
|
9
|
+
<h5 class="card-title"><%= Spree.t(:settings) %></h5>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="card-body">
|
|
12
|
+
<div class="form-group">
|
|
13
|
+
<div class="custom-control custom-checkbox">
|
|
14
|
+
<%= f.check_box :preferred_send_consumer_transactional_emails, class: 'custom-control-input' %>
|
|
15
|
+
<%= f.label :preferred_send_consumer_transactional_emails, Spree.t(:send_consumer_transactional_emails), class: 'custom-control-label' %>
|
|
16
|
+
<small class="form-text text-muted mt-2">
|
|
17
|
+
<%= Spree.t('admin.store_form.send_consumer_transactional_emails_help') %>
|
|
18
|
+
</small>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
7
24
|
<div class="card mb-4">
|
|
8
25
|
<div class="card-header">
|
|
9
26
|
<h5 class="card-title">Email addresses</h5>
|
|
@@ -12,12 +12,14 @@
|
|
|
12
12
|
<%= f.error_message_on :name %>
|
|
13
13
|
</div>
|
|
14
14
|
<div class="form-group">
|
|
15
|
-
<%= f.label :
|
|
16
|
-
|
|
15
|
+
<%= f.label :amount_percentage, Spree.t(:rate) %>
|
|
16
|
+
<div class="input-group">
|
|
17
|
+
<%= f.number_field :amount_percentage, class: 'form-control', min: 0, step: 0.1, required: true %>
|
|
18
|
+
<div class="input-group-append">
|
|
19
|
+
<span class="input-group-text">%</span>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
17
22
|
<%= f.error_message_on :amount %>
|
|
18
|
-
<small class="form-text text-muted">
|
|
19
|
-
<%= Spree.t(:tax_rate_amount_explanation) %>
|
|
20
|
-
</small>
|
|
21
23
|
</div>
|
|
22
24
|
|
|
23
25
|
<div class="form-group">
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<%= taxonomy.taxons.count - 1 %>
|
|
11
11
|
</td>
|
|
12
12
|
<td class="w-10 actions">
|
|
13
|
-
<%= link_to_with_icon 'list-tree', Spree.t('admin.manage_taxons'), spree.admin_taxonomy_path(taxonomy), class: 'btn btn-light btn-sm' %>
|
|
14
|
-
<%= link_to_edit(taxonomy, class: 'btn btn-light btn-sm') if can?(:edit, taxonomy) %>
|
|
13
|
+
<%= link_to_with_icon 'list-tree', Spree.t('admin.manage_taxons'), spree.admin_taxonomy_path(taxonomy), class: 'btn btn-light btn-sm', data: { turbo_frame: '_top' } %>
|
|
14
|
+
<%= link_to_edit(taxonomy, class: 'btn btn-light btn-sm', data: { turbo_frame: '_top' }) if can?(:edit, taxonomy) %>
|
|
15
15
|
</td>
|
|
16
16
|
</tr>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= turbo_render_alerts %>
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
<div class="card-body border-bottom">
|
|
81
81
|
<div class="d-flex align-items-center">
|
|
82
82
|
<%= f.label :sort_order, class: 'text-nowrap mr-2 mb-0' %>
|
|
83
|
-
<%= f.select :sort_order, taxon_sort_options_for_select, {}, { class: 'custom-select custom-select-sm w-auto', data: { action: 'change->auto-submit#submit' } } %>
|
|
83
|
+
<%= f.select :sort_order, taxon_sort_options_for_select, {}, { class: 'custom-select custom-select-sm w-auto', data: { action: 'change->auto-submit#submit' } } %>n sort order dropdown in admin (#13030))
|
|
84
84
|
</div>
|
|
85
85
|
</div>
|
|
86
86
|
|
data/config/importmap.rb
CHANGED
|
@@ -23,7 +23,6 @@ pin '@stimulus-components/rails-nested-form', to: '@stimulus-components--rails-n
|
|
|
23
23
|
pin 'stimulus-notification', preload: ['application-spree-admin'] # @2.2.0
|
|
24
24
|
pin 'stimulus-password-visibility', preload: ['application-spree-admin'] # @2.1.1
|
|
25
25
|
pin 'stimulus-sortable', preload: ['application-spree-admin'] # @4.1.1
|
|
26
|
-
pin 'stimulus-textarea-autogrow', preload: ['application-spree-admin'] # @4.1.0
|
|
27
26
|
pin 'hotkeys-js', preload: ['application-spree-admin'] # @3.13.9
|
|
28
27
|
pin 'stimulus-use', preload: ['application-spree-admin'] # @0.51.3
|
|
29
28
|
pin 'stimulus-checkbox-select-all', preload: ['application-spree-admin'] # @5.3.0
|
data/config/locales/en.yml
CHANGED
|
@@ -212,6 +212,7 @@ en:
|
|
|
212
212
|
label: Display the company address field
|
|
213
213
|
customer_support_email_help: This email is visible to your Store visitors in the Footer section
|
|
214
214
|
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
|
|
215
|
+
send_consumer_transactional_emails_help: When unchecked, transactional emails like order confirmations and shipment notifications will not be sent to customers
|
|
215
216
|
store_setup_tasks:
|
|
216
217
|
add_billing_address: Add billing address
|
|
217
218
|
add_products: Add products
|
data/lib/spree/admin/engine.rb
CHANGED
|
@@ -54,11 +54,14 @@ module Spree
|
|
|
54
54
|
:posts_filters_partials,
|
|
55
55
|
:posts_header_partials,
|
|
56
56
|
:product_dropdown_partials,
|
|
57
|
+
:product_page_title_partials,
|
|
57
58
|
:product_form_partials,
|
|
58
59
|
:product_form_sidebar_partials,
|
|
59
60
|
:products_actions_partials,
|
|
60
61
|
:products_filters_partials,
|
|
61
62
|
:products_header_partials,
|
|
63
|
+
:products_table_header_partials,
|
|
64
|
+
:products_table_row_partials,
|
|
62
65
|
:promotions_actions_partials,
|
|
63
66
|
:promotions_filters_partials,
|
|
64
67
|
:promotions_header_partials,
|
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.
|
|
4
|
+
version: 5.1.6
|
|
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-
|
|
11
|
+
date: 2025-09-18 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.
|
|
19
|
+
version: 5.1.6
|
|
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.
|
|
26
|
+
version: 5.1.6
|
|
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.
|
|
33
|
+
version: 5.1.6
|
|
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.
|
|
40
|
+
version: 5.1.6
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: active_link_to
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -415,7 +415,6 @@ files:
|
|
|
415
415
|
- app/controllers/spree/admin/zones_controller.rb
|
|
416
416
|
- app/helpers/spree/admin/base_helper.rb
|
|
417
417
|
- app/helpers/spree/admin/bulk_operations_helper.rb
|
|
418
|
-
- app/helpers/spree/admin/custom_domains_helper.rb
|
|
419
418
|
- app/helpers/spree/admin/customer_returns_helper.rb
|
|
420
419
|
- app/helpers/spree/admin/flash_helper.rb
|
|
421
420
|
- app/helpers/spree/admin/modal_helper.rb
|
|
@@ -530,7 +529,6 @@ files:
|
|
|
530
529
|
- app/views/spree/admin/custom_domains/_custom_domain.html.erb
|
|
531
530
|
- app/views/spree/admin/custom_domains/_custom_domains.html.erb
|
|
532
531
|
- app/views/spree/admin/custom_domains/_form.html.erb
|
|
533
|
-
- app/views/spree/admin/custom_domains/create.turbo_stream.erb
|
|
534
532
|
- app/views/spree/admin/custom_domains/edit.html.erb
|
|
535
533
|
- app/views/spree/admin/custom_domains/index.html.erb
|
|
536
534
|
- app/views/spree/admin/custom_domains/new.html.erb
|
|
@@ -1021,6 +1019,7 @@ files:
|
|
|
1021
1019
|
- app/views/spree/admin/taxonomies/index.html.erb
|
|
1022
1020
|
- app/views/spree/admin/taxonomies/new.html.erb
|
|
1023
1021
|
- app/views/spree/admin/taxonomies/show.html.erb
|
|
1022
|
+
- app/views/spree/admin/taxonomies/update.turbo_stream.erb
|
|
1024
1023
|
- app/views/spree/admin/taxons/_form.html.erb
|
|
1025
1024
|
- app/views/spree/admin/taxons/_rule_form.html.erb
|
|
1026
1025
|
- app/views/spree/admin/taxons/_rules_form.html.erb
|
|
@@ -1030,6 +1029,7 @@ files:
|
|
|
1030
1029
|
- app/views/spree/admin/taxons/rule_forms/_available_on.html.erb
|
|
1031
1030
|
- app/views/spree/admin/taxons/rule_forms/_sale.html.erb
|
|
1032
1031
|
- app/views/spree/admin/taxons/rule_forms/_tag.html.erb
|
|
1032
|
+
- app/views/spree/admin/taxons/update.turbo_stream.erb
|
|
1033
1033
|
- app/views/spree/admin/themes/_theme.html.erb
|
|
1034
1034
|
- app/views/spree/admin/themes/_theme_preview_image.html.erb
|
|
1035
1035
|
- app/views/spree/admin/themes/edit.html.erb
|
|
@@ -1133,7 +1133,6 @@ files:
|
|
|
1133
1133
|
- vendor/javascript/stimulus-password-visibility.js
|
|
1134
1134
|
- vendor/javascript/stimulus-reveal-controller.js
|
|
1135
1135
|
- vendor/javascript/stimulus-sortable.js
|
|
1136
|
-
- vendor/javascript/stimulus-textarea-autogrow.js
|
|
1137
1136
|
- vendor/javascript/stimulus-use.js
|
|
1138
1137
|
- vendor/javascript/tom-select--dist--esm--tom-select.complete.js.js
|
|
1139
1138
|
- vendor/javascript/trix@2.1.12.js
|
|
@@ -1142,9 +1141,9 @@ licenses:
|
|
|
1142
1141
|
- AGPL-3.0-or-later
|
|
1143
1142
|
metadata:
|
|
1144
1143
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
1145
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.1.
|
|
1144
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.1.6
|
|
1146
1145
|
documentation_uri: https://docs.spreecommerce.org/
|
|
1147
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.1.
|
|
1146
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.1.6
|
|
1148
1147
|
post_install_message:
|
|
1149
1148
|
rdoc_options: []
|
|
1150
1149
|
require_paths:
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// stimulus-textarea-autogrow@4.1.0 downloaded from https://ga.jspm.io/npm:stimulus-textarea-autogrow@4.1.0/dist/stimulus-textarea-autogrow.mjs
|
|
2
|
-
|
|
3
|
-
import{Controller as e}from"@hotwired/stimulus";function r(e,t){let i;return(...s)=>{const o=this;clearTimeout(i),i=setTimeout((()=>e.apply(o,s)),t)}}class l extends e{initialize(){this.autogrow=this.autogrow.bind(this)}connect(){this.element.style.overflow="hidden";const e=this.resizeDebounceDelayValue;this.onResize=e>0?r(this.autogrow,e):this.autogrow,this.autogrow(),this.element.addEventListener("input",this.autogrow),window.addEventListener("resize",this.onResize)}disconnect(){window.removeEventListener("resize",this.onResize)}autogrow(){this.element.style.height="auto",this.element.style.height=`${this.element.scrollHeight}px`}}l.values={resizeDebounceDelay:{type:Number,default:100}};export{l as default};
|
|
4
|
-
|