solidus_reviews 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gem_release.yml +5 -0
  3. data/.github/stale.yml +17 -0
  4. data/.gitignore +11 -8
  5. data/.rspec +1 -1
  6. data/.rubocop.yml +1 -11
  7. data/CHANGELOG.md +32 -0
  8. data/Gemfile +9 -13
  9. data/{LICENSE.md → LICENSE} +1 -1
  10. data/Rakefile +4 -19
  11. data/app/controllers/spree/reviews_controller.rb +29 -2
  12. data/app/decorators/controllers/solidus_reviews/spree/{admin/products_controller_decorator.rb → products_controller_decorator.rb} +0 -4
  13. data/app/models/spree/feedback_review.rb +1 -1
  14. data/app/models/spree/permission_sets/review_display.rb +11 -0
  15. data/app/models/spree/permission_sets/review_management.rb +11 -0
  16. data/app/models/spree/review.rb +16 -2
  17. data/app/models/spree/reviews_ability.rb +5 -0
  18. data/app/models/spree/reviews_configuration.rb +10 -1
  19. data/app/overrides/add_reviews_tab_to_admin.rb +12 -4
  20. data/app/overrides/add_reviews_to_admin_configuration_sidebar.rb +12 -5
  21. data/app/views/spree/admin/review_settings/edit.html.erb +7 -0
  22. data/app/views/spree/admin/reviews/edit.html.erb +4 -2
  23. data/app/views/spree/admin/reviews/index.html.erb +9 -5
  24. data/app/views/spree/reviews/_form.html.erb +6 -4
  25. data/app/views/spree/reviews/edit.html.erb +3 -0
  26. data/app/views/spree/shared/_review.html.erb +6 -4
  27. data/bin/console +17 -0
  28. data/bin/rails +11 -3
  29. data/bin/setup +8 -0
  30. data/config/locales/de-CH.yml +1 -1
  31. data/config/locales/de.yml +1 -1
  32. data/config/locales/en-GB.yml +2 -1
  33. data/config/locales/en.yml +2 -1
  34. data/config/locales/es.yml +2 -1
  35. data/config/locales/fr.yml +1 -1
  36. data/config/locales/it.yml +1 -1
  37. data/config/locales/pl.yml +1 -1
  38. data/config/locales/pt-BR.yml +1 -1
  39. data/config/locales/pt.yml +1 -1
  40. data/config/locales/ro.yml +1 -1
  41. data/config/locales/sv.yml +1 -1
  42. data/config/locales/tr.yml +1 -1
  43. data/config/locales/uk.yml +1 -1
  44. data/config/locales/zh-CN.yml +1 -1
  45. data/config/locales/zh-TW.yml +1 -1
  46. data/config/routes.rb +3 -1
  47. data/lib/controllers/spree/api/feedback_reviews_controller.rb +91 -0
  48. data/lib/solidus_reviews.rb +2 -4
  49. data/lib/solidus_reviews/engine.rb +12 -8
  50. data/lib/solidus_reviews/version.rb +1 -1
  51. data/solidus_reviews.gemspec +19 -12
  52. data/spec/controllers/spree/api/feedback_reviews_controller_spec.rb +136 -0
  53. data/spec/controllers/spree/reviews_controller_spec.rb +136 -0
  54. data/spec/models/review_spec.rb +27 -0
  55. data/spec/models/reviews_configuration_spec.rb +12 -0
  56. data/spec/spec_helper.rb +16 -3
  57. metadata +48 -39
  58. data/spec/controllers/spree/products_controller_spec.rb +0 -11
@@ -21,10 +21,12 @@
21
21
  <%= f.text_area :review, wrap: "virtual", rows: "10", cols: "50" %>
22
22
  </p>
23
23
 
24
- <p class="review_images_field">
25
- <%= f.label :images %><br>
26
- <%= f.file_field :images, :accept => "image/*", multiple: true %>
27
- </p>
24
+ <% if Spree::Reviews::Config[:allow_image_upload] %>
25
+ <p class="review_images_field">
26
+ <%= f.label :images %><br>
27
+ <%= f.file_field :images, :accept => "image/*", multiple: true %>
28
+ </p>
29
+ <% end %>
28
30
 
29
31
  <% if Spree::Reviews::Config[:render_show_identifier_checkbox] %>
30
32
  <p class="review_show_identifier_field">
@@ -0,0 +1,3 @@
1
+ <%= content_tag :h2, I18n.t("spree.leave_us_a_review_for", name: @product.name), class: 'new-review-title' %>
2
+
3
+ <%= render 'form', review: @review, product: @product %>
@@ -24,10 +24,12 @@
24
24
  <div itemprop="reviewBody">
25
25
  <%= simple_format(review.review) %>
26
26
  </div>
27
- <% review.images.each do |image| %>
28
- <div itemprop="image">
29
- <%= link_to image_tag(image.url(:product)), image.url(:original) %>
30
- </div>
27
+ <% if Spree::Reviews::Config[:allow_image_upload] %>
28
+ <% review.images.each do |image| %>
29
+ <div itemprop="image">
30
+ <%= link_to image_tag(image.url(:product)), image.url(:original) %>
31
+ </div>
32
+ <% end %>
31
33
  <% end %>
32
34
  <% if Spree::Reviews::Config[:feedback_rating] && (!Spree::Reviews::Config[:require_login] || spree_current_user) %>
33
35
  <div class="feedback_review" id="feedback_review_<%= review.id %>">
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require "bundler/setup"
6
+ require "solidus_reviews"
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting
9
+ # with your gem easier. You can also use a different console, if you like.
10
+ $LOAD_PATH.unshift(*Dir["#{__dir__}/../app/*"])
11
+
12
+ # (If you use this, don't forget to add pry to your Gemfile!)
13
+ # require "pry"
14
+ # Pry.start
15
+
16
+ require "irb"
17
+ IRB.start(__FILE__)
data/bin/rails CHANGED
@@ -1,7 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
+
2
3
  # frozen_string_literal: true
3
4
 
4
- # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
5
+ app_root = 'spec/dummy'
6
+
7
+ unless File.exist? "#{app_root}/bin/rails"
8
+ system "bin/rake", app_root or begin # rubocop:disable Style/AndOr
9
+ warn "Automatic creation of the dummy app failed"
10
+ exit 1
11
+ end
12
+ end
5
13
 
6
- ENGINE_PATH = File.expand_path('..', __dir__)
7
- load File.expand_path('../spec/dummy/script/rails', __dir__)
14
+ Dir.chdir app_root
15
+ exec 'bin/rails', *ARGV
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ gem install bundler --conservative
7
+ bundle update
8
+ bundle exec rake extension:test_app
@@ -36,7 +36,7 @@ de-CH:
36
36
  one: basiert auf einer Rezension
37
37
  other: "basiert auf %{count} Rezensionen"
38
38
  by: Von
39
- editing_review_for_html: 'Rezension über %{link} bearbeiten'
39
+ editing_review_for_html: 'Rezension über %{product_name} bearbeiten'
40
40
  error_approve_review: Fehler bei der Freischaltung
41
41
  error_no_product: Das rezensierte Produkt existiert nicht mehr.
42
42
  feedback: Feedback
@@ -36,7 +36,7 @@ de:
36
36
  one: basiert auf einer Rezension
37
37
  other: "basiert auf %{count} Rezensionen"
38
38
  by: Von
39
- editing_review_for_html: 'Rezension über %{link} bearbeiten'
39
+ editing_review_for_html: 'Rezension über %{product_name} bearbeiten'
40
40
  error_approve_review: Fehler bei der Freischaltung
41
41
  error_no_product: Das rezensierte Produkt existiert nicht mehr.
42
42
  feedback: Feedback
@@ -35,7 +35,7 @@ en-GB:
35
35
  one: based upon one review
36
36
  other: "based upon %{count} reviews"
37
37
  by: by
38
- editing_review_for_html: 'Editing review for %{link}'
38
+ editing_review_for_html: 'Editing review for %{product_name}'
39
39
  error_approve_review: Error approving review
40
40
  error_no_product: The reviewed product doesn't exist anymore
41
41
  feedback: Feedback
@@ -64,6 +64,7 @@ en-GB:
64
64
  show_email: Show email addresses
65
65
  show_verified_purchaser: Show verified purchaser
66
66
  track_locale: Track user's locale
67
+ allow_image_upload: Allow images to be attached to reviews
67
68
  star:
68
69
  one: "1"
69
70
  other: "%{count}"
@@ -35,7 +35,7 @@ en:
35
35
  one: based upon one review
36
36
  other: "based upon %{count} reviews"
37
37
  by: by
38
- editing_review_for_html: 'Editing review for %{link}'
38
+ editing_review_for_html: 'Editing review for %{product_name}'
39
39
  error_approve_review: Error approving review
40
40
  error_no_product: The reviewed product doesn't exist anymore
41
41
  feedback: Feedback
@@ -64,6 +64,7 @@ en:
64
64
  show_email: Show email addresses
65
65
  show_verified_purchaser: Show verified purchaser
66
66
  track_locale: Track user's locale
67
+ allow_image_upload: Allow images to be attached to reviews
67
68
  star:
68
69
  one: "1"
69
70
  other: "%{count}"
@@ -35,7 +35,7 @@ es:
35
35
  one: "basado en una valoración"
36
36
  other: "basado en %{count} valoraciones"
37
37
  by: por
38
- editing_review_for_html: 'Editando la valoración para %{link}'
38
+ editing_review_for_html: 'Editando la valoración para %{product_name}'
39
39
  error_approve_review: "Error aprobando la valoración"
40
40
  error_no_product: "El producto valorado ya no existe"
41
41
  feedback: Feedback
@@ -64,6 +64,7 @@ es:
64
64
  show_email: "Mostrar las direcciones de correo"
65
65
  show_verified_purchaser: Mostrar comprador verificado
66
66
  track_locale: "Rastrear el locale del usuario"
67
+ allow_image_upload: "Permitir adjuntar imagenes con el comentario"
67
68
  star:
68
69
  one: "1"
69
70
  other: "%{count}"
@@ -35,7 +35,7 @@ fr:
35
35
  one: basé sur un commentaire
36
36
  other: "basé sur %{count} commentaires"
37
37
  by: par
38
- editing_review_for_html: 'Modification du commentaire pour %{link}'
38
+ editing_review_for_html: 'Modification du commentaire pour %{product_name}'
39
39
  error_approve_review: Erreur en approuvant le commentaire
40
40
  error_no_product: Le produit commenté n'existe plus
41
41
  feedback: Réaction
@@ -34,7 +34,7 @@ it:
34
34
  one: basato su una recensione
35
35
  other: "basato su %{count} recensioni"
36
36
  by: da
37
- editing_review_for_html: 'Modifica la recensione per %{link}'
37
+ editing_review_for_html: 'Modifica la recensione per %{product_name}'
38
38
  error_approve_review: Errore approvazione recensione
39
39
  error_no_product: "Il prodotto recensito non esiste più"
40
40
  feedback: Feedback
@@ -37,7 +37,7 @@ pl:
37
37
  few: "na podstawie %{count} opinii"
38
38
  other: "na podstawie %{count} opinii"
39
39
  by: "przez"
40
- editing_review_for_html: 'Edycja opinii dla %{link}'
40
+ editing_review_for_html: 'Edycja opinii dla %{product_name}'
41
41
  error_approve_review: Błąd przy zatwierdzaniu opinii
42
42
  error_no_product: Oceniamy produkt nie istnieje
43
43
  feedback: Komentarz
@@ -35,7 +35,7 @@ pt-BR:
35
35
  one: 'baseado em uma avaliação'
36
36
  other: "baseado em %{count} avaliações"
37
37
  by: 'por'
38
- editing_review_for_html: 'Editando avaliação para %{link}'
38
+ editing_review_for_html: 'Editando avaliação para %{product_name}'
39
39
  error_approve_review: 'Erro aprovando avaliação'
40
40
  error_no_product: "O produto avaliado não existe mais"
41
41
  feedback: 'Parecer'
@@ -35,7 +35,7 @@ pt:
35
35
  one: baseada numa avaliação
36
36
  other: "baseada em %{count} avaliações"
37
37
  by: por
38
- editing_review_for_html: 'Editando a avaliação para %{link}'
38
+ editing_review_for_html: 'Editando a avaliação para %{product_name}'
39
39
  error_approve_review: Erro aprovando a avaliação
40
40
  error_no_product: O produto avaliado já não existe
41
41
  feedback: Feedback
@@ -39,7 +39,7 @@ ro:
39
39
  other: "bazată pe %{count} recenzii"
40
40
  many: "bazată pe %{count} de recenzii"
41
41
  by: de
42
- editing_review_for_html: 'Editare recenzie pentru %{link}'
42
+ editing_review_for_html: 'Editare recenzie pentru %{product_name}'
43
43
  error_approve_review: Eroare la aprobarea recenziei
44
44
  error_no_product: Produsul recenziat nu mai există
45
45
  feedback: Feedback
@@ -35,7 +35,7 @@ sv:
35
35
  one: "baserad på en recension"
36
36
  other: "baserad på %{count} recensioner"
37
37
  by: av
38
- editing_review_for_html: "Editerad recension för %{link}"
38
+ editing_review_for_html: "Editerad recension för %{product_name}"
39
39
  error_approve_review: "Problem med att godkänna recension"
40
40
  error_no_product: "Den betygsatta produkten finns inte längre"
41
41
  feedback: Återkoppling
@@ -35,7 +35,7 @@ tr:
35
35
  one: bir incelemeye göre
36
36
  other: "%{count} incelemeye göre"
37
37
  by: tarafından
38
- editing_review_for_html: 'Yorumu düzenle %{link}'
38
+ editing_review_for_html: 'Yorumu düzenle %{product_name}'
39
39
  error_approve_review: Yorum onaylamada hata
40
40
  error_no_product: Yorumlanan ürün artık yok
41
41
  feedback: Geri bildirim
@@ -39,7 +39,7 @@ uk:
39
39
  many: "на основі %{count} відгуків"
40
40
  other: "на основі %{count} відгуків"
41
41
  by: від
42
- editing_review_for_html: 'Редагувати відгук на %{link}'
42
+ editing_review_for_html: 'Редагувати відгук на %{product_name}'
43
43
  error_approve_review: Не вдалось схвалити відгук
44
44
  error_no_product: Товару, на який писався відгук, більше не існує
45
45
  feedback: Корисність
@@ -33,7 +33,7 @@ zh-CN:
33
33
  one: 以评论为基础
34
34
  other: "以 %{count} 個评论为基础"
35
35
  by: 由
36
- editing_review_for_html: '正在修改 %{link} 的评论'
36
+ editing_review_for_html: '正在修改 %{product_name} 的评论'
37
37
  error_approve_review: 出错了,不能核准评论
38
38
  error_no_product: 被评论的产品不存在了。
39
39
  feedback: 回馈
@@ -33,7 +33,7 @@ zh-TW:
33
33
  one: 以評論為基礎
34
34
  other: '以 %{count} 個評論為基礎'
35
35
  by: 由
36
- editing_review_for_html: '正在修改 %{link} 的評論'
36
+ editing_review_for_html: '正在修改 %{product_name} 的評論'
37
37
  error_approve_review: 出錯了,不能核準評論
38
38
  error_no_product: 被評論的產品不存在了。
39
39
  feedback: 回饋
@@ -13,7 +13,7 @@ Spree::Core::Engine.routes.draw do
13
13
  end
14
14
 
15
15
  resources :products, only: [] do
16
- resources :reviews, only: [:index, :new, :create] do
16
+ resources :reviews, only: [:index, :new, :create, :edit, :update] do
17
17
  end
18
18
  end
19
19
  post '/reviews/:review_id/feedback(.:format)' => 'feedback_reviews#create', as: :feedback_reviews
@@ -22,6 +22,8 @@ Spree::Core::Engine.routes.draw do
22
22
  namespace :api, defaults: { format: 'json' } do
23
23
  resources :reviews, only: [:show, :create, :update, :destroy]
24
24
 
25
+ resources :feedback_reviews, only: [:create, :update, :destroy]
26
+
25
27
  resources :products do
26
28
  resources :reviews, only: [:index]
27
29
  end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Api
5
+ class FeedbackReviewsController < Spree::Api::BaseController
6
+ respond_to :json
7
+
8
+ before_action :load_review, only: [:create, :update, :destroy]
9
+ before_action :load_feedback_review, only: [:update, :destroy]
10
+ before_action :find_review_user
11
+ before_action :sanitize_rating, only: [:create, :update]
12
+ before_action :prevent_multiple_feedback_reviews, only: [:create]
13
+
14
+ def create
15
+ if @review.present?
16
+ @feedback_review = @review.feedback_reviews.new(feedback_review_params)
17
+ @feedback_review.user = @current_api_user
18
+ @feedback_review.locale = I18n.locale.to_s if Spree::Reviews::Config[:track_locale]
19
+ end
20
+
21
+ authorize! :create, @feedback_review
22
+ if @feedback_review.save
23
+ render json: @feedback_review, status: :created
24
+ else
25
+ invalid_resource!(@feedback_review)
26
+ end
27
+ end
28
+
29
+ def update
30
+ authorize! :update, @feedback_review
31
+
32
+ if @feedback_review.update(feedback_review_params)
33
+ render json: @feedback_review, status: :ok
34
+ else
35
+ invalid_resource!(@feedback_review)
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ authorize! :destroy, @feedback_review
41
+
42
+ if @feedback_review.destroy
43
+ render json: @feedback_review, status: :ok
44
+ else
45
+ invalid_resource!(@feedback_review)
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def permitted_feedback_review_attributes
52
+ [:rating, :comment]
53
+ end
54
+
55
+ def feedback_review_params
56
+ params.require(:feedback_review).permit(permitted_feedback_review_attributes)
57
+ end
58
+
59
+ # Finds user based on api_key or by user_id if api_key belongs to an admin.
60
+ def find_review_user
61
+ if params[:user_id] && @current_user_roles.include?('admin')
62
+ @current_api_user = Spree.user_class.find(params[:user_id])
63
+ end
64
+ end
65
+
66
+ # Loads any review that is shared between the user and product
67
+ def load_review
68
+ @review = Spree::Review.find(params[:review_id])
69
+ end
70
+
71
+ # Loads the feedback_review
72
+ def load_feedback_review
73
+ @feedback_review = Spree::FeedbackReview.find(params[:id])
74
+ end
75
+
76
+ # Ensures that a user can't leave multiple feedbacks on a single review
77
+ def prevent_multiple_feedback_reviews
78
+ @feedback_review = @review.feedback_reviews.find_by(user_id: @current_api_user)
79
+ if @feedback_review.present?
80
+ invalid_resource!(@feedback_review)
81
+ end
82
+ end
83
+
84
+ # Converts rating strings like "5 units" to "5"
85
+ # Operates on params
86
+ def sanitize_rating
87
+ params[:rating].to_s.sub!(/\s*[^0-9]*\z/, '') unless params[:feedback_review] && params[:feedback_review][:rating].blank?
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'solidus'
3
+ require 'solidus_core'
4
4
  require 'solidus_support'
5
- require 'sassc/rails'
6
5
  require 'deface'
7
- require 'coffee_script'
8
6
 
9
- require 'solidus_reviews/engine'
10
7
  require 'solidus_reviews/version'
8
+ require 'solidus_reviews/engine'
@@ -1,22 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'spree/core'
4
+
3
5
  module SolidusReviews
4
6
  class Engine < Rails::Engine
5
- require 'spree/core'
6
- isolate_namespace ::Spree
7
+ include SolidusSupport::EngineExtensions
8
+
9
+ isolate_namespace Spree
10
+
7
11
  engine_name 'solidus_reviews'
8
12
 
9
- def self.activate
10
- Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
11
- Rails.configuration.cache_classes ? require(c) : load(c)
12
- end
13
+ # use rspec for tests
14
+ config.generators do |g|
15
+ g.test_framework :rspec
16
+ end
17
+
18
+ config.to_prepare do
13
19
  ::Spree::Ability.register_ability(::Spree::ReviewsAbility)
14
20
  end
15
21
 
16
22
  if SolidusSupport.api_available?
17
23
  paths["app/controllers"] << "lib/controllers"
18
24
  end
19
-
20
- config.to_prepare &method(:activate).to_proc
21
25
  end
22
26
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusReviews
4
- VERSION = '1.3.0'
4
+ VERSION = '1.4.0'
5
5
  end
@@ -4,25 +4,32 @@ $:.push File.expand_path('lib', __dir__)
4
4
  require 'solidus_reviews/version'
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.platform = Gem::Platform::RUBY
8
7
  s.name = 'solidus_reviews'
9
8
  s.version = SolidusReviews::VERSION
10
9
  s.summary = 'Review and rating functionality for your Solidus store.'
11
- s.authors = ['Solidus Contrib']
12
- s.description = s.summary
13
- s.required_ruby_version = '>= 1.9.3'
10
+ s.license = 'BSD-3-Clause'
14
11
 
12
+ s.author = 'Solidus Contrib'
15
13
  s.homepage = 'https://github.com/solidusio-contrib/solidus_reviews'
16
- s.license = 'BSD-3'
17
14
 
18
- s.files = `git ls-files`.split("\n")
19
- s.test_files = `git ls-files -- spec/*`.split("\n")
20
- s.require_path = 'lib'
21
- s.requirements << 'none'
15
+ if s.respond_to?(:metadata)
16
+ s.metadata["homepage_uri"] = s.homepage if s.homepage
17
+ s.metadata["source_code_uri"] = s.homepage if s.homepage
18
+ end
19
+
20
+ s.required_ruby_version = '~> 2.4'
21
+
22
+ s.files = Dir.chdir(File.expand_path(__dir__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ s.test_files = Dir['spec/**/*']
26
+ s.bindir = "exe"
27
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ s.require_paths = ["lib"]
22
29
 
23
30
  s.add_dependency 'deface', '~> 1.0'
24
- s.add_dependency 'solidus', ['>= 1.4', '< 3']
25
- s.add_dependency 'solidus_support'
31
+ s.add_dependency 'solidus_core', ['>= 2.0.0', '< 3']
32
+ s.add_dependency 'solidus_support', '~> 0.4'
26
33
 
27
- s.add_development_dependency 'solidus_extension_dev_tools'
34
+ s.add_development_dependency 'solidus_dev_support'
28
35
  end