workarea-reviews 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.eslintignore +2 -0
  4. data/.eslintrc +24 -0
  5. data/.eslintrc.json +35 -0
  6. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  7. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  8. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  9. data/.github/workflows/ci.yml +60 -0
  10. data/.gitignore +15 -0
  11. data/.rubocop.yml +3 -0
  12. data/.scss-lint.yml +188 -0
  13. data/.stylelintrc.json +8 -0
  14. data/.yardopts +1 -0
  15. data/CHANGELOG.md +745 -0
  16. data/CODE_OF_CONDUCT.md +3 -0
  17. data/CONTRIBUTING.md +3 -0
  18. data/Gemfile +8 -0
  19. data/LICENSE +52 -0
  20. data/README.md +107 -0
  21. data/Rakefile +53 -0
  22. data/app/assets/images/workarea/admin/icons/star.svg +1 -0
  23. data/app/assets/images/workarea/storefront/icons/empty_star.svg +1 -0
  24. data/app/assets/images/workarea/storefront/icons/half_star.svg +1 -0
  25. data/app/assets/images/workarea/storefront/icons/star.svg +1 -0
  26. data/app/assets/javascripts/workarea/storefront/reviews/modules/product_review_ajax_submit.js +39 -0
  27. data/app/assets/javascripts/workarea/storefront/reviews/modules/product_reviews_sort_menus.js +82 -0
  28. data/app/assets/javascripts/workarea/storefront/reviews/modules/rating_buttons.js +103 -0
  29. data/app/assets/javascripts/workarea/storefront/reviews/templates/sort_by_property.jst.ejs +11 -0
  30. data/app/assets/stylesheets/workarea/storefront/reviews/components/_rating.scss +28 -0
  31. data/app/assets/stylesheets/workarea/storefront/reviews/components/_reviews.scss +59 -0
  32. data/app/assets/stylesheets/workarea/storefront/reviews/components/_reviews_aggregate.scss +38 -0
  33. data/app/assets/stylesheets/workarea/storefront/reviews/components/_write_review.scss +63 -0
  34. data/app/controllers/workarea/admin/catalog_products_controller.decorator +9 -0
  35. data/app/controllers/workarea/admin/reports_controller.decorator +10 -0
  36. data/app/controllers/workarea/admin/reviews_controller.rb +51 -0
  37. data/app/controllers/workarea/storefront/review_requests_controller.rb +50 -0
  38. data/app/controllers/workarea/storefront/reviews_controller.rb +53 -0
  39. data/app/helpers/workarea/admin/reviews_helper.rb +13 -0
  40. data/app/helpers/workarea/storefront/reviews_helper.rb +22 -0
  41. data/app/helpers/workarea/storefront/reviews_schema_org_helper.rb +34 -0
  42. data/app/mailers/workarea/admin/status_report_mailer.decorator +8 -0
  43. data/app/mailers/workarea/storefront/review_mailer.rb +23 -0
  44. data/app/models/workarea/catalog/product.decorator +15 -0
  45. data/app/models/workarea/fulfillment.decorator +11 -0
  46. data/app/models/workarea/insights/most_active_reviewers.rb +34 -0
  47. data/app/models/workarea/insights/most_reviewed_products.rb +33 -0
  48. data/app/models/workarea/insights/top_rated_products.rb +33 -0
  49. data/app/models/workarea/review.rb +124 -0
  50. data/app/models/workarea/review/request.rb +62 -0
  51. data/app/models/workarea/search/admin/review.rb +72 -0
  52. data/app/models/workarea/search/storefront/product.decorator +9 -0
  53. data/app/models/workarea/sort.decorator +17 -0
  54. data/app/queries/workarea/reports/reviews_by_product.rb +86 -0
  55. data/app/queries/workarea/reports/reviews_by_user.rb +71 -0
  56. data/app/queries/workarea/review_request_params.rb +47 -0
  57. data/app/queries/workarea/review_summary.rb +11 -0
  58. data/app/queries/workarea/search/admin_reviews.rb +40 -0
  59. data/app/queries/workarea/search/category_browse.decorator +9 -0
  60. data/app/queries/workarea/search/product_search.decorator +9 -0
  61. data/app/seeds/workarea/review_seeds.rb +49 -0
  62. data/app/services/workarea/create_review.rb +99 -0
  63. data/app/view_models/workarea/admin/dashboards/reports_view_model.decorator +11 -0
  64. data/app/view_models/workarea/admin/product_view_model.decorator +7 -0
  65. data/app/view_models/workarea/admin/reports/reviews_by_product_view_model.rb +27 -0
  66. data/app/view_models/workarea/admin/review_view_model.rb +23 -0
  67. data/app/view_models/workarea/admin/reviews_search_view_model.rb +46 -0
  68. data/app/view_models/workarea/storefront/product_view_model.decorator +13 -0
  69. data/app/view_models/workarea/storefront/review_view_model.rb +14 -0
  70. data/app/views/workarea/admin/activities/_review_create.html.haml +12 -0
  71. data/app/views/workarea/admin/activities/_review_destroy.html.haml +10 -0
  72. data/app/views/workarea/admin/activities/_review_update.html.haml +10 -0
  73. data/app/views/workarea/admin/dashboards/_reviews_by_product_card.html.haml +17 -0
  74. data/app/views/workarea/admin/insights/_most_active_reviewers.html.haml +22 -0
  75. data/app/views/workarea/admin/insights/_most_reviewed_products.html.haml +22 -0
  76. data/app/views/workarea/admin/insights/_top_rated_products.html.haml +22 -0
  77. data/app/views/workarea/admin/reports/reviews_by_product.html.haml +44 -0
  78. data/app/views/workarea/admin/reviews/_aux_navigation.html.haml +5 -0
  79. data/app/views/workarea/admin/reviews/_catalog_products_aux_link.html.haml +5 -0
  80. data/app/views/workarea/admin/reviews/_dashboard_navigation.html.haml +1 -0
  81. data/app/views/workarea/admin/reviews/_menu.html.haml +3 -0
  82. data/app/views/workarea/admin/reviews/_summary.html.haml +12 -0
  83. data/app/views/workarea/admin/reviews/edit.html.haml +77 -0
  84. data/app/views/workarea/admin/reviews/index.html.haml +74 -0
  85. data/app/views/workarea/admin/status_report_mailer/_reviews.html.haml +5 -0
  86. data/app/views/workarea/storefront/products/_rating.html.haml +9 -0
  87. data/app/views/workarea/storefront/products/_reviews.html.haml +23 -0
  88. data/app/views/workarea/storefront/products/_reviews_aggregate.html.haml +22 -0
  89. data/app/views/workarea/storefront/products/_reviews_summary.html.haml +2 -0
  90. data/app/views/workarea/storefront/review_mailer/review_request.html.haml +24 -0
  91. data/app/views/workarea/storefront/review_requests/show.html.haml +45 -0
  92. data/app/views/workarea/storefront/reviews/new.html.haml +68 -0
  93. data/app/views/workarea/storefront/style_guides/_reviews_product_summary_docs.html.haml +13 -0
  94. data/app/views/workarea/storefront/style_guides/components/_reviews.html.haml +17 -0
  95. data/app/workers/workarea/create_review_requests.rb +33 -0
  96. data/app/workers/workarea/schedule_review_requests.rb +44 -0
  97. data/app/workers/workarea/send_review_requests.rb +12 -0
  98. data/app/workers/workarea/update_product_review_data.rb +26 -0
  99. data/bin/rails +18 -0
  100. data/config/initializers/append_points.rb +75 -0
  101. data/config/initializers/assets.rb +1 -0
  102. data/config/initializers/configuration.rb +31 -0
  103. data/config/initializers/rack_attack.rb +11 -0
  104. data/config/initializers/recaptcha.rb +19 -0
  105. data/config/initializers/scheduled_jobs.rb +8 -0
  106. data/config/locales/en.yml +150 -0
  107. data/config/routes.rb +25 -0
  108. data/lib/tasks/verify.rake +16 -0
  109. data/lib/workarea/mailer_previews/storefront/review_mailer_preview.rb +10 -0
  110. data/lib/workarea/reviews.rb +13 -0
  111. data/lib/workarea/reviews/engine.rb +16 -0
  112. data/lib/workarea/reviews/version.rb +5 -0
  113. data/package.json +9 -0
  114. data/test/dummy/Rakefile +6 -0
  115. data/test/dummy/app/assets/config/manifest.js +4 -0
  116. data/test/dummy/app/assets/images/.keep +0 -0
  117. data/test/dummy/app/assets/javascripts/application.js +13 -0
  118. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  119. data/test/dummy/app/controllers/application_controller.rb +3 -0
  120. data/test/dummy/app/controllers/concerns/.keep +0 -0
  121. data/test/dummy/app/helpers/application_helper.rb +2 -0
  122. data/test/dummy/app/jobs/application_job.rb +2 -0
  123. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  124. data/test/dummy/app/models/concerns/.keep +0 -0
  125. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  126. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  127. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  128. data/test/dummy/bin/bundle +3 -0
  129. data/test/dummy/bin/rails +4 -0
  130. data/test/dummy/bin/rake +4 -0
  131. data/test/dummy/bin/setup +34 -0
  132. data/test/dummy/bin/update +29 -0
  133. data/test/dummy/config.ru +5 -0
  134. data/test/dummy/config/application.rb +25 -0
  135. data/test/dummy/config/boot.rb +5 -0
  136. data/test/dummy/config/cable.yml +9 -0
  137. data/test/dummy/config/environment.rb +5 -0
  138. data/test/dummy/config/environments/development.rb +55 -0
  139. data/test/dummy/config/environments/production.rb +86 -0
  140. data/test/dummy/config/environments/test.rb +43 -0
  141. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  142. data/test/dummy/config/initializers/assets.rb +11 -0
  143. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  144. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  145. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  146. data/test/dummy/config/initializers/inflections.rb +16 -0
  147. data/test/dummy/config/initializers/mime_types.rb +4 -0
  148. data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
  149. data/test/dummy/config/initializers/session_store.rb +5 -0
  150. data/test/dummy/config/initializers/workarea.rb +5 -0
  151. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  152. data/test/dummy/config/locales/en.yml +23 -0
  153. data/test/dummy/config/puma.rb +47 -0
  154. data/test/dummy/config/routes.rb +5 -0
  155. data/test/dummy/config/secrets.yml +22 -0
  156. data/test/dummy/config/spring.rb +6 -0
  157. data/test/dummy/db/seeds.rb +2 -0
  158. data/test/dummy/lib/assets/.keep +0 -0
  159. data/test/dummy/log/.keep +0 -0
  160. data/test/factories/reviews.rb +32 -0
  161. data/test/fixtures/reviews.csv +5 -0
  162. data/test/helpers/workarea/storefront/reviews_helper_test.rb +20 -0
  163. data/test/integration/workarea/admin/reviews_integration_test.rb +37 -0
  164. data/test/integration/workarea/storefront/review_requests_integration_test.rb +63 -0
  165. data/test/integration/workarea/storefront/reviews_integration_test.rb +82 -0
  166. data/test/javascripts/fixtures/product_review_ajax_submit.html.haml +4 -0
  167. data/test/javascripts/product_review_ajax_submit_spec.js +28 -0
  168. data/test/javascripts/spec_helper.js +23 -0
  169. data/test/models/workarea/insights/most_active_reviewers_test.rb +32 -0
  170. data/test/models/workarea/insights/most_reviewed_products_test.rb +32 -0
  171. data/test/models/workarea/insights/top_rated_products_test.rb +49 -0
  172. data/test/models/workarea/review/request_test.rb +18 -0
  173. data/test/models/workarea/review_test.rb +105 -0
  174. data/test/models/workarea/search/storefront/product_test.decorator +14 -0
  175. data/test/queries/workarea/reports/reviews_by_product_test.rb +104 -0
  176. data/test/queries/workarea/reports/reviews_by_user_test.rb +102 -0
  177. data/test/queries/workarea/review_request_params_test.rb +64 -0
  178. data/test/services/workarea/create_review_test.rb +131 -0
  179. data/test/system/workarea/admin/review_system_test.rb +96 -0
  180. data/test/system/workarea/admin/reviews_by_product_system_test.rb +60 -0
  181. data/test/system/workarea/storefront/review_request_system_test.rb +34 -0
  182. data/test/system/workarea/storefront/review_system_test.rb +113 -0
  183. data/test/teaspoon_env.rb +10 -0
  184. data/test/test_helper.rb +11 -0
  185. data/test/workers/workarea/create_review_requests_test.rb +38 -0
  186. data/test/workers/workarea/schedule_review_requests_test.rb +115 -0
  187. data/test/workers/workarea/send_review_requests_test.rb +30 -0
  188. data/workarea-reviews.gemspec +22 -0
  189. data/yarn.lock +3265 -0
  190. metadata +265 -0
@@ -0,0 +1,27 @@
1
+ module Workarea
2
+ module Admin
3
+ module Reports
4
+ class ReviewsByProductViewModel < ApplicationViewModel
5
+ def results
6
+ @results ||= model.results.map do |result|
7
+ product = products.detect { |p| p.id == result['_id'] }
8
+ OpenStruct.new(
9
+ { product: product }
10
+ .merge(result)
11
+ .merge(
12
+ average_rating: result['average_rating'].round(2),
13
+ weighted_average_rating: result['weighted_average_rating'].round(2)
14
+ )
15
+ )
16
+ end
17
+ end
18
+
19
+ def products
20
+ @products ||= Catalog::Product.any_in(
21
+ id: model.results.map { |r| r['_id'] }
22
+ ).to_a
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ module Workarea
2
+ module Admin
3
+ class ReviewViewModel < ApplicationViewModel
4
+ delegate :primary_image, to: :product, allow_nil: true
5
+
6
+ def name
7
+ if product.present?
8
+ t('workarea.admin.reviews.index.review_for', product: product.name)
9
+ else
10
+ t('workarea.admin.reviews.index.review')
11
+ end
12
+ end
13
+
14
+ def product
15
+ @product ||=
16
+ options[:product] ||
17
+ ProductViewModel.wrap(Catalog::Product.find(product_id))
18
+ rescue Mongoid::Errors::DocumentNotFound
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ module Workarea
2
+ module Admin
3
+ class ReviewsSearchViewModel < SearchViewModel
4
+ def results
5
+ @results ||= PagedArray.from(
6
+ persisted_results.map do |review|
7
+ ReviewViewModel.new(
8
+ review,
9
+ product: products.detect { |p| p.id.to_s == review.product_id.to_s }
10
+ )
11
+ end,
12
+ model.results.page,
13
+ model.results.per_page,
14
+ total
15
+ )
16
+ end
17
+
18
+ def sort
19
+ if options[:sort] == Sort.highest_rating.to_s
20
+ Sort.highest_rating.to_s
21
+ elsif options[:sort] == Sort.lowest_rating.to_s
22
+ Sort.lowest_rating.to_s
23
+ else
24
+ super
25
+ end
26
+ end
27
+
28
+ def sorts
29
+ super + [
30
+ Sort.highest_rating.to_a,
31
+ Sort.lowest_rating.to_a
32
+ ]
33
+ end
34
+
35
+ private
36
+
37
+ def products
38
+ @products ||= ProductViewModel.wrap(
39
+ Catalog::Product
40
+ .any_in(id: persisted_results.map(&:product_id))
41
+ .map { |product| Admin::ProductViewModel.new(product) }
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ module Workarea
2
+ decorate Storefront::ProductViewModel, with: :reviews do
3
+ def has_reviews?
4
+ total_reviews > 0
5
+ end
6
+
7
+ def reviews
8
+ @reviews ||= Review
9
+ .find_for_product(model.id)
10
+ .order(created_at: :desc)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ module Storefront
3
+ class ReviewViewModel < ApplicationViewModel
4
+ def requires_public_info?
5
+ anonymous? || user.public_info.blank?
6
+ end
7
+
8
+ def user
9
+ return if anonymous?
10
+ @user ||= User.find(user_id)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ .activity
2
+ .activity__header
3
+ .activity__avatar
4
+ = link_to_modifier(entry) do
5
+ = avatar_for entry.modifier
6
+ %h3.activity__name= link_to_modifier(entry)
7
+ %p.activity__time= activity_time(entry.created_at)
8
+ .activity__message
9
+ - if entry.audited.present?
10
+ = t('workarea.admin.activities.review_create_html', name: link_to(t('workarea.admin.activities.review'), edit_review_path(entry.audited)))
11
+ - else
12
+ = t('workarea.admin.activities.review_create_html', name: t('workarea.admin.activities.review'))
@@ -0,0 +1,10 @@
1
+ .activity
2
+ .activity__header
3
+ .activity__avatar
4
+ = link_to_modifier(entry) do
5
+ = avatar_for entry.modifier
6
+ %h3.activity__name= link_to_modifier(entry)
7
+ %p.activity__time= activity_time(entry.created_at)
8
+ .activity__message
9
+ = t('workarea.admin.activities.review_destroy_html', name: entry.model_attributes['title'])
10
+ = link_to_restore_for(entry)
@@ -0,0 +1,10 @@
1
+ .activity
2
+ .activity__header
3
+ .activity__avatar
4
+ = link_to_modifier(entry) do
5
+ = avatar_for entry.modifier
6
+ %h3.activity__name= link_to_modifier(entry)
7
+ %p.activity__time= activity_time(entry.created_at)
8
+ .activity__message
9
+ - name = entry.audited.blank? ? entry.model_attributes['title'] : link_to(entry.model_attributes['title'], edit_review_path(entry.audited))
10
+ = t('workarea.admin.activities.review_update_html', fields: fields_clause_for(entry.tracked_changes), name: name)
@@ -0,0 +1,17 @@
1
+ .grid__cell
2
+ .card{ class: card_classes(:reviews_by_product_report, local_assigns[:active]) }
3
+ = link_to reviews_by_product_report_path, class: 'card__header' do
4
+ %span.card__header-text= t('workarea.admin.reports.reviews_by_product.title')
5
+ = inline_svg 'workarea/admin/icons/insights.svg', class: 'card__icon'
6
+
7
+ .card__body
8
+ .card__centered-content
9
+ %table
10
+ %tbody
11
+ - @dashboard.reviews_by_product.results.take(4).each do |result|
12
+ %tr
13
+ %td= result.product.present? ? result.product.name : result._id
14
+ %td.align-right= number_with_delimiter result.reviews
15
+
16
+ = link_to reviews_by_product_report_path, class: 'card__button' do
17
+ %span.button.button--small= t('workarea.admin.dashboards.reports.view_full_report')
@@ -0,0 +1,22 @@
1
+ .insight
2
+ .insight__date
3
+ %span.insight__period= insight.reporting_on.strftime('%B %Y')
4
+ .insight__heading= t('workarea.admin.insights.most_active_reviewers.title')
5
+ .insight__body
6
+ %p.insight__note= t('workarea.admin.insights.most_active_reviewers.info')
7
+ %table
8
+ %thead
9
+ %tr
10
+ %th.align-center= t('workarea.admin.insights.most_active_reviewers.user')
11
+ %th.align-center= t('workarea.admin.insights.most_active_reviewers.reviews')
12
+ %th.align-center= t('workarea.admin.insights.most_active_reviewers.verified')
13
+ %tbody
14
+ - insight.results.each do |result|
15
+ %tr
16
+ %td.align-center
17
+ - if result.user.present?
18
+ = link_to result.user.name, user_path(result.user)
19
+ - else
20
+ = result.email
21
+ %td.align-center= number_with_delimiter result.reviews
22
+ %td.align-center= number_with_delimiter result.verified
@@ -0,0 +1,22 @@
1
+ .insight
2
+ .insight__date
3
+ %span.insight__period= insight.reporting_on.strftime('%B %Y')
4
+ .insight__heading= t('workarea.admin.insights.most_reviewed_products.title')
5
+ .insight__body
6
+ %p.insight__note= t('workarea.admin.insights.most_reviewed_products.info')
7
+ .grid.grid--large.grid--center
8
+ - insight.results.each do |result|
9
+ .grid__cell.grid__cell--50.grid__cell--25-at-wide.align-center
10
+ .insight__product
11
+ - if result.product.blank?
12
+ = image_tag(product_image_url(Workarea::Catalog::ProductPlaceholderImage.cached, :small), alt: result.product_id, class: 'insight__product-image')
13
+ - else
14
+ = link_to catalog_product_path(result.product) do
15
+ = image_tag(product_image_url(result.product.primary_image, :small), alt: result.product.name, class: 'insight__product-image')
16
+ .insight__product-name
17
+ - if result.product.blank?
18
+ = result.product_id
19
+ - else
20
+ = link_to result.product.name, catalog_product_path(result.product)
21
+ .insight__product-info
22
+ %strong= t('workarea.admin.insights.most_reviewed_products.reviews', count: result.reviews)
@@ -0,0 +1,22 @@
1
+ .insight
2
+ .insight__date
3
+ %span.insight__period= insight.reporting_on.strftime('%B %Y')
4
+ .insight__heading= t('workarea.admin.insights.top_rated_products.title')
5
+ .insight__body
6
+ %p.insight__note= t('workarea.admin.insights.top_rated_products.info')
7
+ .grid.grid--large.grid--center
8
+ - insight.results.each do |result|
9
+ .grid__cell.grid__cell--50.grid__cell--25-at-wide.align-center
10
+ .insight__product
11
+ - if result.product.blank?
12
+ = image_tag(product_image_url(Workarea::Catalog::ProductPlaceholderImage.cached, :small), alt: result.product_id, class: 'insight__product-image')
13
+ - else
14
+ = link_to catalog_product_path(result.product) do
15
+ = image_tag(product_image_url(result.product.primary_image, :small), alt: result.product.name, class: 'insight__product-image')
16
+ .insight__product-name
17
+ - if result.product.blank?
18
+ = result.product_id
19
+ - else
20
+ = link_to result.product.name, catalog_product_path(result.product)
21
+ .insight__product-info
22
+ %strong= t('workarea.admin.insights.top_rated_products.rating', rating: number_with_delimiter(result.weighted_average_rating.round(2)))
@@ -0,0 +1,44 @@
1
+ - @page_title = t('workarea.admin.reports.reviews_by_product.title')
2
+
3
+ .view
4
+ .view__header
5
+ .view__heading
6
+ = link_to "↑ #{t('workarea.admin.reports.all_reports')}", reports_dashboards_path
7
+ %h1.heading.heading--no-margin= t('workarea.admin.reports.reviews_by_product.title')
8
+ %p= t('workarea.admin.reports.reference_link_html', path: reference_report_path)
9
+
10
+ .view__container.view__container--narrow
11
+ .browsing-controls.browsing-controls--with-divider.browsing-controls--center.browsing-controls--filters-displayed
12
+ = form_tag reviews_by_product_report_path, method: 'get', class: 'browsing-controls__form' do
13
+ = render 'workarea/admin/shared/date_selector', starts_at: @report.starts_at, ends_at: @report.ends_at
14
+
15
+ .browsing-controls__filter
16
+ .property.property--inline
17
+ = label_tag 'results_filter', t('workarea.admin.reports.reviews_by_product.results_filter'), class: 'property__name'
18
+ = select_tag 'results_filter', options_for_select(reviews_report_filter_options, params[:results_filter]), data: { form_submitting_control: '' }
19
+
20
+
21
+ .browsing-controls__count
22
+ = render_reports_results_message(@report)
23
+ = render 'workarea/admin/reports/export', report: @report
24
+
25
+ %table
26
+ %thead
27
+ %tr
28
+ %th= t('workarea.admin.fields.product')
29
+ %th.align-center= link_to_reports_sorting t('workarea.admin.fields.reviews'), report: @report, sort_by: 'reviews'
30
+ %th.align-center= link_to_reports_sorting t('workarea.admin.fields.verified_reviews'), report: @report, sort_by: 'verified'
31
+ %th.align-center= link_to_reports_sorting t('workarea.admin.fields.average_rating'), report: @report, sort_by: 'average_rating'
32
+ %th.align-center= link_to_reports_sorting t('workarea.admin.fields.weighted_average_rating'), report: @report, sort_by: 'weighted_average_rating'
33
+ %tbody
34
+ - @report.results.each do |result|
35
+ %tr
36
+ %td
37
+ - if result.product.present?
38
+ = link_to result.product.name, catalog_product_path(result.product)
39
+ - else
40
+ = result._id
41
+ %td.align-center= number_with_delimiter result.reviews
42
+ %td.align-center= number_with_delimiter result.verified
43
+ %td.align-center= number_with_delimiter result.average_rating
44
+ %td.align-center= number_with_delimiter result.weighted_average_rating
@@ -0,0 +1,5 @@
1
+ .grid.grid--auto.grid--right.grid--middle
2
+ - if model.product.present?
3
+ .grid__cell= link_to t('workarea.admin.reviews.edit.view_product'), catalog_product_path(model.product)
4
+ - unless model.anonymous?
5
+ .grid__cell= link_to t('workarea.admin.reviews.edit.view_user'), user_path(model.user_id)
@@ -0,0 +1,5 @@
1
+ .grid__cell
2
+ = link_to reviews_path(q: %{"#{model.id}"}, sort: 'newest') do
3
+ = t('workarea.admin.catalog_products.reviews_link')
4
+ - if model.pending_reviews_count > 0
5
+ = t('workarea.admin.catalog_products.pending', pending: model.pending_reviews_count)
@@ -0,0 +1 @@
1
+ %li= link_to t('workarea.admin.dashboards.marketing.reviews'), reviews_path, class: 'dashboard__navigation-link'
@@ -0,0 +1,3 @@
1
+ %li{ class: "primary-nav__item" }
2
+ = link_to reviews_path, class: navigation_link_classes(reviews_path) do
3
+ = t('workarea.admin.reviews.menu.product_reviews', count: Workarea::Review.pending.count)
@@ -0,0 +1,12 @@
1
+ = link_to edit_review_path(model), class: 'summary', data: { global_id: model.to_global_id.to_param } do
2
+ .summary__image-container
3
+ = image_tag(product_image_url(model.primary_image, :medium), alt: model.name, class: 'summary__image') if model.primary_image.present?
4
+ %span.summary__name= model.name
5
+ .summary__info-container
6
+ %span.summary__info= local_time_ago(model.updated_at)
7
+ %span.summary__info
8
+ - if model.approved
9
+ = t('workarea.admin.reviews.approved')
10
+ - else
11
+ = t('workarea.admin.reviews.pending')
12
+ %span.summary__type= t('workarea.admin.reviews.summary.type')
@@ -0,0 +1,77 @@
1
+ - @page_title = @review.name
2
+
3
+ .view
4
+ .view__header
5
+ .grid.grid--middle.grid--right
6
+ .grid__cell.grid__cell--50
7
+ .view__heading
8
+ = link_to_index_for(@review)
9
+ %h1= @review.name
10
+ .grid__cell.grid__cell--25
11
+ = render_aux_navigation_for(@review)
12
+
13
+ .view__container.view__container--narrow
14
+ - @review.errors.full_messages.each do |message|
15
+ = render_message 'error', message
16
+
17
+ = form_tag review_path(@review), method: :patch, id: 'sku_form' do
18
+ .section
19
+ .grid.grid--huge.grid--middle
20
+ .grid__cell.grid__cell--50-at-medium
21
+ .property
22
+ = label_tag 'review_title', t('workarea.admin.fields.title'), class: 'property__name'
23
+ = text_field_tag 'review[title]', @review.title, class: 'text-box'
24
+
25
+ .grid__cell.grid__cell--50-at-medium
26
+ .grid.grid--right.grid--auto
27
+ .grid__cell
28
+ .property
29
+ %span.property__name= t('workarea.admin.reviews.approved')
30
+ = toggle_button_for 'review[approved]', @review.approved
31
+
32
+ .property
33
+ = label_tag 'review_body', t('workarea.admin.fields.body'), class: 'property__name'
34
+ = text_area_tag 'review[body]', @review.body, class: 'text-box text-box--multi-line'
35
+
36
+ .grid.grid--huge
37
+ .grid__cell.grid__cell--50.grid__cell--25-at-medium
38
+ .property
39
+ = label_tag 'review_rating', t('workarea.admin.fields.rating'), class: 'property__name'
40
+ = @review.rating
41
+ .grid__cell.grid__cell--50.grid__cell--25-at-medium
42
+ .property
43
+ = label_tag 'verified', t('workarea.admin.fields.verified'), class: 'property__name'
44
+ = t("workarea.admin.#{@review.verified?}")
45
+ .grid__cell.grid__cell--50.grid__cell--25-at-medium
46
+ .property
47
+ = label_tag 'review_updated_at', t('workarea.admin.fields.updated_at'), class: 'property__name'
48
+ = local_time(@review.updated_at)
49
+ .grid__cell.grid__cell--50.grid__cell--25-at-medium
50
+ .property
51
+ = label_tag 'review_created_at', t('workarea.admin.fields.created_at'), class: 'property__name'
52
+ = local_time(@review.created_at)
53
+
54
+ .grid__cell.grid__cell--50.grid__cell--25-at-medium
55
+ .property
56
+ = label_tag 'review_product_id', t('workarea.admin.fields.product_id'), class: 'property__name'
57
+ - if @review.product.nil?
58
+ = @review.product_id
59
+ - else
60
+ = link_to @review.product_id, catalog_product_path(@review.product)
61
+ - if @review.anonymous?
62
+ .grid__cell.grid__cell--50.grid__cell--25-at-medium
63
+ .property
64
+ = label_tag 'review_name', t('workarea.admin.fields.name'), class: 'property__name'
65
+ = [@review.first_name, @review.last_name].join(' ')
66
+ .grid__cell.grid__cell--50.grid__cell--25-at-medium
67
+ .property
68
+ = label_tag 'review_email', t('workarea.admin.fields.email'), class: 'property__name'
69
+ = @review.email.presence || '--'
70
+
71
+
72
+ .workflow-bar
73
+ .grid.grid--middle
74
+ .grid__cell.grid__cell--50
75
+ = link_to t('workarea.admin.actions.delete'), review_path(@review), data: { method: 'delete', confirm: t('workarea.admin.actions.delete_confirmation')}, class: 'workflow-bar__button workflow-bar__button--delete'
76
+ .grid__cell.grid__cell--50.align-right
77
+ .grid__cell= button_tag t('workarea.admin.reviews.edit.save_review'), value: 'save_review', class: 'workflow-bar__button workflow-bar__button--update'
@@ -0,0 +1,74 @@
1
+ - @page_title = t('workarea.admin.reviews.index.page_title')
2
+
3
+ .view
4
+ .view__header
5
+ .grid.grid--middle.grid--center
6
+ .grid__cell.grid__cell--50
7
+ .view__heading
8
+ = link_to "↑ #{t('workarea.admin.reviews.index.dashboard_link')}", marketing_dashboards_path, class: 'view__dashboard-button'
9
+ %h1= t('workarea.admin.reviews.index.heading')
10
+
11
+ .view__container
12
+ .browsing-controls.browsing-controls--with-divider.browsing-controls--center{ class: ('browsing-controls--filters-displayed' unless @search.toggle_facets?) }
13
+ = form_tag reviews_path, method: 'get', id: 'review_sort_form' do
14
+ = facet_hidden_inputs(@search.facets)
15
+ .browsing-controls__sort
16
+ .property.property--inline
17
+ = label_tag 'sort', t('workarea.admin.search.sort_by'), class: 'property__name'
18
+ = select_tag :sort, options_for_select(@search.sorts, selected: @search.sort), data: { form_submitting_control: '' }
19
+
20
+ .browsing-controls__search
21
+ .search-form
22
+ = text_field_tag :q, params[:q], class: 'search-form__input', id: 'search_products', title: t('workarea.admin.search.keywords'), placeholder: t('workarea.admin.search.keywords')
23
+ = submit_tag 'search_orders', class: 'search-form__button'
24
+
25
+ = render 'workarea/admin/shared/creation_date', search: @search, form_path: reviews_path
26
+
27
+ - if @search.facets.present?
28
+ - @search.facets.each do |facet|
29
+ = render "workarea/admin/facets/#{facet.type}", facet: facet
30
+
31
+ - if @search.toggle_facets?
32
+ .browsing-controls__toggle-filters
33
+ %button.text-button{ type: 'button', data: { toggle_filters: '' } }= t('workarea.admin.search.show_filters')
34
+
35
+ = render 'workarea/admin/facets/applied', search: @search, reset_path: reviews_path
36
+
37
+ %p.browsing-controls__count= pluralize(@search.total, 'Reviews')
38
+
39
+ - if @search.results.any?
40
+ %table.index-table
41
+ %thead
42
+ %tr
43
+ %th.index-table__control-cell
44
+ .checkbox
45
+ = check_box_tag 'select_all', nil, false, id: 'select_all', class: 'checkbox__input', data: { bulk_action_select_all: '' }
46
+ = label_tag 'select_all', t('workarea.admin.bulk_actions.select_all'), class: 'checkbox__label'
47
+ %th= t('workarea.admin.fields.name')
48
+ %th= t('workarea.admin.fields.title')
49
+ %th.align-center= t('workarea.admin.fields.rating')
50
+ %th.align-center= t('workarea.admin.fields.approved')
51
+ %th.align-center= t('workarea.admin.fields.verified')
52
+ %th= t('workarea.admin.fields.created_at')
53
+
54
+ %tbody
55
+ - @search.results.each do |result|
56
+ %tr.index-table__row
57
+ %td.index-table__control-cell
58
+ .checkbox
59
+ = check_box_tag 'global_id', result.to_gid_param, false, class: 'checkbox__input', id: dom_id(result), data: { bulk_action_item: '' }
60
+ = label_tag dom_id(result), '', class: 'checkbox__label', title: t('workarea.admin.bulk_actions.add_summary_button')
61
+ %td= link_to result.name, edit_review_path(result)
62
+ %td= result.title
63
+ %td.align-center= result.rating
64
+ %td.align-center= t("workarea.admin.#{result.approved}")
65
+ %td.align-center= t("workarea.admin.#{result.verified}")
66
+ %td= local_time_ago(result.created_at)
67
+
68
+ - if @search.results.total_pages > 1
69
+ = render 'workarea/admin/shared/pagination', collection: @search.results
70
+
71
+ .workflow-bar
72
+ .grid
73
+ .grid__cell.grid__cell--50
74
+ = render 'workarea/admin/shared/bulk_actions', klass: Workarea::Review, search: @search