spree_mobility 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.hound.yml +21 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +7 -0
  6. data/.travis.yml +45 -0
  7. data/Appraisals +8 -0
  8. data/CONTRIBUTING.md +81 -0
  9. data/Gemfile +8 -0
  10. data/Guardfile +12 -0
  11. data/LICENSE.md +26 -0
  12. data/README.md +92 -0
  13. data/Rakefile +24 -0
  14. data/app/assets/javascripts/spree/backend/spree_mobility.js +2 -0
  15. data/app/assets/javascripts/spree/backend/taxon_tree_menu.js +49 -0
  16. data/app/assets/javascripts/spree/backend/translations.js +50 -0
  17. data/app/controllers/concerns/spree_mobility/controller_mobility_helper.rb +18 -0
  18. data/app/controllers/spree/admin/option_values_controller_decorator.rb +23 -0
  19. data/app/controllers/spree/admin/product_properties_controller_decorator.rb +22 -0
  20. data/app/controllers/spree/admin/shipping_methods_controller_decorator.rb +18 -0
  21. data/app/controllers/spree/admin/translations_controller.rb +53 -0
  22. data/app/controllers/spree/api/base_controller_decorator.rb +5 -0
  23. data/app/controllers/spree/base_controller_decorator.rb +5 -0
  24. data/app/helpers/spree_mobility/locale_helper.rb +11 -0
  25. data/app/models/concerns/spree_mobility/translatable.rb +63 -0
  26. data/app/overrides/spree/admin/option_types/_option_value_fields/add_translation.rb +10 -0
  27. data/app/overrides/spree/admin/option_types/index/add_translation.rb +8 -0
  28. data/app/overrides/spree/admin/product_properties/_product_property_fields/add_translation.rb +10 -0
  29. data/app/overrides/spree/admin/products/index/search_by_name_or_sku.rb +21 -0
  30. data/app/overrides/spree/admin/promotions/index/add_translation_link.rb +8 -0
  31. data/app/overrides/spree/admin/properties/index/add_translation.rb +8 -0
  32. data/app/overrides/spree/admin/shared/_product_tabs/add_translations.rb +10 -0
  33. data/app/overrides/spree/admin/shared/_translations/translation.rb +8 -0
  34. data/app/overrides/spree/admin/shared/sub_menu/_configuration/store_translations.rb +8 -0
  35. data/app/overrides/spree/admin/shipping_methods/index/add_translation.rb +8 -0
  36. data/app/overrides/spree/admin/taxonomies/_list/add_translations.rb +8 -0
  37. data/app/views/spree/admin/translations/_fields.html.erb +12 -0
  38. data/app/views/spree/admin/translations/_form.html.erb +13 -0
  39. data/app/views/spree/admin/translations/_form_fields.html.erb +38 -0
  40. data/app/views/spree/admin/translations/_settings.html.erb +22 -0
  41. data/app/views/spree/admin/translations/option_type.html.erb +9 -0
  42. data/app/views/spree/admin/translations/option_value.html.erb +25 -0
  43. data/app/views/spree/admin/translations/product.html.erb +7 -0
  44. data/app/views/spree/admin/translations/product_property.html.erb +23 -0
  45. data/app/views/spree/admin/translations/promotion.html.erb +9 -0
  46. data/app/views/spree/admin/translations/property.html.erb +9 -0
  47. data/app/views/spree/admin/translations/shipping_method.html.erb +9 -0
  48. data/app/views/spree/admin/translations/store.html.erb +25 -0
  49. data/app/views/spree/admin/translations/taxon.html.erb +25 -0
  50. data/app/views/spree/admin/translations/taxonomy.html.erb +9 -0
  51. data/bin/rails +7 -0
  52. data/config/initializers/enable_extensions.rb +27 -0
  53. data/config/initializers/form_builder_mobility_patch.rb +53 -0
  54. data/config/initializers/mobility.rb +118 -0
  55. data/config/initializers/spree_ransack.rb +31 -0
  56. data/config/locales/be.yml +6 -0
  57. data/config/locales/bg.yml +6 -0
  58. data/config/locales/en.yml +6 -0
  59. data/config/locales/it.yml +6 -0
  60. data/config/locales/ru.yml +6 -0
  61. data/config/locales/zh-TW.yml +6 -0
  62. data/config/routes.rb +7 -0
  63. data/db/migrate/20220411041407_add_translations_to_main_models.rb +83 -0
  64. data/db/migrate/20220412095648_remove_null_constraints_from_spree_tables.rb +13 -0
  65. data/db/migrate/20220413095648_migrate_translation_data.rb +53 -0
  66. data/gemfiles/spree_4_2.gemfile +8 -0
  67. data/gemfiles/spree_master.gemfile +10 -0
  68. data/lib/generators/spree_mobility/install/install_generator.rb +23 -0
  69. data/lib/spree_mobility/configuration.rb +12 -0
  70. data/lib/spree_mobility/core_ext/mobility/backends/active_record/table/mobility_acts_as_paranoid_decorator.rb +31 -0
  71. data/lib/spree_mobility/core_ext/spree/option_type_decorator.rb +11 -0
  72. data/lib/spree_mobility/core_ext/spree/option_value_decorator.rb +30 -0
  73. data/lib/spree_mobility/core_ext/spree/product_decorator.rb +87 -0
  74. data/lib/spree_mobility/core_ext/spree/product_property_decorator.rb +6 -0
  75. data/lib/spree_mobility/core_ext/spree/product_scopes_with_mobility_decorator.rb +16 -0
  76. data/lib/spree_mobility/core_ext/spree/products/find_with_mobility_decorator.rb +12 -0
  77. data/lib/spree_mobility/core_ext/spree/promotion_decorator.rb +11 -0
  78. data/lib/spree_mobility/core_ext/spree/property_decorator.rb +26 -0
  79. data/lib/spree_mobility/core_ext/spree/shipping_method_decorator.rb +10 -0
  80. data/lib/spree_mobility/core_ext/spree/store_decorator.rb +12 -0
  81. data/lib/spree_mobility/core_ext/spree/taxon_decorator.rb +54 -0
  82. data/lib/spree_mobility/core_ext/spree/taxonomy_decorator.rb +29 -0
  83. data/lib/spree_mobility/core_ext/spree/variant_decorator.rb +19 -0
  84. data/lib/spree_mobility/engine.rb +33 -0
  85. data/lib/spree_mobility/fallbacks.rb +45 -0
  86. data/lib/spree_mobility/translation_query.rb +36 -0
  87. data/lib/spree_mobility/version.rb +18 -0
  88. data/lib/spree_mobility.rb +47 -0
  89. data/spec/features/admin/products_spec.rb +15 -0
  90. data/spec/features/admin/translations_spec.rb +259 -0
  91. data/spec/features/translations_spec.rb +35 -0
  92. data/spec/models/product_spec.rb +77 -0
  93. data/spec/models/taxon_spec.rb +16 -0
  94. data/spec/models/translated_models_spec.rb +33 -0
  95. data/spec/models/variant_spec.rb +33 -0
  96. data/spec/spec_helper.rb +10 -0
  97. data/spec/support/i18n.rb +5 -0
  98. data/spec/support/matchers/be_a_thorough_translation_of_matcher.rb +21 -0
  99. data/spec/support/matchers/have_text_like.rb +3 -0
  100. data/spec/support/shared_contexts/translatable_context.rb +63 -0
  101. data/spree_mobility.gemspec +37 -0
  102. metadata +316 -0
@@ -0,0 +1,63 @@
1
+ module SpreeMobility
2
+ module Translatable
3
+ extend ActiveSupport::Concern
4
+
5
+ include Spree::RansackableAttributes
6
+
7
+ included do |klass|
8
+ klass.send :extend, Mobility
9
+ klass.send(:default_scope) { i18n }
10
+ end
11
+
12
+ class_methods do
13
+ def translation_class
14
+ const_get('Translation')
15
+ end
16
+
17
+ def ransack(params = {}, options = {})
18
+ params ||= {}
19
+ names = params.keys
20
+
21
+ # TODO: this should be used together with search param, only fallback if first is empty
22
+ # params[:translations_locale_in] ||= fallback_locales.map(&:to_s)
23
+
24
+ names.each do |n|
25
+ mobility_attributes.each do |t|
26
+ if n.to_s.starts_with? t.to_s
27
+ params[:"translations_#{n}"] = params[n]
28
+ params.delete n
29
+ end
30
+ end
31
+ end
32
+
33
+ super(params, options)
34
+ end
35
+ alias :search :ransack unless respond_to? :search
36
+
37
+ module CopyPreloadedActiveTranslationsToTranslations
38
+ # Although it has :nodoc, preload_associations is a public method of
39
+ # ActiveRecord::Relation and should be relatively safe to use.
40
+ # After the active_translations assoc is preloaded, we copy results over
41
+ # into translations - basically we load translations with results from
42
+ # active_translations.
43
+ def preload_associations(records)
44
+ super.tap do
45
+ records.each do |record|
46
+ # We don't want to overwrite translations if already present
47
+ next if record.association(:translations).target.present?
48
+ record.association(:translations).target =
49
+ record.association(:active_translations).target
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def spree_base_scopes
56
+ # Only preload translations for current locale and its fallbacks
57
+ scope = super.preload(:active_translations)
58
+ scope.singleton_class.prepend CopyPreloadedActiveTranslationsToTranslations
59
+ return scope
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,10 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/option_types/_option_value_fields',
3
+ name: 'option_value_translation',
4
+ insert_bottom: 'td.actions',
5
+ text: <<-HTML
6
+ <% if f.object.persisted? %>
7
+ <%= link_to_with_icon 'translate', nil, spree.admin_translations_path('option_values', f.object.id), title: Spree.t(:'i18n.translations'), class: 'btn btn-sm btn-primary' %>
8
+ <% end %>
9
+ HTML
10
+ )
@@ -0,0 +1,8 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/option_types/index',
3
+ name: 'option_types_index_translation',
4
+ insert_top: 'td.actions',
5
+ text: <<-HTML
6
+ <%= link_to_with_icon 'translate', nil, spree.admin_translations_path('option_types', option_type.id), title: Spree.t(:'i18n.translations'), class: 'btn btn-sm btn-primary' %>
7
+ HTML
8
+ )
@@ -0,0 +1,10 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/product_properties/_product_property_fields',
3
+ name: 'product_property_translation',
4
+ insert_bottom: 'td.actions',
5
+ text: <<-HTML
6
+ <% if f.object.persisted? %>
7
+ <%= link_to_with_icon 'translate', nil, spree.admin_translations_path('product_property', f.object.id), title: Spree.t(:'i18n.translations'), class: 'btn btn-sm btn-primary' %>
8
+ <% end %>
9
+ HTML
10
+ )
@@ -0,0 +1,21 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/products/index',
3
+ name: 'search_by_name_or_sku',
4
+ replace: 'div[data-hook=admin_products_index_search] > div:first-child',
5
+ text: <<-HTML
6
+
7
+ <div class="col-12 col-lg-6">
8
+ <div class="form-group">
9
+ <%= f.label :search_by_name_or_sku, Spree.t(:name_or_sku) %>
10
+ <%= f.text_field :search_by_name_or_sku, size: 15, class: "form-control js-quick-search-target js-filterable" %>
11
+ </div>
12
+ </div>
13
+
14
+ <div class="col-12 col-lg-6">
15
+ <div class="form-group">
16
+ <%= f.label :search_by_name, Spree.t(:product_name) %>
17
+ <%= f.text_field :search_by_name, size: 15, class: "form-control js-filterable" %>
18
+ </div>
19
+ </div>
20
+ HTML
21
+ )
@@ -0,0 +1,8 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/promotions/index',
3
+ name: 'promotions_translation',
4
+ insert_bottom: 'td.actions',
5
+ text: <<-HTML
6
+ <%= link_to_with_icon 'translate', nil, spree.admin_translations_path('promotions', promotion.id), title: Spree.t(:'i18n.translations'), class: 'btn btn-sm btn-primary' %>
7
+ HTML
8
+ )
@@ -0,0 +1,8 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/properties/index',
3
+ name: 'properties_translation',
4
+ insert_bottom: 'td.actions',
5
+ text: <<-HTML
6
+ <%= link_to_with_icon 'translate', nil, spree.admin_translations_path('properties', property.id), title: Spree.t(:'i18n.translations'), class: 'btn btn-sm btn-primary' %>
7
+ HTML
8
+ )
@@ -0,0 +1,10 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/shared/_product_tabs',
3
+ name: 'product_tabs_translation',
4
+ insert_bottom: "[data-hook='admin_product_tabs']",
5
+ text: <<-HTML
6
+ <li>
7
+ <%= link_to_with_icon 'translate', Spree.t(:'i18n.translations'), spree.admin_translations_url('products', @product.slug), class: "\#\{'active' if current == 'Translations'\} nav-link" %>
8
+ </li>
9
+ HTML
10
+ )
@@ -0,0 +1,8 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/shared/_translations',
3
+ name: 'translations_translation',
4
+ insert_bottom: 'script',
5
+ text: <<-HTML
6
+ $.extend(Spree.translations, { translations: "<%= strip_tags(Spree.t(:'i18n.translations')) %>" })
7
+ HTML
8
+ )
@@ -0,0 +1,8 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/shared/sub_menu/_configuration',
3
+ name: 'sub_menu_configuration_translation',
4
+ insert_bottom: "[data-hook='admin_configurations_sidebar_menu']",
5
+ text: <<-HTML
6
+ <%= configurations_sidebar_menu_item Spree.t(:'mobility.store_translations'), spree.admin_translations_path('stores', current_store.id) if can? :manage, Spree::Store %>
7
+ HTML
8
+ )
@@ -0,0 +1,8 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/shipping_methods/index',
3
+ name: 'shipping_methods_translation',
4
+ insert_bottom: 'td.actions',
5
+ text: <<-HTML
6
+ <%= link_to_with_icon 'translate', nil, spree.admin_translations_path('shipping_methods', shipping_method.id), title: Spree.t(:'i18n.translations'), class: 'btn btn-sm btn-primary' %>
7
+ HTML
8
+ )
@@ -0,0 +1,8 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/taxonomies/_list',
3
+ name: 'taxonomies_translation',
4
+ insert_bottom: 'td.actions',
5
+ text: <<-HTML
6
+ <%= link_to_with_icon 'translate', nil, spree.admin_translations_path('taxonomies', taxonomy.id), title: Spree.t(:'i18n.translations'), class: 'btn btn-sm btn-primary' %>
7
+ HTML
8
+ )
@@ -0,0 +1,12 @@
1
+ <div class="panel panel-default fields">
2
+ <div class="panel-heading">
3
+ <%= Spree.t(:'i18n.fields') %>
4
+ </div>
5
+ <div class="list-group" id="attr_list">
6
+ <% @resource.class.mobility_attributes.each_with_index do |attr, i| %>
7
+ <a class="list-group-item <%= 'active' if i.zero? %>" data-attr="<%= attr %>" href="#">
8
+ <%= @resource.class.human_attribute_name(attr) %>
9
+ </a>
10
+ <% end %>
11
+ </div>
12
+ </div>
@@ -0,0 +1,13 @@
1
+ <%= render 'settings' %>
2
+
3
+ <div class="row translations">
4
+ <div class="col-md-4">
5
+ <%= render 'fields' %>
6
+ </div>
7
+ <div class="col-md-8">
8
+ <%= form_for [:admin, @resource] do |f| %>
9
+ <%= render 'form_fields', f: f %>
10
+ <%= render 'spree/admin/shared/edit_resource_links' %>
11
+ <% end %>
12
+ </div>
13
+ </div>
@@ -0,0 +1,38 @@
1
+ <div id="attr_fields">
2
+ <% available_locales.each do |locale| %>
3
+ <%= f.mobility_fields_for locale.to_sym do |g| %>
4
+ <% @resource.class.mobility_attributes.each_with_index do |attr, i| %>
5
+ <div class="panel panel-default <%= attr %> <%= locale %>" style="display:<%= i == 0 ? 'auto' : 'none' %>;">
6
+ <div class="panel-heading">
7
+ <% I18n.with_locale(locale) do %>
8
+ <%= @resource.class.human_attribute_name(attr) %>
9
+
10
+ <div class="pull-right text-muted">
11
+ <small><i><%= Spree.t(:'i18n.this_file_language') %></i></small>
12
+ </div>
13
+ <% end %>
14
+ </div>
15
+
16
+ <div class="panel-body">
17
+ <% field_type = @resource.class.translation_class.columns_hash[attr.to_s].type %>
18
+ <% if @resource.kind_of?(Spree::Product) && attr.to_sym == :description %>
19
+ <%= g.text_area :description, { rows: "30", class: "form-control #{"spree-rte" if Spree::Config[:product_wysiwyg_editor_enabled] }" } %>
20
+ <% elsif @resource.kind_of?(Spree::Taxon) && attr.to_sym == :description %>
21
+ <%= g.text_area :description, { rows: "30", class: "form-control #{"spree-rte" if Spree::Config[:taxon_wysiwyg_editor_enabled] }" } %>
22
+ <% elsif field_type == :text %>
23
+ <%= g.text_area attr, class: 'form-control', rows: 4 %>
24
+ <% else %>
25
+ <%= g.text_field attr, class: 'form-control' %>
26
+ <% end %>
27
+ </div>
28
+ </div>
29
+ <% end %>
30
+ <% end %>
31
+ <% end %>
32
+
33
+ <p class="no-translations" style="display: none">
34
+ <%= Spree.t(:'mobility.no_translations_for_criteria') %>
35
+ </p>
36
+ </div>
37
+
38
+ <hr/>
@@ -0,0 +1,22 @@
1
+ <div class="well well-sm">
2
+ <div class="row no-padding-bottom">
3
+ <div class="col-md-4">
4
+ <div class="form-group no-margin-bottom">
5
+ <label><%= Spree.t(:show) %></label>
6
+ <select class="form-control" name="show-only">
7
+ <option value="all"><%= Spree.t(:all) %></option>
8
+ <option value="incomplete"><%= Spree.t(:'i18n.only_incomplete') %></option>
9
+ <option value="complete"><%= Spree.t(:'i18n.only_complete') %></option>
10
+ </select>
11
+ </div>
12
+ </div>
13
+
14
+ <div class="col-md-8">
15
+ <div class="form-group no-margin-bottom">
16
+ <label><%= Spree.t(:'i18n.select_locale') %></label>
17
+ <%= select_available_locales_fields %>
18
+ <%= hidden_field_tag 'available_locales', available_locales.join(',') %>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </div>
@@ -0,0 +1,9 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::OptionType.model_name.human) %> <span class="green">"<%= @option_type.name %>"</span>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::OptionType.model_name.human), spree.admin_option_types_path, class: 'btn-primary', icon: 'arrow-left' %>
7
+ <% end %>
8
+
9
+ <%= render 'form' %>
@@ -0,0 +1,25 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::OptionValue.model_name.human) %> <span class="green">"<%= @option_value.name %>"</span>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::OptionValue.model_name.human), spree.edit_admin_option_type_path(@option_value.option_type), class: 'btn-primary', icon: 'arrow-left' %>
7
+ <% end %>
8
+
9
+ <%= render 'settings' %>
10
+
11
+ <div class="row translations">
12
+ <div class="col-md-4">
13
+ <%= render 'fields' %>
14
+ </div>
15
+ <div class="col-md-8">
16
+ <%= form_for [:admin, :option_type, @resource] do |f| %>
17
+ <%= render 'form_fields', f: f %>
18
+ <div class="form-actions" data-hook="buttons">
19
+ <%= button Spree.t(:update), 'update' %>
20
+ <span class="or"><%= Spree.t(:or) %></span>
21
+ <%= button_link_to Spree.t(:cancel), spree.edit_admin_option_type_path(@option_value.option_type), icon: 'remove' %>
22
+ </div>
23
+ <% end %>
24
+ </div>
25
+ </div>
@@ -0,0 +1,7 @@
1
+ <%= render 'spree/admin/shared/product_tabs', current: 'Translations' %>
2
+
3
+ <% content_for :page_actions do %>
4
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::Product.model_name.human), spree.admin_products_path, class: 'btn-primary', icon: 'arrow-left' %>
5
+ <% end %>
6
+
7
+ <%= render 'form' %>
@@ -0,0 +1,23 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::ProductProperty.model_name.human) %> <span class="green">"<%= @product_property.property.presentation %>"</span>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::ProductProperty.model_name.human), spree.admin_product_product_properties_path(@product_property.product), class: 'btn-primary', icon: 'icon-arrow-left' %>
7
+ <% end %>
8
+
9
+ <div class="row translations">
10
+ <div class="col-md-4">
11
+ <%= render 'fields' %>
12
+ </div>
13
+ <div class="col-md-8">
14
+ <%= form_for [:admin, @resource.product, @resource], method: :patch do |f| %>
15
+ <%= render 'form_fields', f: f %>
16
+ <div class="form-actions" data-hook="buttons">
17
+ <%= button Spree.t(:update), 'update' %>
18
+ <span class="or"><%= Spree.t(:or) %></span>
19
+ <%= button_link_to Spree.t(:cancel), spree.admin_product_product_properties_path(@product_property.product), icon: 'remove' %>
20
+ </div>
21
+ <% end %>
22
+ </div>
23
+ </div>
@@ -0,0 +1,9 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::Promotion.model_name.human) %>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::Promotion.model_name.human), spree.admin_promotions_path, class: 'btn-primary', icon: 'arrow-left' %>
7
+ <% end %>
8
+
9
+ <%= render 'form' %>
@@ -0,0 +1,9 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::Property.model_name.human) %>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::Property.model_name.human), spree.admin_properties_path, class: 'btn-primary', icon: 'arrow-left' %>
7
+ <% end %>
8
+
9
+ <%= render 'form' %>
@@ -0,0 +1,9 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::ShippingMethod.model_name.human) %>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::ShippingMethod.model_name.human), spree.admin_shipping_methods_path, class: 'btn-primary', :icon => 'arrow-left' %>
7
+ <% end %>
8
+
9
+ <%= render 'form' %>
@@ -0,0 +1,25 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::Store.model_name.human) %>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::Store.model_name.human), spree.admin_stores_path, class: 'btn-primary', icon: 'arrow-left' %>
7
+ <% end %>
8
+
9
+ <%= render 'settings' %>
10
+
11
+ <div class="row translations">
12
+ <div class="col-md-4">
13
+ <%= render 'fields' %>
14
+ </div>
15
+ <div class="col-md-8">
16
+ <%= form_for [:admin, @store] do |f| %>
17
+ <%= render 'form_fields', f: f %>
18
+ <div class="form-actions" data-hook="buttons">
19
+ <%= button Spree.t(:update), 'update' %>
20
+ <span class="or"><%= Spree.t(:or) %></span>
21
+ <%= button_link_to Spree.t(:cancel), spree.edit_admin_store_url(@store), icon: 'remove' %>
22
+ </div>
23
+ <% end %>
24
+ </div>
25
+ </div>
@@ -0,0 +1,25 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::Taxon.model_name.human) %>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::Taxonomy.model_name.human), spree.admin_taxonomies_path, class: 'btn-primary', icon: 'arrow-left' %>
7
+ <% end %>
8
+
9
+ <%= render 'settings' %>
10
+
11
+ <div class="row translations">
12
+ <div class="col-md-4">
13
+ <%= render 'fields' %>
14
+ </div>
15
+ <div class="col-md-8">
16
+ <%= form_for [:admin, @resource.taxonomy, @resource], url: spree.admin_taxonomy_taxon_path(@taxon.taxonomy, @taxon.id) do |f| %>
17
+ <%= render 'form_fields', f: f %>
18
+ <div class="form-actions" data-hook="buttons">
19
+ <%= button Spree.t(:update), 'update' %>
20
+ <span class="or"><%= Spree.t(:or) %></span>
21
+ <%= button_link_to Spree.t(:cancel), spree.edit_admin_taxonomy_url(@taxon.taxonomy), icon: 'remove' %>
22
+ </div>
23
+ <% end %>
24
+ </div>
25
+ </div>
@@ -0,0 +1,9 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::Taxonomy.model_name.human) %>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:back_to_resource_list, resource: Spree::Taxonomy.model_name.human), spree.admin_taxonomies_path, class: 'btn-primary', icon: 'arrow-left' %>
7
+ <% end %>
8
+
9
+ <%= render 'form' %>
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_mobility/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,27 @@
1
+ require 'mobility'
2
+ require 'mobility/backends/active_record/table'
3
+
4
+ Dir[Rails.root.join('lib', 'spree_mobility', 'core_ext', '**', '*.rb')].each { |f| require f }
5
+
6
+ # Extend library classes
7
+ SpreeMobility.prepend_once(::Mobility::Backends::ActiveRecord::Table.singleton_class,
8
+ SpreeMobility::CoreExt::Mobility::Backends::ActiveRecord::Table::MobilityActsAsParanoidDecorator)
9
+
10
+ Rails.application.config.to_prepare do
11
+ # Extend reloadable classes
12
+ SpreeMobility.prepend_once(::Spree::OptionType, SpreeMobility::CoreExt::Spree::OptionTypeDecorator)
13
+ SpreeMobility.prepend_once(::Spree::OptionValue, SpreeMobility::CoreExt::Spree::OptionValueDecorator)
14
+ SpreeMobility.prepend_once(::Spree::Product, SpreeMobility::CoreExt::Spree::ProductDecorator)
15
+ SpreeMobility.prepend_once(::Spree::Product.singleton_class, SpreeMobility::CoreExt::Spree::ProductDecorator::ClassMethods)
16
+ SpreeMobility.prepend_once(::Spree::Product.singleton_class, SpreeMobility::CoreExt::Spree::ProductScopesWithMobilityDecorator)
17
+ SpreeMobility.prepend_once(::Spree::ProductProperty, SpreeMobility::CoreExt::Spree::ProductPropertyDecorator)
18
+ SpreeMobility.prepend_once(::Spree::Promotion, SpreeMobility::CoreExt::Spree::PromotionDecorator)
19
+ SpreeMobility.prepend_once(::Spree::Property, SpreeMobility::CoreExt::Spree::PropertyDecorator)
20
+ SpreeMobility.prepend_once(::Spree::ShippingMethod, SpreeMobility::CoreExt::Spree::ShippingMethodDecorator)
21
+ SpreeMobility.prepend_once(::Spree::Store, SpreeMobility::CoreExt::Spree::StoreDecorator)
22
+ SpreeMobility.prepend_once(::Spree::Taxon, SpreeMobility::CoreExt::Spree::TaxonDecorator)
23
+ SpreeMobility.prepend_once(::Spree::Taxonomy, SpreeMobility::CoreExt::Spree::TaxonomyDecorator)
24
+ SpreeMobility.prepend_once(::Spree::Variant.singleton_class, SpreeMobility::CoreExt::Spree::VariantDecorator::ClassMethods)
25
+ SpreeMobility.prepend_once(::Spree::Products::Find, SpreeMobility::CoreExt::Spree::Products::FindWithMobilityDecorator)
26
+ end
27
+
@@ -0,0 +1,53 @@
1
+ module ActionView
2
+ module Helpers
3
+ class FormBuilder
4
+ #
5
+ # Helper that renders mobility_translations fields
6
+ # on a per-locale basis, so you can use them separately
7
+ # in the same form and still saving them all at once
8
+ # in the same request.
9
+ #
10
+ # Use it like this:
11
+ #
12
+ # <h1>Editing post</h1>
13
+ #
14
+ # <% form_for(@post) do |f| %>
15
+ # <%= f.error_messages %>
16
+ #
17
+ # <h2>English (default locale)</h2>
18
+ # <p><%= f.text_field :title %></p>
19
+ # <p><%= f.text_field :teaser %></p>
20
+ # <p><%= f.text_field :body %></p>
21
+ #
22
+ # <hr/>
23
+ #
24
+ # <h2>Spanish translation</h2>
25
+ # <% f.mobility_fields_for :es do |g| %>
26
+ # <p><%= g.text_field :title %></p>
27
+ # <p><%= g.text_field :teaser %></p>
28
+ # <p><%= g.text_field :body %></p>
29
+ # <% end %>
30
+ #
31
+ # <hr/>
32
+ #
33
+ # <h2>French translation</h2>
34
+ # <% f.mobility_fields_for :fr do |g| %>
35
+ # <p><%= g.text_field :title %></p>
36
+ # <p><%= g.text_field :teaser %></p>
37
+ # <p><%= g.text_field :body %></p>
38
+ # <% end %>
39
+ #
40
+ # <% end %>
41
+ #
42
+ def mobility_fields_for(locale, *args, &proc)
43
+ raise ArgumentError, "Missing block" unless block_given?
44
+ @index = @index ? @index + 1 : 1
45
+ object_name = "#{@object_name}[translations_attributes][#{@index}]"
46
+ object = @object.translations.find_by(locale: locale)
47
+ @template.concat @template.hidden_field_tag("#{object_name}[id]", object ? object.id : "")
48
+ @template.concat @template.hidden_field_tag("#{object_name}[locale]", locale)
49
+ @template.fields_for(object_name, object, *args, &proc)
50
+ end
51
+ end
52
+ end
53
+ end