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.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/alchemy/admin/link_dialog/product_tab.rb +2 -1
  3. data/app/components/alchemy/admin/product_select.rb +14 -4
  4. data/app/components/alchemy/admin/taxon_select.rb +46 -0
  5. data/app/components/alchemy/admin/variant_select.rb +48 -0
  6. data/app/javascript/alchemy_solidus/components/ajax_config.js +10 -0
  7. data/app/javascript/alchemy_solidus/components/product_select.js +56 -27
  8. data/app/javascript/alchemy_solidus/components/taxon_select.js +48 -0
  9. data/app/javascript/alchemy_solidus/components/variant_select.js +79 -0
  10. data/app/javascript/alchemy_solidus.js +2 -0
  11. data/app/views/alchemy/ingredients/_spree_product_editor.html.erb +10 -21
  12. data/app/views/alchemy/ingredients/_spree_taxon_editor.html.erb +10 -21
  13. data/app/views/alchemy/ingredients/_spree_variant_editor.html.erb +10 -22
  14. data/config/initializers/alchemy.rb +20 -20
  15. data/config/initializers/spree.rb +7 -7
  16. data/db/migrate/20120229160509_create_alchemy_essence_spree_products.rb +6 -6
  17. data/db/migrate/20191107135822_create_alchemy_essence_spree_variants.rb +1 -1
  18. data/lib/alchemy/solidus/alchemy_user_extension.rb +1 -1
  19. data/lib/alchemy/solidus/spree_admin_unauthorized_redirect.rb +1 -1
  20. data/lib/alchemy/solidus/spree_user_extension.rb +1 -1
  21. data/lib/alchemy/solidus/version.rb +1 -1
  22. data/lib/generators/alchemy/solidus/install/install_generator.rb +32 -32
  23. metadata +8 -7
  24. data/app/javascript/alchemy_solidus/product_select.js +0 -37
  25. data/app/javascript/alchemy_solidus/select2_config.js +0 -24
  26. data/app/javascript/alchemy_solidus/taxon_select.js +0 -37
  27. 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: 286c4a4ae1a6aba7c83ecc17b9f51e06b2e4b3cf7504382970edaed1c4de9ef1
4
- data.tar.gz: fd623314a68027a9a1cd6bcd49067e0891a6342364f140668217f2c3fa339d7c
3
+ metadata.gz: 15dc076bf68bd7b1c707371eb37043cce0118953337e4cb83a4d3b618986c96f
4
+ data.tar.gz: b4d750ba90f8e34ca84116c92fe644a286f2d7dbb3ce27e856ecef9b292e3f0d
5
5
  SHA512:
6
- metadata.gz: 541d7bda1ff72e631923ab176dcd868c3f5bb16716a6e0eb0592a0749a9fef22f08f043c2b8393e9ce0a6e82ac2fcf919fb9fc5de621ddc452146e22d8045060
7
- data.tar.gz: 3d260407d78557bda063934ac4105ff8f7357a40f0a9b25313608a8a5f256cc7eb2a739eb3775ec924cbd0c3dc9e7765da950936e2fba57ccda68fc7af1272d4
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
- name: product.name,
39
- slug: product.slug
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
@@ -0,0 +1,10 @@
1
+ export default function ajaxConfig(ajaxConfig, apiKey) {
2
+ return {
3
+ ...ajaxConfig,
4
+ params: {
5
+ headers: {
6
+ Authorization: `Bearer ${apiKey}`,
7
+ },
8
+ },
9
+ }
10
+ }
@@ -1,42 +1,71 @@
1
- import "alchemy_solidus/product_select"
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
- get url() {
17
- return this.getAttribute("url")
4
+ export default class ProductSelect extends RemoteSelect {
5
+ get ajaxConfig() {
6
+ return ajaxConfig(super.ajaxConfig, this.apiKey)
18
7
  }
19
8
 
20
- get apiToken() {
9
+ get apiKey() {
21
10
  return this.getAttribute("api-key")
22
11
  }
23
12
 
24
- _initSelection(_$el, callback) {
25
- const selection = this.getAttribute("selection")
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
- _formatResult(product) {
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
- id: `${Spree.mountedAt()}products/${product.slug}`,
33
- text: product.name,
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
- _searchQuery(value) {
38
- const slug = value.replace(`${Spree.mountedAt()}products/`, "")
39
- return `q[slug_eq]=${slug}`
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)
@@ -1 +1,3 @@
1
1
  import "alchemy_solidus/components/product_select"
2
+ import "alchemy_solidus/components/taxon_select"
3
+ import "alchemy_solidus/components/variant_select"
@@ -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
- <%= f.text_field :product_id,
7
- value: spree_product_editor.product&.id,
8
- id: spree_product_editor.form_field_id(:product_id),
9
- class: 'alchemy_selectbox full_width' %>
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
- <%= f.text_field :taxon_id,
7
- value: spree_taxon_editor.taxon&.id,
8
- id: spree_taxon_editor.form_field_id(:taxon_id),
9
- class: 'alchemy_selectbox full_width' %>
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
- <%= f.text_field :variant_id,
7
- value: spree_variant_editor.variant&.id,
8
- id: spree_variant_editor.form_field_id(:variant_id),
9
- class: 'alchemy_selectbox full_width' %>
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: 'spree',
3
- name: 'solidus',
2
+ engine_name: "spree",
3
+ name: "solidus",
4
4
  navigation: {
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 },
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: '/spree/admin/orders',
13
- action: 'index',
14
- name: 'Orders'
12
+ controller: "/spree/admin/orders",
13
+ action: "index",
14
+ name: "Orders"
15
15
  },
16
16
  {
17
- controller: '/spree/admin/products',
18
- action: 'index',
19
- name: 'Products'
17
+ controller: "/spree/admin/products",
18
+ action: "index",
19
+ name: "Products"
20
20
  },
21
21
  {
22
- controller: '/spree/admin/stock_items',
23
- action: 'index',
24
- name: 'Stock'
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: '/spree/admin/users',
34
- action: 'index',
35
- name: 'Users'
33
+ controller: "/spree/admin/users",
34
+ action: "index",
35
+ name: "Users"
36
36
  }
37
37
  )
38
- Alchemy.user_class_name = 'Spree::User'
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
- 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),
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
- 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
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: { to_table: Spree::Variant.table_name }
4
+ t.references :variant, null: true, foreign_key: {to_table: Spree::Variant.table_name}
5
5
 
6
6
  t.timestamps
7
7
  end
@@ -7,7 +7,7 @@ module Alchemy
7
7
 
8
8
  def spree_roles
9
9
  if admin?
10
- ::Spree::Role.where(name: 'admin')
10
+ ::Spree::Role.where(name: "admin")
11
11
  else
12
12
  ::Spree::Role.none
13
13
  end
@@ -1,6 +1,6 @@
1
1
  Spree::Admin::BaseController.unauthorized_redirect = -> do
2
2
  if spree_current_user
3
- flash[:error] = I18n.t('spree.authorization_failure')
3
+ flash[:error] = I18n.t("spree.authorization_failure")
4
4
  redirect_to spree.root_path
5
5
  else
6
6
  store_location
@@ -11,7 +11,7 @@ module Alchemy
11
11
 
12
12
  def alchemy_roles
13
13
  if has_spree_role?(:admin)
14
- %w(admin)
14
+ %w[admin]
15
15
  else
16
16
  []
17
17
  end
@@ -1,5 +1,5 @@
1
1
  module Alchemy
2
2
  module Solidus
3
- VERSION = "7.5.1"
3
+ VERSION = "7.6.0"
4
4
  end
5
5
  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
- default: false,
19
- type: :boolean,
20
- desc:
21
- "Set true if you don't want to run the Alchemy installer"
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
- 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."
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
- 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."
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
- 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."
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
- default: false,
39
- type: :boolean,
40
- desc: "Set true if run from a automated script (ie. on a CI)"
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
- !options[:skip_spree_custom_user_generator]
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
- /main_app\./,
81
- "Alchemy."
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
- Alchemy::User.count.zero?
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
- sentinel = SPREE_MOUNT_REGEXP
126
+ sentinel = if File.read(routes_file_path).match SPREE_MOUNT_REGEXP
127
+ SPREE_MOUNT_REGEXP
128
128
  else
129
- sentinel = "Rails.application.routes.draw do\n"
129
+ "Rails.application.routes.draw do\n"
130
130
  end
131
- inject_into_file routes_file_path, { after: sentinel } do
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
- yes?("\nDo you want Alchemy to handle the root route '/'? (y/n)")
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, { after: sentinel } do
141
+ inject_into_file routes_file_path, {after: sentinel} do
142
142
  <<~ROOT_ROUTE
143
- \ # Let AlchemyCMS handle the root route
144
- \ root to: 'alchemy/pages#index'
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
- "//= require alchemy/solidus/admin.js"
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.5.1
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-02-11 00:00:00.000000000 Z
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/product_select.js
255
- - app/javascript/alchemy_solidus/select2_config.js
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.3
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
- }