spree_backend 4.3.0.rc1 → 4.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/images/noimage/backend-missing-image.svg +4 -0
- data/app/assets/javascripts/spree/backend/global/select2_autocomplete.es6 +79 -90
- data/app/assets/javascripts/spree/backend/global/select2_populate.es6 +39 -13
- data/app/assets/javascripts/spree/backend/global/tinymce.es6 +1 -1
- data/app/assets/javascripts/spree/backend/menus/menu.es6 +1 -2
- data/app/assets/javascripts/spree/backend/option_type_autocomplete.js +6 -0
- data/app/assets/javascripts/spree/backend/taxon_autocomplete.js +7 -1
- data/app/assets/stylesheets/spree/backend/shared/_base.scss +52 -0
- data/app/controllers/spree/admin/images_controller.rb +25 -8
- data/app/controllers/spree/admin/orders_controller.rb +1 -1
- data/app/controllers/spree/admin/payment_methods_controller.rb +2 -2
- data/app/controllers/spree/admin/products_controller.rb +1 -1
- data/app/controllers/spree/admin/resource_controller.rb +8 -11
- data/app/views/spree/admin/cms_sections/types/_hero_image.html.erb +3 -4
- data/app/views/spree/admin/cms_sections/types/_image_gallery.html.erb +12 -15
- data/app/views/spree/admin/cms_sections/types/_side_by_side_images.html.erb +2 -2
- data/app/views/spree/admin/images/index.html.erb +3 -1
- data/app/views/spree/admin/orders/_line_items.html.erb +1 -1
- data/app/views/spree/admin/orders/_shipment_manifest.html.erb +1 -1
- data/app/views/spree/admin/products/_autocomplete.js.erb +6 -2
- data/app/views/spree/admin/products/_form.html.erb +13 -2
- data/app/views/spree/admin/products/index.html.erb +1 -1
- data/app/views/spree/admin/properties/index.html.erb +10 -0
- data/app/views/spree/admin/shared/_account_nav.html.erb +2 -2
- data/app/views/spree/admin/shared/cms/_spree_product.html.erb +23 -10
- data/app/views/spree/admin/shared/cms/_spree_taxon.html.erb +23 -10
- data/app/views/spree/admin/shared/linkables/_spree_cms_page.erb +1 -6
- data/app/views/spree/admin/users/_lifetime_stats.html.erb +16 -4
- data/app/views/spree/admin/users/items.html.erb +1 -1
- data/app/views/spree/admin/variants/_autocomplete.js.erb +6 -2
- data/spree_backend.gemspec +1 -1
- metadata +13 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f66f277592476e40c4b45e8a044aa4e88aad8d1c5bcaffb9be969e10f66bc9d1
|
4
|
+
data.tar.gz: 3ea8a5805c632a533e065f8a95079a1d3ab6fef5e22a6571aefac630de061bf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 073e261756b177f6370036d7c51b695f68909cf26cd13e74eb58502c6b8bb0f6f226bfe2e80511a9bdb8ecedf0d509c9ceb3f04f5f9633914b22f55e36701271
|
7
|
+
data.tar.gz: de5654888dc5ed1519b8ec3207a9429bc7a259a0c8eea8c8b42ba661fb251b5e14e56407779df5e426cadd09fa0e6b339d6b1f590943b4fc526a3a8f3d1536c7
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-image" viewBox="0 0 16 16">
|
2
|
+
<path d="M6.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
|
3
|
+
<path d="M2.002 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2h-12zm12 1a1 1 0 0 1 1 1v6.5l-3.777-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12V3a1 1 0 0 1 1-1h12z"/>
|
4
|
+
</svg>
|
@@ -1,49 +1,39 @@
|
|
1
1
|
// SELECT2 AUTOCOMPLETE JS
|
2
|
-
//
|
3
|
-
//
|
4
|
-
// as shown here: <select class="select2autocomplete"></select>.
|
2
|
+
// The JavaScript in this file allows Spree developers to set up Select2 autocomplete search
|
3
|
+
// using the API v2 by simply adding data attributes to a select element.
|
5
4
|
|
6
5
|
// REQUIRED ATTRIBUTES
|
7
|
-
//
|
8
|
-
//
|
9
|
-
//
|
10
|
-
// Example:
|
6
|
+
// You must provide a URL for the API V2, use the format shown below. See backend.js for other API V2 URL's.
|
7
|
+
// REQUIRED:
|
11
8
|
// data-autocomplete-url-value="products_api_v2"
|
12
9
|
|
13
|
-
//
|
14
|
-
//
|
15
|
-
//
|
16
|
-
//
|
17
|
-
//
|
18
|
-
// data-autocomplete-
|
19
|
-
// data-autocomplete-
|
20
|
-
// data-autocomplete-
|
21
|
-
// data-autocomplete-
|
22
|
-
// data-autocomplete-min-input-value="4" <- Minimum input for search | DEFAULT is: 3
|
23
|
-
// data-autocomplete-search-query-value="title_i_cont" <- Custom search query | DEFAULT is: 'name_i_cont'
|
24
|
-
// data-autocomplete-custom-return-id-value="permalink" <- Return a custom attribute rather than the ID | DEFAULT: returns id
|
10
|
+
// OPTIONAL:
|
11
|
+
// data-autocomplete-placeholder-value="Seach Pages" <- Sets the placeholder | DEFAULT is: 'Search'.
|
12
|
+
// data-autocomplete-clear-value=boolean <- Allow select2 to be cleared | DEFAULT is: false (no clear button).
|
13
|
+
// data-autocomplete-multiple-value=boolean <- Multiple or Single select | DEFAULT is: false (single).
|
14
|
+
// data-autocomplete-return-attr-value="pretty_name" <- Return Attribute. | DEFAULT is: 'name'.
|
15
|
+
// data-autocomplete-min-input-value="4" <- Minimum input for search | DEFAULT is: 3.
|
16
|
+
// data-autocomplete-search-query-value="title_i_cont" <- Custom search query | DEFAULT is: 'name_i_cont'.
|
17
|
+
// data-autocomplete-custom-return-id-value="permalink" <- Return a custom attribute | DEFAULT: returns id.
|
18
|
+
// data-autocomplete-debug-mode-value=boolean <- Turn on console loggin of data returned by the request.
|
25
19
|
//
|
26
|
-
//
|
27
|
-
//
|
28
|
-
//
|
29
|
-
// here we only want to retuen Pages that have linkable slugs, not homepages, and so we filter those using the
|
30
|
-
// data attributes shown below.
|
31
|
-
//
|
32
|
-
// Examples:
|
33
|
-
// data-autocomplete-additional-query-value="type_not_eq" <- Additional hard coded query | DEFAULT: null (not used)
|
34
|
-
// data-autocomplete-additional-term-value="Spree::Cms::Pages::Homepage" <- Additional hard coded term | DEFAULT: null (not used)
|
20
|
+
// Add your own custom URL params to the request as needed
|
21
|
+
// EXAMPLE:
|
22
|
+
// data-autocomplete-additional-url-params-value="filter[type_not_eq]=Spree::Cms::Pages::Homepage"
|
35
23
|
|
36
24
|
document.addEventListener('DOMContentLoaded', function() {
|
37
|
-
|
38
|
-
select2Autocompletes.forEach(element => buildParamsFromDataAttrs(element))
|
25
|
+
loadAutoCompleteParams()
|
39
26
|
})
|
40
27
|
|
41
|
-
|
28
|
+
// eslint-disable-next-line no-unused-vars
|
29
|
+
function loadAutoCompleteParams() {
|
30
|
+
const select2Autocompletes = document.querySelectorAll('select[data-autocomplete-url-value]')
|
31
|
+
select2Autocompletes.forEach(element => buildParamsFromDataAttrs(element))
|
32
|
+
}
|
33
|
+
|
34
|
+
function buildParamsFromDataAttrs(element) {
|
42
35
|
$(element).select2Autocomplete({
|
43
|
-
// Required Attributes
|
44
36
|
apiUrl: Spree.routes[element.dataset.autocompleteUrlValue],
|
45
|
-
|
46
|
-
// Optional Attributes
|
47
37
|
placeholder: element.dataset.autocompletePlaceholderValue,
|
48
38
|
allow_clear: element.dataset.autocompleteClearValue,
|
49
39
|
multiple: element.dataset.autocompleteMultipleValue,
|
@@ -51,19 +41,17 @@ function buildParamsFromDataAttrs (element) {
|
|
51
41
|
minimum_input: element.dataset.autocompleteMinInputValue,
|
52
42
|
search_query: element.dataset.autocompleteSearchQueryValue,
|
53
43
|
custom_return_id: element.dataset.autocompleteCustomReturnIdValue,
|
54
|
-
|
55
|
-
|
56
|
-
additional_query: element.dataset.autocompleteAdditionalQueryValue,
|
57
|
-
additional_term: element.dataset.autocompleteAdditionalTermValue
|
44
|
+
additional_url_params: element.dataset.autocompleteAdditionalUrlParamsValue,
|
45
|
+
debug_mode: element.dataset.autocompleteDebugModeValue
|
58
46
|
})
|
59
47
|
}
|
60
48
|
|
61
|
-
// Can also be called directly as javastript.
|
62
49
|
$.fn.select2Autocomplete = function(params) {
|
63
|
-
|
64
|
-
|
50
|
+
let apiUrl = null
|
51
|
+
let returnedFields
|
65
52
|
|
66
|
-
|
53
|
+
const resourcePlural = params.apiUrl.match(/([^/]*)\/*$/)[1]
|
54
|
+
const resourceSingular = resourcePlural.slice(0, -1)
|
67
55
|
const select2placeHolder = params.placeholder || Spree.translations.search
|
68
56
|
const select2Multiple = params.multiple || false
|
69
57
|
const select2allowClear = params.allow_clear || false
|
@@ -71,19 +59,42 @@ $.fn.select2Autocomplete = function(params) {
|
|
71
59
|
const minimumInput = params.minimum_input || 3
|
72
60
|
const searchQuery = params.search_query || 'name_i_cont'
|
73
61
|
const customReturnId = params.custom_return_id || null
|
74
|
-
const
|
75
|
-
const
|
62
|
+
const additionalUrlParams = params.additional_url_params || null
|
63
|
+
const DebugMode = params.debug_mode || null
|
76
64
|
|
65
|
+
//
|
66
|
+
// Set up a clean URL for sparseFields
|
67
|
+
if (customReturnId == null) {
|
68
|
+
returnedFields = returnAttribute
|
69
|
+
} else {
|
70
|
+
returnedFields = `${returnAttribute},${customReturnId}`
|
71
|
+
}
|
72
|
+
const sparseFields = `fields[${resourceSingular}]=${returnedFields}`
|
73
|
+
|
74
|
+
//
|
75
|
+
// Set up a clean URL for Additional URL Params
|
76
|
+
if (additionalUrlParams != null) {
|
77
|
+
// URL + Additional URL Params + Sparse Fields
|
78
|
+
apiUrl = `${params.apiUrl}?${additionalUrlParams}&${sparseFields}`
|
79
|
+
} else {
|
80
|
+
// URL + Sparse Fields (the default response for a noraml Select2)
|
81
|
+
apiUrl = `${params.apiUrl}?${sparseFields}`
|
82
|
+
}
|
83
|
+
|
84
|
+
if (DebugMode != null) console.log('Request URL:' + apiUrl)
|
85
|
+
|
86
|
+
//
|
87
|
+
// Format the returned values.
|
77
88
|
function formatList(values) {
|
78
89
|
if (customReturnId) {
|
79
|
-
return values.map(function
|
90
|
+
return values.map(function(obj) {
|
80
91
|
return {
|
81
92
|
id: obj.attributes[customReturnId],
|
82
93
|
text: obj.attributes[returnAttribute]
|
83
94
|
}
|
84
95
|
})
|
85
96
|
} else {
|
86
|
-
return values.map(function
|
97
|
+
return values.map(function(obj) {
|
87
98
|
return {
|
88
99
|
id: obj.id,
|
89
100
|
text: obj.attributes[returnAttribute]
|
@@ -92,52 +103,30 @@ $.fn.select2Autocomplete = function(params) {
|
|
92
103
|
}
|
93
104
|
}
|
94
105
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
}
|
110
|
-
},
|
111
|
-
processResults: function(json) {
|
112
|
-
return {
|
113
|
-
results: formatList(json.data)
|
106
|
+
//
|
107
|
+
// Set-up Select2 and make AJAX request.
|
108
|
+
this.select2({
|
109
|
+
multiple: select2Multiple,
|
110
|
+
allowClear: select2allowClear,
|
111
|
+
placeholder: select2placeHolder,
|
112
|
+
minimumInputLength: minimumInput,
|
113
|
+
ajax: {
|
114
|
+
url: apiUrl,
|
115
|
+
headers: Spree.apiV2Authentication(),
|
116
|
+
data: function(params) {
|
117
|
+
return {
|
118
|
+
filter: {
|
119
|
+
[searchQuery]: params.term
|
114
120
|
}
|
115
121
|
}
|
116
|
-
}
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
placeholder: select2placeHolder,
|
123
|
-
minimumInputLength: minimumInput,
|
124
|
-
ajax: {
|
125
|
-
url: apiUrl,
|
126
|
-
headers: Spree.apiV2Authentication(),
|
127
|
-
data: function (params) {
|
128
|
-
return {
|
129
|
-
filter: {
|
130
|
-
[searchQuery]: params.term,
|
131
|
-
[additionalQuery]: additionalTerm
|
132
|
-
}
|
133
|
-
}
|
134
|
-
},
|
135
|
-
processResults: function(json) {
|
136
|
-
return {
|
137
|
-
results: formatList(json.data)
|
138
|
-
}
|
122
|
+
},
|
123
|
+
processResults: function(json) {
|
124
|
+
if (DebugMode != null) console.log(json)
|
125
|
+
|
126
|
+
return {
|
127
|
+
results: formatList(json.data)
|
139
128
|
}
|
140
129
|
}
|
141
|
-
}
|
142
|
-
}
|
130
|
+
}
|
131
|
+
})
|
143
132
|
}
|
@@ -1,11 +1,9 @@
|
|
1
1
|
/**
|
2
2
|
populateSelectOptionsFromApi(params)
|
3
|
+
Allows you to easily fetch data from API (Platfrom v2) and populate an empty <select> with <option> tags, including a selected <option> tag.
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
including a selected <option> tag.
|
7
|
-
|
8
|
-
## EXAMPLE USE CASE called from ERB view file:
|
5
|
+
## EXAMPLE A
|
6
|
+
# Populating a list of all taxons including a selected item
|
9
7
|
|
10
8
|
populateSelectOptionsFromApi({
|
11
9
|
targetElement: '#mySelectElement',
|
@@ -16,6 +14,24 @@
|
|
16
14
|
selectedOption: <%= @menu_item.linked_resource_id %>
|
17
15
|
<% end %>
|
18
16
|
})
|
17
|
+
|
18
|
+
## EXAMPLE B
|
19
|
+
# Populating a single selected item using filter and returning an attribute other than the ID
|
20
|
+
|
21
|
+
<% if resource.link_one.present? %>
|
22
|
+
<script>
|
23
|
+
populateSelectOptionsFromApi({
|
24
|
+
targetElement: "#<%= save_to %>Select2",
|
25
|
+
apiUrl: Spree.routes.taxons_api_v2 + "?filter[permalink_matches]=<%= resource.send(save_to) %>",
|
26
|
+
returnValueFromAttributes: 'permalink',
|
27
|
+
returnOptionText: 'pretty_name',
|
28
|
+
|
29
|
+
<% if resource.send(save_to) %>
|
30
|
+
selectedOption: "<%= resource.send(save_to) %>"
|
31
|
+
<% end %>
|
32
|
+
})
|
33
|
+
</script>
|
34
|
+
<% end %>
|
19
35
|
**/
|
20
36
|
|
21
37
|
// eslint-disable-next-line no-unused-vars
|
@@ -32,30 +48,40 @@ const handleErrors = function(response) {
|
|
32
48
|
const createRequest = function(params, succeed, fail) {
|
33
49
|
const targetElement = params.targetElement
|
34
50
|
const apiUrl = params.apiUrl
|
35
|
-
const
|
51
|
+
const returnOptionText = params.returnOptionText
|
52
|
+
const returnValueFromAttributes = params.returnValueFromAttributes || null
|
36
53
|
const selectedOption = params.selectedOption
|
37
54
|
const selectEl = document.querySelector(targetElement)
|
38
55
|
|
39
56
|
fetch(apiUrl, { headers: Spree.apiV2Authentication() })
|
40
57
|
.then((response) => handleErrors(response))
|
41
|
-
.then((json) => succeed(json.data,
|
58
|
+
.then((json) => succeed(json.data, returnValueFromAttributes, returnOptionText, selectEl, selectedOption))
|
42
59
|
.catch((error) => fail(error, selectEl))
|
43
60
|
}
|
44
61
|
|
45
|
-
const updateSelectSuccess = function(parsedData,
|
62
|
+
const updateSelectSuccess = function(parsedData, returnValueFromAttributes, returnOptionText, selectEl, selectedOption) {
|
63
|
+
const selectedOpt = selectEl.querySelector('option[selected]')
|
64
|
+
|
46
65
|
parsedData.forEach((object) => {
|
47
66
|
const optionEl = document.createElement('option')
|
48
|
-
optionEl.value = object.id
|
49
|
-
optionEl.innerHTML = object.attributes[returnAttribute]
|
50
67
|
|
51
|
-
if (
|
68
|
+
if (returnValueFromAttributes == null) {
|
69
|
+
optionEl.value = object.id
|
70
|
+
if (parseInt(selectedOption, 10) === parseInt(object.id, 10)) optionEl.selected = true
|
71
|
+
} else {
|
72
|
+
optionEl.value = object.attributes[returnValueFromAttributes]
|
73
|
+
if (selectedOpt.value === object.attributes[returnValueFromAttributes]) {
|
74
|
+
selectedOpt.remove()
|
75
|
+
|
76
|
+
optionEl.setAttribute('selected', 'selected')
|
77
|
+
}
|
78
|
+
}
|
52
79
|
|
80
|
+
optionEl.innerHTML = object.attributes[returnOptionText]
|
53
81
|
selectEl.appendChild(optionEl)
|
54
82
|
})
|
55
83
|
}
|
56
84
|
|
57
85
|
const updateSelectError = function(error, selectEl) {
|
58
|
-
selectEl.disabled = true
|
59
|
-
|
60
86
|
console.log(error)
|
61
87
|
}
|
@@ -6,6 +6,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
6
6
|
'image table paste code link table'
|
7
7
|
],
|
8
8
|
menubar: false,
|
9
|
-
toolbar: 'undo redo | styleselect | bold italic link | alignleft aligncenter alignright alignjustify | table | bullist numlist outdent indent | code '
|
9
|
+
toolbar: 'undo redo | styleselect | bold italic link forecolor backcolor | alignleft aligncenter alignright alignjustify | table | bullist numlist outdent indent | code '
|
10
10
|
});
|
11
11
|
})
|
@@ -29,12 +29,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
29
29
|
|
30
30
|
function handleMenuItemMove(evt) {
|
31
31
|
const data = {
|
32
|
-
moved_item_id: parseInt(evt.item.dataset.itemId, 10),
|
33
32
|
new_parent_id: parseInt(evt.to.dataset.parentId, 10) || null,
|
34
33
|
new_position_idx: parseInt(evt.newIndex, 10)
|
35
34
|
}
|
36
35
|
|
37
|
-
fetch(Spree.routes.menus_items_api_v2
|
36
|
+
fetch(`${Spree.routes.menus_items_api_v2}/${evt.item.dataset.itemId}/reposition`, {
|
38
37
|
method: 'PATCH',
|
39
38
|
headers: {
|
40
39
|
Authorization: 'Bearer ' + OAUTH_TOKEN,
|
@@ -1,6 +1,8 @@
|
|
1
1
|
$.fn.optionTypeAutocomplete = function () {
|
2
2
|
'use strict'
|
3
3
|
|
4
|
+
console.warn('optionTypeAutocomplete is deprecated and will be removed in Spree 5.0')
|
5
|
+
|
4
6
|
this.select2({
|
5
7
|
minimumInputLength: 2,
|
6
8
|
multiple: true,
|
@@ -23,5 +25,9 @@ $.fn.optionTypeAutocomplete = function () {
|
|
23
25
|
}
|
24
26
|
|
25
27
|
$(document).ready(function () {
|
28
|
+
var productOptionTypeSelector = document.getElementById('product_option_type_ids')
|
29
|
+
if (productOptionTypeSelector == null) return
|
30
|
+
if (productOptionTypeSelector.hasAttribute('data-autocomplete-url-value')) return
|
31
|
+
|
26
32
|
$('#product_option_type_ids').optionTypeAutocomplete()
|
27
33
|
})
|
@@ -2,6 +2,8 @@ $.fn.taxonAutocomplete = function() {
|
|
2
2
|
'use strict'
|
3
3
|
|
4
4
|
function formatTaxonList(values) {
|
5
|
+
console.warn('taxonAutocomplete is deprecated and will be removed in Spree 5.0')
|
6
|
+
|
5
7
|
return values.map(function (obj) {
|
6
8
|
return {
|
7
9
|
id: obj.id,
|
@@ -20,7 +22,7 @@ $.fn.taxonAutocomplete = function() {
|
|
20
22
|
data: function (params) {
|
21
23
|
return {
|
22
24
|
q: {
|
23
|
-
name_cont: params.term
|
25
|
+
name_cont: params.term
|
24
26
|
},
|
25
27
|
token: Spree.api_key
|
26
28
|
}
|
@@ -35,5 +37,9 @@ $.fn.taxonAutocomplete = function() {
|
|
35
37
|
}
|
36
38
|
|
37
39
|
$(document).ready(function () {
|
40
|
+
var productTaxonSelector = document.getElementById('product_taxon_ids')
|
41
|
+
if (productTaxonSelector == null) return
|
42
|
+
if (productTaxonSelector.hasAttribute('data-autocomplete-url-value')) return
|
43
|
+
|
38
44
|
$('#product_taxon_ids').taxonAutocomplete()
|
39
45
|
})
|
@@ -28,6 +28,58 @@ figure.admin-img-holder {
|
|
28
28
|
}
|
29
29
|
}
|
30
30
|
|
31
|
+
div.admin-product-image-container {
|
32
|
+
border: 1px solid $gray-500;
|
33
|
+
background-color: #fefefe;
|
34
|
+
border-radius: $border-radius;
|
35
|
+
overflow: hidden;
|
36
|
+
display: flex;
|
37
|
+
justify-content: center;
|
38
|
+
margin: auto;
|
39
|
+
|
40
|
+
a {
|
41
|
+
display: flex
|
42
|
+
}
|
43
|
+
|
44
|
+
img {
|
45
|
+
max-width: 100%;
|
46
|
+
height: auto;
|
47
|
+
align-self: center;
|
48
|
+
transform: scale(1.6);
|
49
|
+
}
|
50
|
+
|
51
|
+
svg {
|
52
|
+
color: $gray-600;
|
53
|
+
align-self: center;
|
54
|
+
}
|
55
|
+
|
56
|
+
&.mini-img {
|
57
|
+
border-radius: $border-radius / 2;
|
58
|
+
width: 24px;
|
59
|
+
height: 24px;
|
60
|
+
}
|
61
|
+
|
62
|
+
&.small-img {
|
63
|
+
border-radius: $border-radius;
|
64
|
+
width: 50px;
|
65
|
+
height: 50px;
|
66
|
+
}
|
67
|
+
|
68
|
+
&.product-img {
|
69
|
+
border-width: 2px;
|
70
|
+
border-radius: $border-radius * 2;
|
71
|
+
width: 100px;
|
72
|
+
height: 100px;
|
73
|
+
}
|
74
|
+
|
75
|
+
&.large-img {
|
76
|
+
border-width: 3px;
|
77
|
+
border-radius: $border-radius * 3;
|
78
|
+
width: 300px;
|
79
|
+
height: 300px;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
31
83
|
.js-remove-promo-rule-option-value {
|
32
84
|
color: $primary !important;
|
33
85
|
&:hover {
|
@@ -1,10 +1,7 @@
|
|
1
1
|
module Spree
|
2
2
|
module Admin
|
3
3
|
class ImagesController < ResourceController
|
4
|
-
|
5
|
-
|
6
|
-
belongs_to 'spree/product', find_by: :slug
|
7
|
-
|
4
|
+
before_action :load_product
|
8
5
|
before_action :load_edit_data, except: :index
|
9
6
|
|
10
7
|
create.before :set_viewable
|
@@ -13,24 +10,44 @@ module Spree
|
|
13
10
|
private
|
14
11
|
|
15
12
|
def location_after_destroy
|
16
|
-
spree.admin_product_images_url(@
|
13
|
+
spree.admin_product_images_url(@product)
|
17
14
|
end
|
18
15
|
|
19
16
|
def location_after_save
|
20
|
-
spree.admin_product_images_url(
|
17
|
+
spree.admin_product_images_url(@product)
|
21
18
|
end
|
22
19
|
|
23
20
|
def load_edit_data
|
24
|
-
@variants =
|
21
|
+
@variants = @product.variants.map do |variant|
|
25
22
|
[variant.sku_and_options_text, variant.id]
|
26
23
|
end
|
27
|
-
@variants.insert(0, [Spree.t(:all),
|
24
|
+
@variants.insert(0, [Spree.t(:all), @product.master_id])
|
28
25
|
end
|
29
26
|
|
30
27
|
def set_viewable
|
31
28
|
@image.viewable_type = 'Spree::Variant'
|
32
29
|
@image.viewable_id = params[:image][:viewable_id]
|
33
30
|
end
|
31
|
+
|
32
|
+
def load_product
|
33
|
+
@product = scope.friendly.find(params[:product_id])
|
34
|
+
end
|
35
|
+
|
36
|
+
def scope
|
37
|
+
current_store.products
|
38
|
+
end
|
39
|
+
|
40
|
+
def collection_url
|
41
|
+
spree.admin_product_images_url
|
42
|
+
end
|
43
|
+
|
44
|
+
def modle_class
|
45
|
+
Spree::Image
|
46
|
+
end
|
47
|
+
|
48
|
+
def collection
|
49
|
+
@collection ||= load_product.variant_images
|
50
|
+
end
|
34
51
|
end
|
35
52
|
end
|
36
53
|
end
|
@@ -113,7 +113,7 @@ module Spree
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def resend
|
116
|
-
|
116
|
+
@order.deliver_order_confirmation_email
|
117
117
|
flash[:success] = Spree.t(:order_email_resent)
|
118
118
|
|
119
119
|
redirect_back fallback_location: spree.edit_admin_order_url(@order)
|
@@ -10,7 +10,7 @@ module Spree
|
|
10
10
|
def create
|
11
11
|
@payment_method = params[:payment_method].delete(:type).constantize.new(payment_method_params)
|
12
12
|
@object = @payment_method
|
13
|
-
|
13
|
+
set_current_store
|
14
14
|
invoke_callbacks(:create, :before)
|
15
15
|
if @payment_method.save
|
16
16
|
invoke_callbacks(:create, :after)
|
@@ -39,7 +39,7 @@ module Spree
|
|
39
39
|
end
|
40
40
|
|
41
41
|
if @payment_method.update(attributes)
|
42
|
-
|
42
|
+
set_current_store
|
43
43
|
invoke_callbacks(:update, :after)
|
44
44
|
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:payment_method))
|
45
45
|
redirect_to spree.edit_admin_payment_method_path(@payment_method)
|
@@ -30,7 +30,7 @@ module Spree
|
|
30
30
|
end
|
31
31
|
invoke_callbacks(:update, :before)
|
32
32
|
if @object.update(permitted_resource_params)
|
33
|
-
|
33
|
+
set_current_store
|
34
34
|
invoke_callbacks(:update, :after)
|
35
35
|
flash[:success] = flash_message_for(@object, :successfully_updated)
|
36
36
|
respond_with(@object) do |format|
|
@@ -3,7 +3,8 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
3
3
|
|
4
4
|
helper_method :new_object_url, :edit_object_url, :object_url, :collection_url
|
5
5
|
before_action :load_resource, except: :update_positions
|
6
|
-
before_action :set_currency, :
|
6
|
+
before_action :set_currency, :set_current_store, only: [:new, :create]
|
7
|
+
|
7
8
|
rescue_from ActiveRecord::RecordNotFound, with: :resource_not_found
|
8
9
|
|
9
10
|
respond_to :html
|
@@ -26,7 +27,7 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
26
27
|
def update
|
27
28
|
invoke_callbacks(:update, :before)
|
28
29
|
if @object.update(permitted_resource_params)
|
29
|
-
|
30
|
+
set_current_store
|
30
31
|
invoke_callbacks(:update, :after)
|
31
32
|
respond_with(@object) do |format|
|
32
33
|
format.html do
|
@@ -207,21 +208,17 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
207
208
|
collection_url
|
208
209
|
end
|
209
210
|
|
210
|
-
def
|
211
|
+
def set_current_store
|
211
212
|
return if @object.nil?
|
212
213
|
|
213
|
-
@object
|
214
|
-
@object.cost_currency = current_currency if model_class.method_defined?(:cost_currency=)
|
214
|
+
ensure_current_store(@object)
|
215
215
|
end
|
216
216
|
|
217
|
-
def
|
217
|
+
def set_currency
|
218
218
|
return if @object.nil?
|
219
219
|
|
220
|
-
|
221
|
-
|
222
|
-
elsif model_class.method_defined?(:stores) && @object.stores.exclude?(current_store)
|
223
|
-
@object.stores << current_store
|
224
|
-
end
|
220
|
+
@object.currency = current_currency if model_class.method_defined?(:currency=)
|
221
|
+
@object.cost_currency = current_currency if model_class.method_defined?(:cost_currency=)
|
225
222
|
end
|
226
223
|
|
227
224
|
# URL helpers
|
@@ -37,10 +37,9 @@
|
|
37
37
|
<%= image_tag main_app.url_for(@cms_section.image_one) %>
|
38
38
|
</figure>
|
39
39
|
<% end %>
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
<% end %>
|
40
|
+
|
41
|
+
<%= f.file_field :image_one %>
|
42
|
+
<%= f.error_message_on :image_one %>
|
44
43
|
<% end %>
|
45
44
|
<small class="form-text text-muted"><%= Spree.t('admin.cms.hero.aspect_ratio') %></small>
|
46
45
|
</div>
|
@@ -22,7 +22,7 @@
|
|
22
22
|
|
23
23
|
<div class="row">
|
24
24
|
<div class="col-12 col-md-4 mb-3">
|
25
|
-
<div class="card p-3">
|
25
|
+
<div id="image_a_details" class="card p-3">
|
26
26
|
<div class="text-center">
|
27
27
|
<h4 class="pb-2"><%= Spree.t('admin.cms.image_gallery.image_a') %></h4>
|
28
28
|
<%= f.field_container :image_one, class: ['form-group'] do %>
|
@@ -35,10 +35,9 @@
|
|
35
35
|
<%= image_tag main_app.url_for(@cms_section.image_one) %>
|
36
36
|
</figure>
|
37
37
|
<% end %>
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
<% end %>
|
38
|
+
|
39
|
+
<%= f.file_field :image_one %>
|
40
|
+
<%= f.error_message_on :image_one %>
|
42
41
|
<% end %>
|
43
42
|
</div>
|
44
43
|
<small class="text-muted mb-4"><%= Spree.t('admin.cms.image_gallery.square_image') %></small>
|
@@ -67,7 +66,7 @@
|
|
67
66
|
</div>
|
68
67
|
|
69
68
|
<div class="col-12 col-md-4 mb-3">
|
70
|
-
<div class="card p-3">
|
69
|
+
<div id="image_b_details" class="card p-3">
|
71
70
|
<div class="text-center">
|
72
71
|
<h4 class="pb-2"><%= Spree.t('admin.cms.image_gallery.image_b') %></h4>
|
73
72
|
<%= f.field_container :image_two, class: ['form-group'] do %>
|
@@ -80,10 +79,9 @@
|
|
80
79
|
<%= image_tag main_app.url_for(@cms_section.image_two) %>
|
81
80
|
</figure>
|
82
81
|
<% end %>
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
<% end %>
|
82
|
+
|
83
|
+
<%= f.file_field :image_two %>
|
84
|
+
<%= f.error_message_on :image_two %>
|
87
85
|
<% end %>
|
88
86
|
</div>
|
89
87
|
<small class="text-muted mb-4"><%= Spree.t('admin.cms.image_gallery.tall_image') %></small>
|
@@ -112,7 +110,7 @@
|
|
112
110
|
</div>
|
113
111
|
|
114
112
|
<div class="col-12 col-md-4 mb-3">
|
115
|
-
<div class="card p-3">
|
113
|
+
<div id="image_c_details" class="card p-3">
|
116
114
|
<div class="text-center">
|
117
115
|
<h4 class="pb-2"><%= Spree.t('admin.cms.image_gallery.image_c') %></h4>
|
118
116
|
<%= f.field_container :image_three, class: ['form-group'] do %>
|
@@ -125,10 +123,9 @@
|
|
125
123
|
<%= image_tag main_app.url_for(@cms_section.image_three) %>
|
126
124
|
</figure>
|
127
125
|
<% end %>
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
<% end %>
|
126
|
+
|
127
|
+
<%= f.file_field :image_three %>
|
128
|
+
<%= f.error_message_on :image_three %>
|
132
129
|
<% end %>
|
133
130
|
</div>
|
134
131
|
<small class="text-muted mb-4"><%= Spree.t('admin.cms.image_gallery.square_image') %></small>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="row pb-0">
|
2
2
|
<div class="col-12 col-md-6 mb-3">
|
3
|
-
<div class="card p-3">
|
3
|
+
<div id="left_image_details" class="card p-3">
|
4
4
|
<div class="text-center">
|
5
5
|
<h4 class="pb-2"><%= Spree.t('admin.cms.side_by_side.left_image') %></h4>
|
6
6
|
<%= f.field_container :image_one, class: ['form-group'] do %>
|
@@ -51,7 +51,7 @@
|
|
51
51
|
</div>
|
52
52
|
|
53
53
|
<div class="col-12 col-md-6 mb-3">
|
54
|
-
<div class="card p-3">
|
54
|
+
<div id="right_image_details" class="card p-3">
|
55
55
|
<div class="text-center">
|
56
56
|
<h4 class="pb-2"><%= Spree.t('admin.cms.side_by_side.right_image') %></h4>
|
57
57
|
<%= f.field_container :image_two, class: ['form-group'] do %>
|
@@ -41,7 +41,9 @@
|
|
41
41
|
<% end %>
|
42
42
|
</td>
|
43
43
|
<td class="image">
|
44
|
-
|
44
|
+
<div class="admin-product-image-container small-img">
|
45
|
+
<%= link_to image_tag(main_app.url_for(image.url(:product))), main_app.rails_blob_url(image.attachment) %>
|
46
|
+
</div>
|
45
47
|
</td>
|
46
48
|
<% if has_variants %>
|
47
49
|
<td><%= options_text_for(image) %></td>
|
@@ -20,7 +20,7 @@
|
|
20
20
|
<% order.line_items.each do |item| %>
|
21
21
|
<tr class="line-item" id="line-item-<%= item.id %>">
|
22
22
|
<td class="line-item-image image text-center">
|
23
|
-
<%= link_to
|
23
|
+
<%= link_to small_image(item.variant), edit_admin_product_path(item.variant.product) %>
|
24
24
|
</td>
|
25
25
|
<td class="line-item-name text-center">
|
26
26
|
<%= link_to item.name, edit_admin_product_path(item.variant.product) %>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% shipment.manifest.each do |item| %>
|
2
2
|
<tr class="stock-item" data-item-quantity="<%= item.quantity %>">
|
3
3
|
<td class="item-image image text-center">
|
4
|
-
<%= link_to
|
4
|
+
<%= link_to small_image(item.variant), edit_admin_product_path(item.variant.product) %>
|
5
5
|
</td>
|
6
6
|
|
7
7
|
<td class="item-name">
|
@@ -17,9 +17,13 @@
|
|
17
17
|
</nav>
|
18
18
|
<div class='image'>
|
19
19
|
{{#if image }}
|
20
|
-
<
|
20
|
+
<div class="admin-product-image-container small-img">
|
21
|
+
<img src='{{image}}' alt='{{ product.attributes.name }}' class='thumbnail rounded border border' />
|
22
|
+
</div>
|
21
23
|
{{ else }}
|
22
|
-
<
|
24
|
+
<div class="admin-product-image-container small-img">
|
25
|
+
<%= inline_svg_tag "noimage/backend-missing-image.svg", class: "noimage", size: "60%*60%" %>
|
26
|
+
</div>
|
23
27
|
{{/if}}
|
24
28
|
</div>
|
25
29
|
<div class="p-0 pt-1 text-center product-info">
|
@@ -204,7 +204,12 @@
|
|
204
204
|
<%= f.label :taxon_ids, Spree.t(:taxons) %>
|
205
205
|
|
206
206
|
<% if can? :modify, Spree::Classification %>
|
207
|
-
<%= f.select :taxon_ids, options_from_collection_for_select(@product.taxons, :id, :pretty_name, @product.taxon_ids),
|
207
|
+
<%= f.select :taxon_ids, options_from_collection_for_select(@product.taxons, :id, :pretty_name, @product.taxon_ids),
|
208
|
+
{ include_hidden: true },
|
209
|
+
multiple: true,
|
210
|
+
data: { autocomplete_url_value: 'taxons_api_v2',
|
211
|
+
autocomplete_return_attr_value: 'pretty_name',
|
212
|
+
autocomplete_multiple_value: true } %>
|
208
213
|
<% elsif @product.taxons.any? %>
|
209
214
|
<ul class="text_list">
|
210
215
|
<% @product.taxons.each do |taxon| %>
|
@@ -223,7 +228,13 @@
|
|
223
228
|
<%= f.label :option_type_ids, Spree.t(:option_types) %>
|
224
229
|
|
225
230
|
<% if can? :modify, Spree::ProductOptionType %>
|
226
|
-
|
231
|
+
<%= f.select :option_type_ids, options_from_collection_for_select(@product.option_types, :id, :name, @product.option_type_ids),
|
232
|
+
{ include_hidden: true },
|
233
|
+
multiple: true,
|
234
|
+
class: 'select2-hidden-accessible',
|
235
|
+
data: { autocomplete_url_value: 'option_types_api_v2',
|
236
|
+
autocomplete_return_attr_value: 'name',
|
237
|
+
autocomplete_multiple_value: true } %>
|
227
238
|
<% elsif @product.option_types.any? %>
|
228
239
|
<ul class="text_list">
|
229
240
|
<% @product.option_types.each do |type| %>
|
@@ -68,7 +68,7 @@
|
|
68
68
|
<tr <%== "style='color: red;'" if product.deleted? %> id="<%= spree_dom_id product %>" data-hook="admin_products_index_rows" class="<%= cycle('odd', 'even') %>">
|
69
69
|
<td scope="row" class="image">
|
70
70
|
<%= link_to edit_admin_product_path(product) do %>
|
71
|
-
<%=
|
71
|
+
<%= small_image product %>
|
72
72
|
<% end %>
|
73
73
|
</td>
|
74
74
|
<td><%= link_to product.try(:name), edit_admin_product_path(product) %></td>
|
@@ -28,6 +28,16 @@
|
|
28
28
|
</div>
|
29
29
|
</div>
|
30
30
|
|
31
|
+
<div class="row">
|
32
|
+
<div class="col-12 col-lg-6">
|
33
|
+
<div class="form-group">
|
34
|
+
<%= label_tag :q_filterable_eq, Spree.t(:filterable_status) %>
|
35
|
+
<%= f.select :filterable_eq, options_for_select([[Spree.t(:filterable), true], [Spree.t(:non_filterable), false]]), { include_blank: true }, class: 'select2-clear js-filterable' %>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
|
31
41
|
<div class="form-actions" data-hook="admin_pproperties_index_search_buttons">
|
32
42
|
<%= button Spree.t(:search), 'search.svg' %>
|
33
43
|
</div>
|
@@ -37,7 +37,7 @@
|
|
37
37
|
|
38
38
|
<div class="dropdown-divider m-0"></div>
|
39
39
|
|
40
|
-
<%= link_to 'http://
|
40
|
+
<%= link_to 'http://spreecommerce.org/contact', target: :blank, class: 'd-block text-dark py-3 px-4 dropdown-item' do %>
|
41
41
|
<%= svg_icon name: "info.svg", width: '18', height: '18' %>
|
42
42
|
|
43
43
|
<%= Spree.t(:support) %>
|
@@ -49,7 +49,7 @@
|
|
49
49
|
<%= Spree.t(:join_slack) %>
|
50
50
|
<% end %>
|
51
51
|
|
52
|
-
<%= link_to 'https://
|
52
|
+
<%= link_to 'https://dev-docs.spreecommerce.org/extensions/extensions', target: :blank, class: 'd-block text-dark py-3 px-4 dropdown-item' do %>
|
53
53
|
<%= svg_icon name: "extensions.svg", width: '18', height: '18' %>
|
54
54
|
|
55
55
|
<%= Spree.t(:extensions_directory) %>
|
@@ -1,14 +1,27 @@
|
|
1
1
|
<%= f.field_container save_to, class: ['form-group'] do %>
|
2
2
|
<%= f.label save_to, Spree.t('admin.cms.link_to_product') %>
|
3
|
-
<%= f.select save_to,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
autocomplete_return_attr_value: 'name',
|
12
|
-
autocomplete_custom_return_id_value: 'slug' } %>
|
3
|
+
<%= f.select save_to, options_from_collection_for_select([resource], save_to, save_to, resource.send(save_to) || nil), { include_blank: true },
|
4
|
+
id: "cms_section_#{save_to}",
|
5
|
+
data: { autocomplete_placeholder_value: Spree.t('admin.navigation.seach_for_a_product'),
|
6
|
+
autocomplete_clear_value: true,
|
7
|
+
autocomplete_url_value: 'products_api_v2',
|
8
|
+
autocomplete_return_attr_value: 'name',
|
9
|
+
autocomplete_custom_return_id_value: 'slug' } %>
|
10
|
+
|
13
11
|
<%= f.error_message_on :save_to %>
|
14
12
|
<% end %>
|
13
|
+
|
14
|
+
<% if resource.link_one.present? %>
|
15
|
+
<script>
|
16
|
+
populateSelectOptionsFromApi({
|
17
|
+
targetElement: "#cms_section_<%= save_to %>",
|
18
|
+
apiUrl: Spree.routes.products_api_v2 + "?filter[slug_matches]=<%= resource.send(save_to) %>",
|
19
|
+
returnValueFromAttributes: 'slug',
|
20
|
+
returnOptionText: 'name',
|
21
|
+
|
22
|
+
<% if resource.send(save_to) %>
|
23
|
+
selectedOption: "<%= resource.send(save_to) %>"
|
24
|
+
<% end %>
|
25
|
+
})
|
26
|
+
</script>
|
27
|
+
<% end %>
|
@@ -1,14 +1,27 @@
|
|
1
1
|
<%= f.field_container save_to, class: ['form-group'] do %>
|
2
2
|
<%= f.label save_to, Spree.t('admin.cms.link_to_taxon') %>
|
3
|
-
<%= f.select save_to,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
autocomplete_return_attr_value: 'permalink',
|
12
|
-
autocomplete_custom_return_id_value: 'permalink' } %>
|
3
|
+
<%= f.select save_to, options_from_collection_for_select([resource], save_to, save_to, resource.send(save_to) || nil), { include_blank: true },
|
4
|
+
id: "cms_section_#{save_to}",
|
5
|
+
data: { autocomplete_placeholder_value: Spree.t('admin.navigation.seach_for_a_taxon'),
|
6
|
+
autocomplete_clear_value: true,
|
7
|
+
autocomplete_url_value: 'taxons_api_v2',
|
8
|
+
autocomplete_return_attr_value: 'pretty_name',
|
9
|
+
autocomplete_custom_return_id_value: 'permalink' } %>
|
10
|
+
|
13
11
|
<%= f.error_message_on :save_to %>
|
14
12
|
<% end %>
|
13
|
+
|
14
|
+
<% if resource.link_one.present? %>
|
15
|
+
<script>
|
16
|
+
populateSelectOptionsFromApi({
|
17
|
+
targetElement: "#cms_section_<%= save_to %>",
|
18
|
+
apiUrl: Spree.routes.taxons_api_v2 + "?filter[permalink_matches]=<%= resource.send(save_to) %>",
|
19
|
+
returnValueFromAttributes: 'permalink',
|
20
|
+
returnOptionText: 'pretty_name',
|
21
|
+
|
22
|
+
<% if resource.send(save_to) %>
|
23
|
+
selectedOption: "<%= resource.send(save_to) %>"
|
24
|
+
<% end %>
|
25
|
+
})
|
26
|
+
</script>
|
27
|
+
<% end %>
|
@@ -16,12 +16,7 @@
|
|
16
16
|
autocomplete_url_value: 'pages_api_v2',
|
17
17
|
autocomplete_return_attr_value: 'title',
|
18
18
|
autocomplete_search_query_value: 'title_i_cont',
|
19
|
-
|
20
|
-
# Hard coded additional filter to filter out homepages from
|
21
|
-
# the results. Homepages don't have a slug, and we already have
|
22
|
-
# a dedicated Home Page link_to type.
|
23
|
-
autocomplete_additional_query_value: 'type_not_eq',
|
24
|
-
autocomplete_additional_term_value: 'Spree::Cms::Pages::Homepage' } %>
|
19
|
+
autocomplete_additional_url_params_value: 'filter[type_not_eq]=Spree::Cms::Pages::Homepage' } %>
|
25
20
|
|
26
21
|
<%= f.error_message_on :linked_resource_id %>
|
27
22
|
<small class="form-text text-muted"><%= resource.link %></small>
|
@@ -8,19 +8,31 @@
|
|
8
8
|
<table class="table" id="user-lifetime-stats" data-hook>
|
9
9
|
<tr>
|
10
10
|
<td width="30%"><%= Spree.t(:total_sales) %>:</td>
|
11
|
-
<td
|
11
|
+
<td>
|
12
|
+
<% @user.report_values_for(:lifetime_value, current_store).each do |value| %>
|
13
|
+
<div><%= value %></div>
|
14
|
+
<% end %>
|
15
|
+
</td>
|
12
16
|
</tr>
|
13
17
|
<tr>
|
14
18
|
<td><%= Spree.t(:num_orders) %>:</td>
|
15
|
-
<td><%= @user.order_count %></td>
|
19
|
+
<td><%= @user.order_count(current_store) %></td>
|
16
20
|
</tr>
|
17
21
|
<tr>
|
18
22
|
<td><%= Spree.t(:average_order_value) %>:</td>
|
19
|
-
<td
|
23
|
+
<td>
|
24
|
+
<% @user.report_values_for(:average_order_value, current_store).each do |value| %>
|
25
|
+
<div><%= value %></div>
|
26
|
+
<% end %>
|
27
|
+
</td>
|
20
28
|
</tr>
|
21
29
|
<tr>
|
22
30
|
<td><%= Spree.t('admin.user.store_credits') %>:</td>
|
23
|
-
<td id="store_credit"
|
31
|
+
<td id="store_credit">
|
32
|
+
<% @user.available_store_credits(current_store).each do |value| %>
|
33
|
+
<div><%= value %></div>
|
34
|
+
<% end %>
|
35
|
+
</td>
|
24
36
|
</tr>
|
25
37
|
<tr>
|
26
38
|
<td><%= Spree.t(:member_since) %>:</td>
|
@@ -27,7 +27,7 @@
|
|
27
27
|
<tr class="stock-item" data-item-quantity="<%= item.quantity %>">
|
28
28
|
<td class="order-completed-at"><%= order_time(order.completed_at) if order.completed_at %></td>
|
29
29
|
<td class="item-image">
|
30
|
-
<%=
|
30
|
+
<%= small_image(item.variant) %>
|
31
31
|
</td>
|
32
32
|
<td class="item-name">
|
33
33
|
<%= item.name %>
|
@@ -2,9 +2,13 @@
|
|
2
2
|
<div class='variant-autocomplete-item media align-items-center'>
|
3
3
|
<figure class='variant-image media-left mb-0 mr-3'>
|
4
4
|
{{#if variant.image }}
|
5
|
-
<
|
5
|
+
<div class="admin-product-image-container small-img">
|
6
|
+
<img src='{{variant.image}}' class="thumbnail mb-0" />
|
7
|
+
</div>
|
6
8
|
{{ else }}
|
7
|
-
<
|
9
|
+
<div class="admin-product-image-container small-img">
|
10
|
+
<%= inline_svg_tag "noimage/backend-missing-image.svg", class: "noimage", size: "60%*60%" %>
|
11
|
+
</div>
|
8
12
|
{{/if}}
|
9
13
|
</figure>
|
10
14
|
|
data/spree_backend.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.metadata = {
|
16
16
|
"bug_tracker_uri" => "https://github.com/spree/spree/issues",
|
17
17
|
"changelog_uri" => "https://github.com/spree/spree/releases/tag/v#{s.version}",
|
18
|
-
"documentation_uri" => "https://
|
18
|
+
"documentation_uri" => "https://dev-docs.spreecommerce.org/",
|
19
19
|
"source_code_uri" => "https://github.com/spree/spree/tree/v#{s.version}",
|
20
20
|
}
|
21
21
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_backend
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.3.
|
4
|
+
version: 4.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Schofield
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-01-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: spree_api
|
@@ -17,28 +17,28 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 4.3.
|
20
|
+
version: 4.3.1
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 4.3.
|
27
|
+
version: 4.3.1
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: spree_core
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 4.3.
|
34
|
+
version: 4.3.1
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 4.3.
|
41
|
+
version: 4.3.1
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: babel-transpiler
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -298,6 +298,7 @@ files:
|
|
298
298
|
- app/assets/images/backend-void.svg
|
299
299
|
- app/assets/images/backend-window-sidebar.svg
|
300
300
|
- app/assets/images/credit_cards/credit_card.gif
|
301
|
+
- app/assets/images/noimage/backend-missing-image.svg
|
301
302
|
- app/assets/images/noimage/large.png
|
302
303
|
- app/assets/images/noimage/mini.png
|
303
304
|
- app/assets/images/noimage/product.png
|
@@ -817,9 +818,9 @@ licenses:
|
|
817
818
|
- BSD-3-Clause
|
818
819
|
metadata:
|
819
820
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
820
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v4.3.
|
821
|
-
documentation_uri: https://
|
822
|
-
source_code_uri: https://github.com/spree/spree/tree/v4.3.
|
821
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v4.3.1
|
822
|
+
documentation_uri: https://dev-docs.spreecommerce.org/
|
823
|
+
source_code_uri: https://github.com/spree/spree/tree/v4.3.1
|
823
824
|
post_install_message:
|
824
825
|
rdoc_options: []
|
825
826
|
require_paths:
|
@@ -831,12 +832,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
831
832
|
version: '2.5'
|
832
833
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
833
834
|
requirements:
|
834
|
-
- - "
|
835
|
+
- - ">="
|
835
836
|
- !ruby/object:Gem::Version
|
836
|
-
version:
|
837
|
+
version: '0'
|
837
838
|
requirements:
|
838
839
|
- none
|
839
|
-
rubygems_version: 3.2.
|
840
|
+
rubygems_version: 3.2.22
|
840
841
|
signing_key:
|
841
842
|
specification_version: 4
|
842
843
|
summary: Admin Dashboard for Spree eCommerce platform
|