spree_backend 4.3.0.rc1 → 4.3.1
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/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
|