alchemy-solidus 7.5.1 → 7.6.0
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/components/alchemy/admin/link_dialog/product_tab.rb +2 -1
- data/app/components/alchemy/admin/product_select.rb +14 -4
- data/app/components/alchemy/admin/taxon_select.rb +46 -0
- data/app/components/alchemy/admin/variant_select.rb +48 -0
- data/app/javascript/alchemy_solidus/components/ajax_config.js +10 -0
- data/app/javascript/alchemy_solidus/components/product_select.js +56 -27
- data/app/javascript/alchemy_solidus/components/taxon_select.js +48 -0
- data/app/javascript/alchemy_solidus/components/variant_select.js +79 -0
- data/app/javascript/alchemy_solidus.js +2 -0
- data/app/views/alchemy/ingredients/_spree_product_editor.html.erb +10 -21
- data/app/views/alchemy/ingredients/_spree_taxon_editor.html.erb +10 -21
- data/app/views/alchemy/ingredients/_spree_variant_editor.html.erb +10 -22
- data/config/initializers/alchemy.rb +20 -20
- data/config/initializers/spree.rb +7 -7
- data/db/migrate/20120229160509_create_alchemy_essence_spree_products.rb +6 -6
- data/db/migrate/20191107135822_create_alchemy_essence_spree_variants.rb +1 -1
- data/lib/alchemy/solidus/alchemy_user_extension.rb +1 -1
- data/lib/alchemy/solidus/spree_admin_unauthorized_redirect.rb +1 -1
- data/lib/alchemy/solidus/spree_user_extension.rb +1 -1
- data/lib/alchemy/solidus/version.rb +1 -1
- data/lib/generators/alchemy/solidus/install/install_generator.rb +32 -32
- metadata +8 -7
- data/app/javascript/alchemy_solidus/product_select.js +0 -37
- data/app/javascript/alchemy_solidus/select2_config.js +0 -24
- data/app/javascript/alchemy_solidus/taxon_select.js +0 -37
- data/app/javascript/alchemy_solidus/variant_select.js +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15dc076bf68bd7b1c707371eb37043cce0118953337e4cb83a4d3b618986c96f
|
4
|
+
data.tar.gz: b4d750ba90f8e34ca84116c92fe644a286f2d7dbb3ce27e856ecef9b292e3f0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33b5b8f176dbf5db6047537a149b55048956f5732bd0c63b47e2b67de6a0949240d8d62786288bc76f9ddd69bfad544c7c4509017d176c8891654958480389e1
|
7
|
+
data.tar.gz: 1fe4a15e0c4da77036c0df1e6adbe2c68fa8d6f5e0adcb5d56f4602b0c6156beb870fcfabb9ec1f71a7d3cb19b91b52aa10f6d738fff45ccd43b95831e88d083
|
@@ -47,7 +47,8 @@ module Alchemy
|
|
47
47
|
select = render self.class.product_select_class.new(
|
48
48
|
current_alchemy_user.spree_api_key,
|
49
49
|
product: product,
|
50
|
-
url: spree.api_products_path
|
50
|
+
url: spree.api_products_path,
|
51
|
+
value_attribute: :slug
|
51
52
|
).with_content(input)
|
52
53
|
content_tag("div", label + select, class: "input select")
|
53
54
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module Alchemy
|
2
2
|
module Admin
|
3
3
|
class ProductSelect < ViewComponent::Base
|
4
|
+
VALUE_ATTRIBUTES = %i[id slug].freeze
|
5
|
+
|
4
6
|
delegate :spree, to: :helpers
|
5
7
|
|
6
|
-
attr_reader :api_key, :product, :url, :query_params
|
8
|
+
attr_reader :api_key, :product, :url, :query_params, :placeholder
|
7
9
|
|
8
|
-
def initialize(api_key, product: nil, url: nil, query_params: nil)
|
10
|
+
def initialize(api_key, product: nil, url: nil, query_params: nil, placeholder: nil, value_attribute: nil)
|
9
11
|
@api_key = api_key
|
10
12
|
@product = product
|
11
13
|
@url = url
|
12
14
|
@query_params = query_params
|
15
|
+
@placeholder = placeholder
|
16
|
+
@value_attribute = value_attribute
|
13
17
|
end
|
14
18
|
|
15
19
|
def call
|
@@ -18,9 +22,15 @@ module Alchemy
|
|
18
22
|
|
19
23
|
private
|
20
24
|
|
25
|
+
def value_attribute
|
26
|
+
@value_attribute.in?(VALUE_ATTRIBUTES) ? @value_attribute : :id
|
27
|
+
end
|
28
|
+
|
21
29
|
def attributes
|
22
30
|
attrs = {
|
31
|
+
placeholder: placeholder || Alchemy.t(:search_product, scope: "solidus"),
|
23
32
|
url: url || spree.api_products_path,
|
33
|
+
"value-attribute": value_attribute,
|
24
34
|
"api-key": api_key
|
25
35
|
}
|
26
36
|
|
@@ -35,8 +45,8 @@ module Alchemy
|
|
35
45
|
|
36
46
|
def serialized_selection
|
37
47
|
{
|
38
|
-
|
39
|
-
|
48
|
+
id: product.send(value_attribute),
|
49
|
+
name: product.name
|
40
50
|
}.to_json
|
41
51
|
end
|
42
52
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Alchemy
|
2
|
+
module Admin
|
3
|
+
class TaxonSelect < ViewComponent::Base
|
4
|
+
delegate :spree, to: :helpers
|
5
|
+
|
6
|
+
attr_reader :api_key, :taxon, :url, :query_params, :placeholder
|
7
|
+
|
8
|
+
def initialize(api_key, taxon: nil, url: nil, query_params: nil, placeholder: nil)
|
9
|
+
@api_key = api_key
|
10
|
+
@taxon = taxon
|
11
|
+
@url = url
|
12
|
+
@query_params = query_params
|
13
|
+
@placeholder = placeholder
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
content_tag("alchemy-taxon-select", content, attributes)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def attributes
|
23
|
+
attrs = {
|
24
|
+
url: url || spree.api_taxons_path,
|
25
|
+
placeholder: placeholder || Alchemy.t(:search_taxon, scope: :solidus),
|
26
|
+
"api-key": api_key
|
27
|
+
}
|
28
|
+
|
29
|
+
attrs[:"query-params"] = query_params.to_json if query_params
|
30
|
+
|
31
|
+
if taxon
|
32
|
+
attrs[:selection] = serialized_selection
|
33
|
+
end
|
34
|
+
|
35
|
+
attrs
|
36
|
+
end
|
37
|
+
|
38
|
+
def serialized_selection
|
39
|
+
{
|
40
|
+
id: taxon.id,
|
41
|
+
text: taxon.pretty_name
|
42
|
+
}.to_json
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Alchemy
|
2
|
+
module Admin
|
3
|
+
class VariantSelect < ViewComponent::Base
|
4
|
+
delegate :spree, to: :helpers
|
5
|
+
|
6
|
+
attr_reader :api_key, :variant, :url, :query_params, :placeholder
|
7
|
+
|
8
|
+
def initialize(api_key, variant: nil, url: nil, query_params: nil, placeholder: nil)
|
9
|
+
@api_key = api_key
|
10
|
+
@variant = variant
|
11
|
+
@url = url
|
12
|
+
@query_params = query_params
|
13
|
+
@placeholder = placeholder
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
content_tag("alchemy-variant-select", content, attributes)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def attributes
|
23
|
+
attrs = {
|
24
|
+
url: url || spree.api_variants_path,
|
25
|
+
placeholder: placeholder || Alchemy.t(:search_variant, scope: :solidus),
|
26
|
+
"api-key": api_key
|
27
|
+
}
|
28
|
+
|
29
|
+
attrs[:"query-params"] = query_params.to_json if query_params
|
30
|
+
|
31
|
+
if variant
|
32
|
+
attrs[:selection] = serialized_selection
|
33
|
+
end
|
34
|
+
|
35
|
+
attrs
|
36
|
+
end
|
37
|
+
|
38
|
+
def serialized_selection
|
39
|
+
{
|
40
|
+
id: variant.id,
|
41
|
+
name: variant.name,
|
42
|
+
sku: variant.sku,
|
43
|
+
options_text: variant.options_text
|
44
|
+
}.to_json
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,42 +1,71 @@
|
|
1
|
-
import "
|
2
|
-
|
3
|
-
export default class ProductSelect extends HTMLElement {
|
4
|
-
connectedCallback() {
|
5
|
-
const input = this.querySelector("#product_link")
|
6
|
-
input.classList.add("alchemy_selectbox")
|
7
|
-
|
8
|
-
$(input).alchemyProductSelect({
|
9
|
-
baseUrl: this.url,
|
10
|
-
apiToken: this.apiToken,
|
11
|
-
initSelection: this._initSelection.bind(this),
|
12
|
-
formatResultObject: this._formatResult.bind(this),
|
13
|
-
})
|
14
|
-
}
|
1
|
+
import { RemoteSelect } from "alchemy_admin/components/remote_select"
|
2
|
+
import ajaxConfig from "alchemy_solidus/components/ajax_config"
|
15
3
|
|
16
|
-
|
17
|
-
|
4
|
+
export default class ProductSelect extends RemoteSelect {
|
5
|
+
get ajaxConfig() {
|
6
|
+
return ajaxConfig(super.ajaxConfig, this.apiKey)
|
18
7
|
}
|
19
8
|
|
20
|
-
get
|
9
|
+
get apiKey() {
|
21
10
|
return this.getAttribute("api-key")
|
22
11
|
}
|
23
12
|
|
24
|
-
|
25
|
-
|
26
|
-
const product = JSON.parse(selection)
|
27
|
-
callback(this._formatResult(product))
|
13
|
+
get valueAttribute() {
|
14
|
+
return this.getAttribute("value-attribute") || "id"
|
28
15
|
}
|
29
16
|
|
30
|
-
|
17
|
+
/**
|
18
|
+
* Parses server response into select2 results object
|
19
|
+
* @param {object} response
|
20
|
+
* @returns {object}
|
21
|
+
* @private
|
22
|
+
*/
|
23
|
+
_parseResponse(response) {
|
31
24
|
return {
|
32
|
-
|
33
|
-
|
25
|
+
results: response.products.map((product) => {
|
26
|
+
return {
|
27
|
+
id: this._parsedValue(product),
|
28
|
+
name: product.name,
|
29
|
+
}
|
30
|
+
}),
|
31
|
+
more: response.current_page * response.per_page < response.total_count,
|
34
32
|
}
|
35
33
|
}
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
/**
|
36
|
+
* The value used for the select send to the server
|
37
|
+
* after submitting the form this select is placed in.
|
38
|
+
*
|
39
|
+
* Note: Returning an url if the `value-attribute` is "slug".
|
40
|
+
*
|
41
|
+
* @param {object} product
|
42
|
+
* @returns {string}
|
43
|
+
*/
|
44
|
+
_parsedValue(product) {
|
45
|
+
return this.valueAttribute === "slug"
|
46
|
+
? `${Spree.mountedAt()}products/${product.slug}`
|
47
|
+
: product.id
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* result which is visible if a product was selected
|
52
|
+
* @param {object} product
|
53
|
+
* @returns {string}
|
54
|
+
* @private
|
55
|
+
*/
|
56
|
+
_renderResult(product) {
|
57
|
+
return product.name
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* html template for each list entry
|
62
|
+
* @param {object} product
|
63
|
+
* @param {string} term
|
64
|
+
* @returns {string}
|
65
|
+
* @private
|
66
|
+
*/
|
67
|
+
_renderListEntry(product, term) {
|
68
|
+
return this._hightlightTerm(product.name, term)
|
40
69
|
}
|
41
70
|
}
|
42
71
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { RemoteSelect } from "alchemy_admin/components/remote_select"
|
2
|
+
import ajaxConfig from "alchemy_solidus/components/ajax_config"
|
3
|
+
|
4
|
+
export default class TaxonSelect extends RemoteSelect {
|
5
|
+
get ajaxConfig() {
|
6
|
+
return ajaxConfig(super.ajaxConfig, this.apiKey)
|
7
|
+
}
|
8
|
+
|
9
|
+
get apiKey() {
|
10
|
+
return this.getAttribute("api-key")
|
11
|
+
}
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Parses server response into select2 results object
|
15
|
+
* @param {object} response
|
16
|
+
* @returns {object}
|
17
|
+
* @private
|
18
|
+
*/
|
19
|
+
_parseResponse(response) {
|
20
|
+
return {
|
21
|
+
results: response.taxons,
|
22
|
+
more: response.current_page * response.per_page < response.total_count,
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
/**
|
27
|
+
* result which is visible if a taxon was selected
|
28
|
+
* @param {object} taxon
|
29
|
+
* @returns {string}
|
30
|
+
* @private
|
31
|
+
*/
|
32
|
+
_renderResult(taxon) {
|
33
|
+
return taxon.text || taxon.pretty_name
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* html template for each list entry
|
38
|
+
* @param {object} taxon
|
39
|
+
* @param {string} term
|
40
|
+
* @returns {string}
|
41
|
+
* @private
|
42
|
+
*/
|
43
|
+
_renderListEntry(taxon, term) {
|
44
|
+
return this._hightlightTerm(taxon.pretty_name, term)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
customElements.define("alchemy-taxon-select", TaxonSelect)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import { RemoteSelect } from "alchemy_admin/components/remote_select"
|
2
|
+
import ajaxConfig from "alchemy_solidus/components/ajax_config"
|
3
|
+
|
4
|
+
export default class VariantSelect extends RemoteSelect {
|
5
|
+
get ajaxConfig() {
|
6
|
+
return ajaxConfig(super.ajaxConfig, this.apiKey)
|
7
|
+
}
|
8
|
+
|
9
|
+
get apiKey() {
|
10
|
+
return this.getAttribute("api-key")
|
11
|
+
}
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Search query send to server from select2
|
15
|
+
* @param {string} term
|
16
|
+
* @param {number} page
|
17
|
+
* @returns {object}
|
18
|
+
* @private
|
19
|
+
*/
|
20
|
+
_searchQuery(term, page) {
|
21
|
+
return {
|
22
|
+
q: {
|
23
|
+
product_name_or_sku_cont: term,
|
24
|
+
...JSON.parse(this.queryParams),
|
25
|
+
},
|
26
|
+
page: page,
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Parses server response into select2 results object
|
32
|
+
* @param {object} response
|
33
|
+
* @returns {object}
|
34
|
+
* @private
|
35
|
+
*/
|
36
|
+
_parseResponse(response) {
|
37
|
+
return {
|
38
|
+
results: response.variants,
|
39
|
+
more: response.current_page * response.per_page < response.total_count,
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* result which is visible if a variant was selected
|
45
|
+
* @param {object} variant
|
46
|
+
* @returns {string}
|
47
|
+
* @private
|
48
|
+
*/
|
49
|
+
_renderResult(variant) {
|
50
|
+
return variant.options_text
|
51
|
+
? `${variant.name} - ${variant.options_text}`
|
52
|
+
: variant.name
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* html template for each list entry
|
57
|
+
* @param {object} variant
|
58
|
+
* @param {string} term
|
59
|
+
* @returns {string}
|
60
|
+
* @private
|
61
|
+
*/
|
62
|
+
_renderListEntry(variant, term) {
|
63
|
+
const name = this._hightlightTerm(variant.name, term)
|
64
|
+
const sku = this._hightlightTerm(variant.sku, term)
|
65
|
+
return `
|
66
|
+
<div class="variant-select-result">
|
67
|
+
<div>
|
68
|
+
<span>${name}</span>
|
69
|
+
</div>
|
70
|
+
<div>
|
71
|
+
<span>${variant.options_text}</span>
|
72
|
+
<span>${sku}</span>
|
73
|
+
</div>
|
74
|
+
</div>
|
75
|
+
`
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
customElements.define("alchemy-variant-select", VariantSelect)
|
@@ -3,26 +3,15 @@
|
|
3
3
|
data: spree_product_editor.data_attributes do %>
|
4
4
|
<%= element_form.fields_for(:ingredients, spree_product_editor.ingredient) do |f| %>
|
5
5
|
<%= ingredient_label(spree_product_editor, :product_id) %>
|
6
|
-
<%=
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
<%= render Alchemy::Admin::ProductSelect.new(
|
7
|
+
current_alchemy_user.spree_api_key,
|
8
|
+
query_params: spree_product_editor.settings[:query_params],
|
9
|
+
product: spree_product_editor.product
|
10
|
+
) do %>
|
11
|
+
<%= f.text_field :product_id,
|
12
|
+
value: spree_product_editor.product&.id,
|
13
|
+
id: spree_product_editor.form_field_id(:product_id),
|
14
|
+
class: 'full_width' %>
|
15
|
+
<% end %>
|
10
16
|
<% end %>
|
11
17
|
<% end %>
|
12
|
-
|
13
|
-
<script type="module">
|
14
|
-
import "alchemy_solidus/product_select"
|
15
|
-
|
16
|
-
$('#<%= spree_product_editor.form_field_id(:product_id) %>').alchemyProductSelect({
|
17
|
-
placeholder: "<%= Alchemy.t(:search_product, scope: 'solidus') %>",
|
18
|
-
apiToken: "<%= current_alchemy_user.spree_api_key %>",
|
19
|
-
baseUrl: "<%= spree.api_products_path %>",
|
20
|
-
query_params: <%== spree_product_editor.settings[:query_params].to_json %>,
|
21
|
-
<% if spree_product_editor.product %>
|
22
|
-
initialSelection: {
|
23
|
-
id: <%= spree_product_editor.product.id %>,
|
24
|
-
text: "<%= spree_product_editor.product.name %>"
|
25
|
-
}
|
26
|
-
<% end %>
|
27
|
-
})
|
28
|
-
</script>
|
@@ -3,26 +3,15 @@
|
|
3
3
|
data: spree_taxon_editor.data_attributes do %>
|
4
4
|
<%= element_form.fields_for(:ingredients, spree_taxon_editor.ingredient) do |f| %>
|
5
5
|
<%= ingredient_label(spree_taxon_editor, :taxon_id) %>
|
6
|
-
<%=
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
<%= render Alchemy::Admin::TaxonSelect.new(
|
7
|
+
current_alchemy_user.spree_api_key,
|
8
|
+
query_params: spree_taxon_editor.settings[:query_params],
|
9
|
+
taxon: spree_taxon_editor.ingredient.taxon
|
10
|
+
) do %>
|
11
|
+
<%= f.text_field :taxon_id,
|
12
|
+
value: spree_taxon_editor.taxon&.id,
|
13
|
+
id: spree_taxon_editor.form_field_id(:taxon_id),
|
14
|
+
class: "full_width" %>
|
15
|
+
<% end %>
|
10
16
|
<% end %>
|
11
17
|
<% end %>
|
12
|
-
|
13
|
-
<script type="module">
|
14
|
-
import "alchemy_solidus/taxon_select"
|
15
|
-
|
16
|
-
$('#<%= spree_taxon_editor.form_field_id(:taxon_id) %>').alchemyTaxonSelect({
|
17
|
-
placeholder: "<%= Alchemy.t(:search_taxon, scope: 'solidus') %>",
|
18
|
-
apiToken: "<%= current_alchemy_user.spree_api_key %>",
|
19
|
-
baseUrl: "<%= spree.api_taxons_path %>",
|
20
|
-
query_params: <%== spree_taxon_editor.settings[:query_params].to_json %>,
|
21
|
-
<% if spree_taxon_editor.taxon %>
|
22
|
-
initialSelection: {
|
23
|
-
id: <%= spree_taxon_editor.taxon.id %>,
|
24
|
-
text: "<%= spree_taxon_editor.taxon.pretty_name %>"
|
25
|
-
}
|
26
|
-
<% end %>
|
27
|
-
})
|
28
|
-
</script>
|
@@ -3,10 +3,16 @@
|
|
3
3
|
data: spree_variant_editor.data_attributes do %>
|
4
4
|
<%= element_form.fields_for(:ingredients, spree_variant_editor.ingredient) do |f| %>
|
5
5
|
<%= ingredient_label(spree_variant_editor, :variant_id) %>
|
6
|
-
<%=
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
<%= render Alchemy::Admin::VariantSelect.new(
|
7
|
+
current_alchemy_user.spree_api_key,
|
8
|
+
query_params: spree_variant_editor.settings[:query_params],
|
9
|
+
variant: spree_variant_editor.ingredient.variant
|
10
|
+
) do %>
|
11
|
+
<%= f.text_field :variant_id,
|
12
|
+
value: spree_variant_editor.variant&.id,
|
13
|
+
id: spree_variant_editor.form_field_id(:variant_id),
|
14
|
+
class: 'alchemy_selectbox full_width' %>
|
15
|
+
<% end %>
|
10
16
|
<% end %>
|
11
17
|
<% end %>
|
12
18
|
|
@@ -28,21 +34,3 @@
|
|
28
34
|
}
|
29
35
|
}
|
30
36
|
</style>
|
31
|
-
|
32
|
-
<script type="module">
|
33
|
-
import "alchemy_solidus/variant_select"
|
34
|
-
|
35
|
-
$('#<%= spree_variant_editor.form_field_id(:variant_id) %>').alchemyVariantSelect({
|
36
|
-
placeholder: "<%= Alchemy.t(:search_variant, scope: 'solidus') %>",
|
37
|
-
apiToken: "<%= current_alchemy_user.spree_api_key %>",
|
38
|
-
baseUrl: "<%= spree.api_variants_path %>",
|
39
|
-
query_params: <%== spree_variant_editor.settings[:query_params].to_json %>,
|
40
|
-
<% if spree_variant_editor.variant %>
|
41
|
-
initialSelection: {
|
42
|
-
id: <%= spree_variant_editor.variant.id %>,
|
43
|
-
name: "<%= spree_variant_editor.variant.name %>",
|
44
|
-
options_text: "<%= spree_variant_editor.variant.options_text %>"
|
45
|
-
}
|
46
|
-
<% end %>
|
47
|
-
})
|
48
|
-
</script>
|
@@ -1,27 +1,27 @@
|
|
1
1
|
alchemy_module = {
|
2
|
-
engine_name:
|
3
|
-
name:
|
2
|
+
engine_name: "spree",
|
3
|
+
name: "solidus",
|
4
4
|
navigation: {
|
5
|
-
controller:
|
6
|
-
action:
|
7
|
-
name:
|
8
|
-
icon: Alchemy.gem_version >= Gem::Version.new("7.4.0.a") ?
|
9
|
-
data: {
|
5
|
+
controller: "/spree/admin/orders",
|
6
|
+
action: "index",
|
7
|
+
name: "Store",
|
8
|
+
icon: (Alchemy.gem_version >= Gem::Version.new("7.4.0.a")) ? "shopping-cart" : "shopping-cart-line",
|
9
|
+
data: {turbolinks: false},
|
10
10
|
sub_navigation: [
|
11
11
|
{
|
12
|
-
controller:
|
13
|
-
action:
|
14
|
-
name:
|
12
|
+
controller: "/spree/admin/orders",
|
13
|
+
action: "index",
|
14
|
+
name: "Orders"
|
15
15
|
},
|
16
16
|
{
|
17
|
-
controller:
|
18
|
-
action:
|
19
|
-
name:
|
17
|
+
controller: "/spree/admin/products",
|
18
|
+
action: "index",
|
19
|
+
name: "Products"
|
20
20
|
},
|
21
21
|
{
|
22
|
-
controller:
|
23
|
-
action:
|
24
|
-
name:
|
22
|
+
controller: "/spree/admin/stock_items",
|
23
|
+
action: "index",
|
24
|
+
name: "Stock"
|
25
25
|
}
|
26
26
|
]
|
27
27
|
}
|
@@ -30,12 +30,12 @@ alchemy_module = {
|
|
30
30
|
if defined?(Spree::Auth::Engine)
|
31
31
|
alchemy_module[:navigation][:sub_navigation].push(
|
32
32
|
{
|
33
|
-
controller:
|
34
|
-
action:
|
35
|
-
name:
|
33
|
+
controller: "/spree/admin/users",
|
34
|
+
action: "index",
|
35
|
+
name: "Users"
|
36
36
|
}
|
37
37
|
)
|
38
|
-
Alchemy.user_class_name =
|
38
|
+
Alchemy.user_class_name = "Spree::User"
|
39
39
|
Alchemy.current_user_method = :spree_current_user
|
40
40
|
|
41
41
|
if Alchemy.respond_to?(:logout_method)
|
@@ -24,13 +24,13 @@ Rails.application.config.after_initialize do
|
|
24
24
|
match_path: "/languages"
|
25
25
|
),
|
26
26
|
(if defined?(Alchemy::Devise::Engine)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
config.class::MenuItem.new(
|
28
|
+
label: :users,
|
29
|
+
condition: -> { can?(:index, :alchemy_admin_users) },
|
30
|
+
url: -> { Alchemy::Engine.routes.url_helpers.admin_users_path },
|
31
|
+
match_path: "/users"
|
32
|
+
)
|
33
|
+
end),
|
34
34
|
config.class::MenuItem.new(
|
35
35
|
label: :tags,
|
36
36
|
condition: -> { can?(:index, :alchemy_admin_tags) },
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class CreateAlchemyEssenceSpreeProducts < ActiveRecord::Migration[4.2]
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
def change
|
3
|
+
create_table "alchemy_essence_spree_products" do |t|
|
4
|
+
t.integer :spree_product_id
|
5
|
+
end
|
6
|
+
add_index :alchemy_essence_spree_products, :spree_product_id
|
7
|
+
end
|
8
8
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class CreateAlchemyEssenceSpreeVariants < ActiveRecord::Migration[5.2]
|
2
2
|
def change
|
3
3
|
create_table :alchemy_essence_spree_variants do |t|
|
4
|
-
t.references :variant, null: true, foreign_key: {
|
4
|
+
t.references :variant, null: true, foreign_key: {to_table: Spree::Variant.table_name}
|
5
5
|
|
6
6
|
t.timestamps
|
7
7
|
end
|
@@ -15,29 +15,29 @@ module Alchemy
|
|
15
15
|
desc "Installs Alchemy Solidus into your App."
|
16
16
|
|
17
17
|
class_option :skip_alchemy_installer,
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
default: false,
|
19
|
+
type: :boolean,
|
20
|
+
desc:
|
21
|
+
"Set true if you don't want to run the Alchemy installer"
|
22
22
|
class_option :skip_alchemy_devise_installer,
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
default: false,
|
24
|
+
type: :boolean,
|
25
|
+
desc:
|
26
|
+
"Set true if you don't want to run the Alchemy Devise installer. NOTE: Automatically skipped if Alchemy::Devise is not available."
|
27
27
|
class_option :skip_spree_custom_user_generator,
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
default: false,
|
29
|
+
type: :boolean,
|
30
|
+
desc:
|
31
|
+
"Set true if you don't want to run the Solidus custom user generator. NOTE: Automatically skipped if Alchemy::Devise is not available."
|
32
32
|
class_option :skip_alchemy_user_generator,
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
default: false,
|
34
|
+
type: :boolean,
|
35
|
+
desc:
|
36
|
+
"Set true if you don't want to generate an admin user. NOTE: Automatically skipped if Alchemy::Devise is not available."
|
37
37
|
class_option :auto_accept,
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
default: false,
|
39
|
+
type: :boolean,
|
40
|
+
desc: "Set true if run from a automated script (ie. on a CI)"
|
41
41
|
|
42
42
|
source_root File.expand_path("files", __dir__)
|
43
43
|
|
@@ -66,7 +66,7 @@ module Alchemy
|
|
66
66
|
|
67
67
|
def run_spree_custom_user_generator
|
68
68
|
if alchemy_devise_present? &&
|
69
|
-
|
69
|
+
!options[:skip_spree_custom_user_generator]
|
70
70
|
arguments =
|
71
71
|
(
|
72
72
|
if options[:auto_accept]
|
@@ -77,15 +77,15 @@ module Alchemy
|
|
77
77
|
)
|
78
78
|
Spree::CustomUserGenerator.start(arguments)
|
79
79
|
gsub_file "lib/spree/authentication_helpers.rb",
|
80
|
-
|
81
|
-
|
80
|
+
/main_app\./,
|
81
|
+
"Alchemy."
|
82
82
|
rake("db:migrate", abort_on_failure: true)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
def create_admin_user
|
87
87
|
if alchemy_devise_present? && !options[:skip_alchemy_user_generator] &&
|
88
|
-
|
88
|
+
Alchemy::User.count.zero?
|
89
89
|
login = ENV.fetch("ALCHEMY_ADMIN_USER_LOGIN", "admin")
|
90
90
|
email = ENV.fetch("ALCHEMY_ADMIN_USER_EMAIL", "admin@example.com")
|
91
91
|
password = ENV.fetch("ALCHEMY_ADMIN_USER_PASSWORD", "test1234")
|
@@ -123,12 +123,12 @@ module Alchemy
|
|
123
123
|
default: mountpoint
|
124
124
|
)
|
125
125
|
end
|
126
|
-
if File.read(routes_file_path).match SPREE_MOUNT_REGEXP
|
127
|
-
|
126
|
+
sentinel = if File.read(routes_file_path).match SPREE_MOUNT_REGEXP
|
127
|
+
SPREE_MOUNT_REGEXP
|
128
128
|
else
|
129
|
-
|
129
|
+
"Rails.application.routes.draw do\n"
|
130
130
|
end
|
131
|
-
inject_into_file routes_file_path, {
|
131
|
+
inject_into_file routes_file_path, {after: sentinel} do
|
132
132
|
"\n mount Alchemy::Engine, at: '/#{mountpoint.chomp("/")}'\n"
|
133
133
|
end
|
134
134
|
end
|
@@ -136,12 +136,12 @@ module Alchemy
|
|
136
136
|
def set_root_route
|
137
137
|
routes_file_path = Rails.root.join("config", "routes.rb")
|
138
138
|
if options[:auto_accept] ||
|
139
|
-
|
139
|
+
yes?("\nDo you want Alchemy to handle the root route '/'? (y/n)")
|
140
140
|
sentinel = "Rails.application.routes.draw do\n"
|
141
|
-
inject_into_file routes_file_path, {
|
141
|
+
inject_into_file routes_file_path, {after: sentinel} do
|
142
142
|
<<~ROOT_ROUTE
|
143
|
-
|
144
|
-
|
143
|
+
# Let AlchemyCMS handle the root route
|
144
|
+
root to: 'alchemy/pages#index'
|
145
145
|
ROOT_ROUTE
|
146
146
|
end
|
147
147
|
copy_file("db/seeds/alchemy/pages.yml")
|
@@ -151,7 +151,7 @@ module Alchemy
|
|
151
151
|
|
152
152
|
def append_assets
|
153
153
|
append_file "vendor/assets/javascripts/alchemy/admin/all.js",
|
154
|
-
|
154
|
+
"//= require alchemy/solidus/admin.js"
|
155
155
|
end
|
156
156
|
|
157
157
|
private
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alchemy-solidus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas von Deyen
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-08 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: alchemy_cms
|
@@ -243,6 +243,8 @@ files:
|
|
243
243
|
- app/assets/javascripts/alchemy/solidus/admin.js
|
244
244
|
- app/components/alchemy/admin/link_dialog/product_tab.rb
|
245
245
|
- app/components/alchemy/admin/product_select.rb
|
246
|
+
- app/components/alchemy/admin/taxon_select.rb
|
247
|
+
- app/components/alchemy/admin/variant_select.rb
|
246
248
|
- app/components/alchemy/ingredients/spree_product_view.rb
|
247
249
|
- app/components/alchemy/ingredients/spree_taxon_view.rb
|
248
250
|
- app/components/alchemy/ingredients/spree_variant_view.rb
|
@@ -250,11 +252,10 @@ files:
|
|
250
252
|
- app/decorators/models/alchemy/solidus/spree_taxon_decorator.rb
|
251
253
|
- app/decorators/models/alchemy/solidus/spree_variant_decorator.rb
|
252
254
|
- app/javascript/alchemy_solidus.js
|
255
|
+
- app/javascript/alchemy_solidus/components/ajax_config.js
|
253
256
|
- app/javascript/alchemy_solidus/components/product_select.js
|
254
|
-
- app/javascript/alchemy_solidus/
|
255
|
-
- app/javascript/alchemy_solidus/
|
256
|
-
- app/javascript/alchemy_solidus/taxon_select.js
|
257
|
-
- app/javascript/alchemy_solidus/variant_select.js
|
257
|
+
- app/javascript/alchemy_solidus/components/taxon_select.js
|
258
|
+
- app/javascript/alchemy_solidus/components/variant_select.js
|
258
259
|
- app/models/alchemy/ingredients/spree_product.rb
|
259
260
|
- app/models/alchemy/ingredients/spree_taxon.rb
|
260
261
|
- app/models/alchemy/ingredients/spree_variant.rb
|
@@ -309,7 +310,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
309
310
|
- !ruby/object:Gem::Version
|
310
311
|
version: '0'
|
311
312
|
requirements: []
|
312
|
-
rubygems_version: 3.6.
|
313
|
+
rubygems_version: 3.6.5
|
313
314
|
specification_version: 4
|
314
315
|
summary: The World's Most Flexible E-Commerce Platform meets The World's Most Flexible
|
315
316
|
Content Management System!
|
@@ -1,37 +0,0 @@
|
|
1
|
-
import { getSelect2Config } from "alchemy_solidus/select2_config"
|
2
|
-
|
3
|
-
$.fn.alchemyProductSelect = function (options) {
|
4
|
-
const config = getSelect2Config(options)
|
5
|
-
|
6
|
-
function formatResultObject(product) {
|
7
|
-
return {
|
8
|
-
id: product.id,
|
9
|
-
text: product.name,
|
10
|
-
}
|
11
|
-
}
|
12
|
-
|
13
|
-
const select2config = Object.assign(config, {
|
14
|
-
ajax: Object.assign(config.ajax, {
|
15
|
-
data(term, page) {
|
16
|
-
return {
|
17
|
-
q: Object.assign(
|
18
|
-
{
|
19
|
-
name_cont: term,
|
20
|
-
},
|
21
|
-
options.query_params
|
22
|
-
),
|
23
|
-
page: page,
|
24
|
-
}
|
25
|
-
},
|
26
|
-
results(data, page) {
|
27
|
-
return {
|
28
|
-
results: data.products.map(
|
29
|
-
options.formatResultObject || formatResultObject
|
30
|
-
),
|
31
|
-
more: page * data.per_page < data.total_count,
|
32
|
-
}
|
33
|
-
},
|
34
|
-
}),
|
35
|
-
})
|
36
|
-
this.select2(select2config)
|
37
|
-
}
|
@@ -1,24 +0,0 @@
|
|
1
|
-
export function getSelect2Config(options) {
|
2
|
-
const headers = {
|
3
|
-
Authorization: "Bearer " + options.apiToken,
|
4
|
-
}
|
5
|
-
|
6
|
-
return {
|
7
|
-
placeholder: options.placeholder,
|
8
|
-
minimumInputLength: 3,
|
9
|
-
allowClear: true,
|
10
|
-
initSelection:
|
11
|
-
options.initSelection ||
|
12
|
-
function (_$el, callback) {
|
13
|
-
if (options.initialSelection) {
|
14
|
-
callback(options.initialSelection)
|
15
|
-
}
|
16
|
-
},
|
17
|
-
ajax: {
|
18
|
-
url: options.baseUrl,
|
19
|
-
datatype: "json",
|
20
|
-
quietMillis: 300,
|
21
|
-
params: { headers: headers },
|
22
|
-
},
|
23
|
-
}
|
24
|
-
}
|
@@ -1,37 +0,0 @@
|
|
1
|
-
import { getSelect2Config } from "alchemy_solidus/select2_config"
|
2
|
-
|
3
|
-
$.fn.alchemyTaxonSelect = function (options) {
|
4
|
-
const config = getSelect2Config(options)
|
5
|
-
|
6
|
-
this.select2(
|
7
|
-
$.extend(true, config, {
|
8
|
-
ajax: {
|
9
|
-
data(term, page) {
|
10
|
-
return {
|
11
|
-
q: $.extend(
|
12
|
-
{
|
13
|
-
name_cont: term,
|
14
|
-
},
|
15
|
-
options.query_params
|
16
|
-
),
|
17
|
-
page: page,
|
18
|
-
}
|
19
|
-
},
|
20
|
-
results(data, page) {
|
21
|
-
return {
|
22
|
-
results: data.taxons.map(function (taxon) {
|
23
|
-
return {
|
24
|
-
id: taxon.id,
|
25
|
-
text: taxon.pretty_name,
|
26
|
-
}
|
27
|
-
}),
|
28
|
-
more: page * data.per_page < data.total_count,
|
29
|
-
}
|
30
|
-
},
|
31
|
-
},
|
32
|
-
formatSelection(taxon) {
|
33
|
-
return taxon.text || taxon.name
|
34
|
-
},
|
35
|
-
})
|
36
|
-
)
|
37
|
-
}
|
@@ -1,55 +0,0 @@
|
|
1
|
-
import { getSelect2Config } from "alchemy_solidus/select2_config"
|
2
|
-
|
3
|
-
$.fn.alchemyVariantSelect = function (options) {
|
4
|
-
const config = getSelect2Config(options)
|
5
|
-
|
6
|
-
function formatSelection(variant) {
|
7
|
-
return variant.options_text
|
8
|
-
? `${variant.name} - ${variant.options_text}`
|
9
|
-
: variant.name
|
10
|
-
}
|
11
|
-
|
12
|
-
function formatResult(variant, _el, query) {
|
13
|
-
const matchTerm = new RegExp(query.term, "gi")
|
14
|
-
const formatMatch = (match) => `<em>${match}</em>`
|
15
|
-
const name = variant.name.replace(matchTerm, formatMatch)
|
16
|
-
const sku = variant.sku.replace(matchTerm, formatMatch)
|
17
|
-
return `
|
18
|
-
<div class="variant-select-result">
|
19
|
-
<div>
|
20
|
-
<span>${name}</span>
|
21
|
-
</div>
|
22
|
-
<div>
|
23
|
-
<span>${variant.options_text}</span>
|
24
|
-
<span>${sku}</span>
|
25
|
-
</div>
|
26
|
-
</div>
|
27
|
-
`
|
28
|
-
}
|
29
|
-
|
30
|
-
this.select2(
|
31
|
-
$.extend(true, config, {
|
32
|
-
ajax: {
|
33
|
-
data(term, page) {
|
34
|
-
return {
|
35
|
-
q: $.extend(
|
36
|
-
{
|
37
|
-
product_name_or_sku_cont: term,
|
38
|
-
},
|
39
|
-
options.query_params
|
40
|
-
),
|
41
|
-
page: page,
|
42
|
-
}
|
43
|
-
},
|
44
|
-
results(data, page) {
|
45
|
-
return {
|
46
|
-
results: data.variants,
|
47
|
-
more: page * data.per_page < data.total_count,
|
48
|
-
}
|
49
|
-
},
|
50
|
-
},
|
51
|
-
formatSelection,
|
52
|
-
formatResult,
|
53
|
-
})
|
54
|
-
)
|
55
|
-
}
|