solidus_reviews 1.0.0 → 1.1.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 +5 -5
- data/.rubocop.yml +322 -0
- data/.travis.yml +27 -14
- data/Gemfile +23 -8
- data/LICENSE.md +2 -2
- data/README.md +9 -11
- data/Rakefile +2 -0
- data/app/controllers/spree/admin/feedback_reviews_controller.rb +3 -1
- data/app/controllers/spree/admin/review_settings_controller.rb +3 -1
- data/app/controllers/spree/admin/reviews_controller.rb +9 -6
- data/app/controllers/spree/feedback_reviews_controller.rb +25 -19
- data/app/controllers/spree/products_controller_decorator.rb +2 -0
- data/app/controllers/spree/reviews_controller.rb +11 -7
- data/app/helpers/spree/api/api_helpers_decorator.rb +12 -0
- data/app/helpers/spree/reviews_helper.rb +15 -5
- data/app/models/spree/feedback_review.rb +5 -4
- data/app/models/spree/product_decorator.rb +5 -4
- data/app/models/spree/review.rb +28 -10
- data/app/models/spree/reviews_ability.rb +17 -3
- data/app/models/spree/reviews_configuration.rb +16 -8
- data/app/models/spree/user_decorator.rb +3 -0
- data/app/overrides/add_reviews_after_product_properties.rb +7 -5
- data/app/overrides/add_reviews_tab_to_admin.rb +12 -4
- data/app/overrides/add_reviews_to_admin_configuration_sidebar.rb +13 -5
- data/app/views/spree/admin/feedback_reviews/index.html.erb +9 -9
- data/app/views/spree/admin/review_settings/edit.html.erb +64 -35
- data/app/views/spree/admin/reviews/_form.html.erb +26 -5
- data/app/views/spree/admin/reviews/edit.html.erb +2 -2
- data/app/views/spree/admin/reviews/index.html.erb +100 -88
- data/app/views/spree/api/reviews/_review.json.jbuilder +8 -0
- data/app/views/spree/api/reviews/index.json.jbuilder +6 -0
- data/app/views/spree/api/reviews/show.json.jbuilder +3 -0
- data/app/views/spree/feedback_reviews/_form.html.erb +5 -5
- data/app/views/spree/feedback_reviews/_summary.html.erb +3 -3
- data/app/views/spree/feedback_reviews/create.js.erb +2 -2
- data/app/views/spree/reviews/_form.html.erb +15 -10
- data/app/views/spree/reviews/new.html.erb +2 -2
- data/app/views/spree/shared/_rating.html.erb +3 -3
- data/app/views/spree/shared/_review.html.erb +29 -19
- data/app/views/spree/shared/_review_summary.html.erb +3 -3
- data/app/views/spree/shared/_reviews.html.erb +6 -6
- data/app/views/spree/shared/_shortrating.html.erb +2 -2
- data/bin/rails +4 -2
- data/config/initializers/constants.rb +2 -0
- data/config/initializers/load_preferences.rb +2 -0
- data/config/locales/de-CH.yml +14 -1
- data/config/locales/de.yml +14 -1
- data/config/locales/en-GB.yml +14 -2
- data/config/locales/en.yml +14 -1
- data/config/locales/es.yml +14 -2
- data/config/locales/fr.yml +14 -2
- data/config/locales/it.yml +79 -0
- data/config/locales/pl.yml +14 -2
- data/config/locales/pt-BR.yml +14 -2
- data/config/locales/pt.yml +14 -2
- data/config/locales/ro.yml +15 -3
- data/config/locales/ru.yml +14 -2
- data/config/locales/sv.yml +14 -1
- data/config/locales/tr.yml +14 -2
- data/config/locales/uk.yml +14 -1
- data/config/locales/zh-CN.yml +14 -1
- data/config/locales/zh-TW.yml +14 -1
- data/config/routes.rb +18 -1
- data/db/migrate/20081020220724_create_reviews.rb +4 -2
- data/db/migrate/20101222083309_create_feedback_reviews.rb +5 -3
- data/db/migrate/20110406083603_add_rating_to_products.rb +7 -5
- data/db/migrate/20110606150524_add_user_to_reviews.rb +4 -2
- data/db/migrate/20110806093221_add_ip_address_to_reviews.rb +3 -1
- data/db/migrate/20120110172331_namespace_tables.rb +3 -1
- data/db/migrate/20120123141326_recalculate_ratings.rb +6 -5
- data/db/migrate/20120712182514_add_locale_to_reviews.rb +4 -2
- data/db/migrate/20120712182627_add_locale_to_feedback_reviews.rb +4 -2
- data/db/migrate/20140703200946_add_show_identifier_to_reviews.rb +3 -1
- data/db/migrate/20190613165528_add_verified_purchaser_to_reviews.rb +5 -0
- data/lib/controllers/spree/api/reviews_controller.rb +111 -0
- data/lib/generators/solidus_reviews/install/install_generator.rb +5 -4
- data/lib/solidus_reviews.rb +3 -1
- data/lib/solidus_reviews/factories.rb +3 -1
- data/lib/solidus_reviews/factories/feedback_review_factory.rb +6 -5
- data/lib/solidus_reviews/factories/review_factory.rb +19 -9
- data/lib/spree_reviews/engine.rb +7 -0
- data/solidus_reviews.gemspec +20 -18
- data/spec/controllers/admin/feedback_reviews_controller_spec.rb +9 -7
- data/spec/controllers/admin/review_settings_controller_spec.rb +18 -16
- data/spec/controllers/admin/reviews_controller_spec.rb +18 -16
- data/spec/controllers/feedback_reviews_controller_spec.rb +29 -25
- data/spec/controllers/products_controller_spec.rb +4 -2
- data/spec/controllers/reviews_controller_spec.rb +67 -40
- data/spec/controllers/spree/api/reviews_controller_spec.rb +233 -0
- data/spec/features/admin_spec.rb +3 -0
- data/spec/features/reviews_spec.rb +27 -11
- data/spec/helpers/review_helper_spec.rb +3 -2
- data/spec/models/feedback_review_spec.rb +19 -17
- data/spec/models/product_spec.rb +41 -19
- data/spec/models/review_spec.rb +100 -42
- data/spec/models/reviews_ability_spec.rb +10 -8
- data/spec/models/reviews_configuration_spec.rb +28 -19
- data/spec/spec_helper.rb +21 -35
- data/vendor/assets/javascripts/jquery.rating.js +389 -376
- metadata +108 -59
data/Rakefile
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Spree::Admin::FeedbackReviewsController < Spree::Admin::ResourceController
|
2
4
|
belongs_to 'spree/review'
|
3
5
|
def index
|
4
6
|
@collection = parent.feedback_reviews
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Spree::Admin::ReviewSettingsController < Spree::Admin::BaseController
|
2
|
-
|
4
|
+
before_action :process_unset_checkboxes, only: [:update]
|
3
5
|
|
4
6
|
def update
|
5
7
|
Spree::Reviews::Config.set(params[:preferences])
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Spree::Admin::ReviewsController < Spree::Admin::ResourceController
|
2
4
|
helper Spree::ReviewsHelper
|
3
5
|
|
@@ -6,20 +8,21 @@ class Spree::Admin::ReviewsController < Spree::Admin::ResourceController
|
|
6
8
|
end
|
7
9
|
|
8
10
|
def approve
|
9
|
-
|
11
|
+
review = Spree::Review.find(params[:id])
|
10
12
|
|
11
|
-
if
|
12
|
-
|
13
|
+
if review.update_attribute(:approved, true)
|
14
|
+
flash[:success] = I18n.t('spree.info_approve_review')
|
13
15
|
else
|
14
|
-
|
16
|
+
flash[:error] = I18n.t('spree.error_approve_review')
|
15
17
|
end
|
18
|
+
|
16
19
|
redirect_to admin_reviews_path
|
17
20
|
end
|
18
21
|
|
19
22
|
def edit
|
20
23
|
if @review.product.nil?
|
21
|
-
flash[:error] =
|
22
|
-
redirect_to admin_reviews_path
|
24
|
+
flash[:error] = I18n.t('spree.error_no_product')
|
25
|
+
redirect_to admin_reviews_path
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Spree::FeedbackReviewsController < Spree::StoreController
|
2
4
|
helper Spree::BaseHelper
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
+
before_action :sanitize_rating, only: [:create]
|
7
|
+
before_action :load_review, only: [:create]
|
6
8
|
|
7
9
|
def create
|
8
|
-
|
9
10
|
if @review.present?
|
10
11
|
@feedback_review = @review.feedback_reviews.new(feedback_review_params)
|
11
12
|
@feedback_review.user = spree_current_user
|
@@ -15,27 +16,32 @@ class Spree::FeedbackReviewsController < Spree::StoreController
|
|
15
16
|
end
|
16
17
|
|
17
18
|
respond_to do |format|
|
18
|
-
format.html {
|
19
|
-
|
19
|
+
format.html {
|
20
|
+
if SolidusSupport.solidus_gem_version < Gem::Version.new('2.0')
|
21
|
+
redirect_to(:back)
|
22
|
+
else
|
23
|
+
redirect_back(fallback_location: root_path)
|
24
|
+
end
|
25
|
+
}
|
26
|
+
format.js { render action: :create }
|
20
27
|
end
|
21
|
-
|
22
28
|
end
|
23
29
|
|
24
30
|
protected
|
25
|
-
def load_review
|
26
|
-
@review ||= Spree::Review.find_by_id!(params[:review_id])
|
27
|
-
end
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
+
def load_review
|
33
|
+
@review ||= Spree::Review.find_by_id!(params[:review_id])
|
34
|
+
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def permitted_feedback_review_attributes
|
37
|
+
[:rating, :comment]
|
38
|
+
end
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
40
|
+
def feedback_review_params
|
41
|
+
params.require(:feedback_review).permit(permitted_feedback_review_attributes)
|
42
|
+
end
|
41
43
|
|
44
|
+
def sanitize_rating
|
45
|
+
params[:feedback_review][:rating].to_s.sub!(/\s*[^0-9]*\z/, '') unless params[:feedback_review] && params[:feedback_review][:rating].blank?
|
46
|
+
end
|
47
|
+
end
|
@@ -1,30 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Spree::ReviewsController < Spree::StoreController
|
2
4
|
helper Spree::BaseHelper
|
3
|
-
|
4
|
-
rescue_from ActiveRecord::RecordNotFound, :with => :render_404
|
5
|
+
before_action :load_product, only: [:index, :new, :create]
|
5
6
|
|
6
7
|
def index
|
7
8
|
@approved_reviews = Spree::Review.approved.where(product: @product)
|
8
9
|
end
|
9
10
|
|
10
11
|
def new
|
11
|
-
@review = Spree::Review.new(:
|
12
|
+
@review = Spree::Review.new(product: @product)
|
12
13
|
authorize! :create, @review
|
13
14
|
end
|
14
15
|
|
15
16
|
# save if all ok
|
16
17
|
def create
|
17
|
-
params[:review][:rating].sub!(/\s*[^0-9]*\z/,'') unless params[:review][:rating].blank?
|
18
|
+
params[:review][:rating].sub!(/\s*[^0-9]*\z/, '') unless params[:review][:rating].blank?
|
18
19
|
|
19
20
|
@review = Spree::Review.new(review_params)
|
20
21
|
@review.product = @product
|
21
22
|
@review.user = spree_current_user if spree_user_signed_in?
|
22
23
|
@review.ip_address = request.remote_ip
|
23
24
|
@review.locale = I18n.locale.to_s if Spree::Reviews::Config[:track_locale]
|
25
|
+
# Handle images
|
26
|
+
params[:review][:images]&.each do |image|
|
27
|
+
@review.images.new(attachment: image)
|
28
|
+
end
|
24
29
|
|
25
30
|
authorize! :create, @review
|
26
31
|
if @review.save
|
27
|
-
flash[:notice] =
|
32
|
+
flash[:notice] = I18n.t('spree.review_successfully_submitted')
|
28
33
|
redirect_to spree.product_path(@product)
|
29
34
|
else
|
30
35
|
render :new
|
@@ -38,11 +43,10 @@ class Spree::ReviewsController < Spree::StoreController
|
|
38
43
|
end
|
39
44
|
|
40
45
|
def permitted_review_attributes
|
41
|
-
[:rating, :title, :review, :name, :show_identifier]
|
46
|
+
[:rating, :title, :review, :name, :show_identifier, :images]
|
42
47
|
end
|
43
48
|
|
44
49
|
def review_params
|
45
50
|
params.require(:review).permit(permitted_review_attributes)
|
46
51
|
end
|
47
|
-
|
48
52
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Spree::Api::ApiHelpers.module_eval do
|
4
|
+
@@review_attributes = [
|
5
|
+
:id, :product_id, :name, :location, :rating, :title, :review, :approved,
|
6
|
+
:created_at, :updated_at, :user_id, :ip_address, :locale, :show_identifier
|
7
|
+
]
|
8
|
+
|
9
|
+
def review_attributes
|
10
|
+
@@review_attributes
|
11
|
+
end
|
12
|
+
end
|
@@ -1,17 +1,27 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Spree::ReviewsHelper
|
3
4
|
def star(the_class)
|
4
|
-
content_tag(:span, " ✮ ".html_safe, :
|
5
|
+
content_tag(:span, " ✮ ".html_safe, class: the_class)
|
5
6
|
end
|
6
7
|
|
7
8
|
def mk_stars(m)
|
8
|
-
(1..5).collect {|n| n <= m ? star("lit") : star("unlit") }.join
|
9
|
+
(1..5).collect { |n| n <= m ? star("lit") : star("unlit") }.join
|
9
10
|
end
|
10
11
|
|
11
12
|
def txt_stars(n, show_out_of = true)
|
12
|
-
res =
|
13
|
-
res += " #{
|
13
|
+
res = I18n.t('spree.star', count: n)
|
14
|
+
res += " #{I18n.t('spree.out_of_5')}" if show_out_of
|
14
15
|
res
|
15
16
|
end
|
16
17
|
|
18
|
+
def display_verified_purchaser?(review)
|
19
|
+
Spree::Reviews::Config[:show_verified_purchaser] && review.user &&
|
20
|
+
Spree::LineItem.joins(:order, :variant)
|
21
|
+
.where.not(spree_orders: { completed_at: nil })
|
22
|
+
.find_by(
|
23
|
+
spree_variants: { product_id: review.product_id },
|
24
|
+
spree_orders: { user_id: review.user_id }
|
25
|
+
).present?
|
26
|
+
end
|
17
27
|
end
|
@@ -1,17 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Spree::FeedbackReview < ActiveRecord::Base
|
2
|
-
belongs_to :user, :
|
4
|
+
belongs_to :user, class_name: Spree.user_class.to_s
|
3
5
|
|
4
6
|
belongs_to :review, dependent: :destroy
|
5
7
|
validates :review, presence: true
|
6
8
|
|
7
9
|
validates :rating, numericality: { only_integer: true,
|
8
|
-
greater_than_or_equal_to: 1,
|
10
|
+
greater_than_or_equal_to: 1,
|
9
11
|
less_than_or_equal_to: 5,
|
10
|
-
message:
|
12
|
+
message: :you_must_enter_value_for_rating }
|
11
13
|
|
12
14
|
scope :most_recent_first, -> { order("spree_feedback_reviews.created_at DESC") }
|
13
15
|
default_scope { most_recent_first }
|
14
16
|
|
15
17
|
scope :localized, lambda { |lc| where('spree_feedback_reviews.locale = ?', lc) }
|
16
|
-
|
17
18
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Add access to reviews/ratings to the product model
|
2
4
|
Spree::Product.class_eval do
|
3
5
|
has_many :reviews
|
@@ -7,15 +9,14 @@ Spree::Product.class_eval do
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def recalculate_rating
|
10
|
-
reviews_count =
|
12
|
+
reviews_count = reviews.reload.default_approval_filter.count
|
11
13
|
|
12
14
|
self.reviews_count = reviews_count
|
13
15
|
if reviews_count > 0
|
14
|
-
self.avg_rating =
|
16
|
+
self.avg_rating = '%.1f' % (reviews.default_approval_filter.sum(:rating).to_f / reviews_count)
|
15
17
|
else
|
16
18
|
self.avg_rating = 0
|
17
19
|
end
|
18
|
-
|
20
|
+
save
|
19
21
|
end
|
20
|
-
|
21
22
|
end
|
data/app/models/spree/review.rb
CHANGED
@@ -1,22 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Spree::Review < ActiveRecord::Base
|
2
4
|
belongs_to :product, touch: true
|
3
|
-
belongs_to :user, :
|
5
|
+
belongs_to :user, class_name: Spree.user_class.to_s
|
4
6
|
has_many :feedback_reviews
|
7
|
+
has_many :images, -> { order(:position) }, as: :viewable,
|
8
|
+
dependent: :destroy, class_name: "Spree::Image"
|
5
9
|
|
6
|
-
|
10
|
+
before_create :verify_purchaser
|
11
|
+
after_save :recalculate_product_rating, if: :approved?
|
7
12
|
after_destroy :recalculate_product_rating
|
8
13
|
|
9
|
-
validates :name, presence: true
|
10
|
-
validates :review, presence: true
|
11
|
-
|
12
14
|
validates :rating, numericality: { only_integer: true,
|
13
|
-
greater_than_or_equal_to: 1,
|
15
|
+
greater_than_or_equal_to: 1,
|
14
16
|
less_than_or_equal_to: 5,
|
15
|
-
message:
|
16
|
-
|
17
|
+
message: :you_must_enter_value_for_rating }
|
17
18
|
|
18
19
|
default_scope { order("spree_reviews.created_at DESC") }
|
19
|
-
|
20
|
+
|
20
21
|
scope :localized, ->(lc) { where('spree_reviews.locale = ?', lc) }
|
21
22
|
scope :most_recent_first, -> { order('spree_reviews.created_at DESC') }
|
22
23
|
scope :oldest_first, -> { reorder('spree_reviews.created_at ASC') }
|
@@ -31,6 +32,23 @@ class Spree::Review < ActiveRecord::Base
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def recalculate_product_rating
|
34
|
-
|
35
|
+
product.recalculate_rating if product.present?
|
36
|
+
end
|
37
|
+
|
38
|
+
def email
|
39
|
+
user.try!(:email)
|
40
|
+
end
|
41
|
+
|
42
|
+
def verify_purchaser
|
43
|
+
return unless user_id && product_id
|
44
|
+
|
45
|
+
verified_purchase = Spree::LineItem.joins(:order, :variant)
|
46
|
+
.where.not(spree_orders: { completed_at: nil })
|
47
|
+
.find_by(
|
48
|
+
spree_variants: { product_id: product_id },
|
49
|
+
spree_orders: { user_id: user_id }
|
50
|
+
).present?
|
51
|
+
|
52
|
+
self.verified_purchaser = verified_purchase
|
35
53
|
end
|
36
54
|
end
|
@@ -1,14 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Spree::ReviewsAbility
|
2
4
|
include CanCan::Ability
|
3
5
|
|
4
|
-
def initialize
|
6
|
+
def initialize(user)
|
5
7
|
review_ability_class = self.class
|
6
|
-
|
8
|
+
|
9
|
+
can :create, Spree::Review do |_review|
|
7
10
|
review_ability_class.allow_anonymous_reviews? || !user.email.blank?
|
8
11
|
end
|
9
|
-
|
12
|
+
|
13
|
+
can :create, Spree::FeedbackReview do |_review|
|
10
14
|
review_ability_class.allow_anonymous_reviews? || !user.email.blank?
|
11
15
|
end
|
16
|
+
|
17
|
+
# You can read your own reviews, and everyone can read approved ones
|
18
|
+
can :read, Spree::Review do |review|
|
19
|
+
review.user == user || review.approved?
|
20
|
+
end
|
21
|
+
|
22
|
+
# You can only change your own review
|
23
|
+
can [:update, :destroy], Spree::Review do |review|
|
24
|
+
review.user == user
|
25
|
+
end
|
12
26
|
end
|
13
27
|
|
14
28
|
def self.allow_anonymous_reviews?
|
@@ -1,26 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Spree::ReviewsConfiguration < Spree::Preferences::Configuration
|
2
4
|
def self.boolean_preferences
|
3
|
-
%w(include_unapproved_reviews feedback_rating show_email require_login track_locale)
|
5
|
+
%w(display_unapproved_reviews include_unapproved_reviews feedback_rating show_email require_login track_locale)
|
4
6
|
end
|
5
7
|
|
6
8
|
# include non-approved reviews in (public) listings
|
7
|
-
preference :include_unapproved_reviews, :boolean, :
|
9
|
+
preference :include_unapproved_reviews, :boolean, default: false
|
10
|
+
|
11
|
+
# displays non-approved reviews in (public) listings
|
12
|
+
preference :display_unapproved_reviews, :boolean, default: false
|
8
13
|
|
9
14
|
# control how many reviews are shown in summaries etc.
|
10
|
-
preference :preview_size, :integer, :
|
15
|
+
preference :preview_size, :integer, default: 3
|
11
16
|
|
12
17
|
# show a reviewer's email address
|
13
|
-
preference :show_email, :boolean, :
|
18
|
+
preference :show_email, :boolean, default: false
|
19
|
+
|
20
|
+
# show if a reviewer actually purchased the product
|
21
|
+
preference :show_verified_purchaser, :boolean, default: false
|
14
22
|
|
15
23
|
# show helpfullness rating form elements
|
16
|
-
preference :feedback_rating, :boolean, :
|
24
|
+
preference :feedback_rating, :boolean, default: false
|
17
25
|
|
18
26
|
# require login to post reviews
|
19
|
-
preference :require_login, :boolean, :
|
27
|
+
preference :require_login, :boolean, default: true
|
20
28
|
|
21
29
|
# whether to keep track of the reviewer's locale
|
22
|
-
preference :track_locale, :boolean, :
|
30
|
+
preference :track_locale, :boolean, default: false
|
23
31
|
|
24
32
|
# render checkbox for a user to approve to show their identifier (name or email) on their review
|
25
|
-
preference :render_show_identifier_checkbox, :boolean, :
|
33
|
+
preference :render_show_identifier_checkbox, :boolean, default: false
|
26
34
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
:
|
5
|
-
:
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Deface::Override.new(virtual_path: "spree/products/show",
|
4
|
+
name: "converted_product_properties_767643482",
|
5
|
+
insert_after: "[data-hook='product_properties']",
|
6
|
+
partial: "spree/shared/reviews",
|
7
|
+
disabled: false)
|
@@ -1,4 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Spree::Backend::Config.configure do |config|
|
4
|
+
config.menu_items.detect { |menu_item|
|
5
|
+
menu_item.label == :products
|
6
|
+
}.sections << :reviews
|
7
|
+
end
|
8
|
+
|
9
|
+
Deface::Override.new(virtual_path: "spree/admin/shared/_product_sub_menu",
|
10
|
+
name: "reviews_admin_tab",
|
11
|
+
insert_bottom: "[data-hook='admin_product_sub_tabs']",
|
12
|
+
text: "<%= tab(:reviews, label: 'review_management') %>")
|