workarea-reviews 3.0.8 → 3.1.2
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 +4 -4
- data/.eslintrc.json +35 -0
- data/.github/workflows/ci.yml +60 -0
- data/.gitignore +1 -2
- data/.rubocop.yml +3 -0
- data/.stylelintrc.json +8 -0
- data/CHANGELOG.md +24 -12
- data/Gemfile +4 -2
- data/Rakefile +4 -5
- data/app/controllers/workarea/admin/reports_controller.decorator +10 -0
- data/app/helpers/workarea/admin/reviews_helper.rb +6 -5
- data/app/helpers/workarea/storefront/reviews_helper.rb +1 -3
- data/app/helpers/workarea/storefront/reviews_schema_org_helper.rb +34 -0
- data/app/mailers/workarea/admin/status_report_mailer.decorator +2 -2
- data/app/models/workarea/insights/most_active_reviewers.rb +34 -0
- data/app/models/workarea/insights/most_reviewed_products.rb +33 -0
- data/app/models/workarea/insights/top_rated_products.rb +33 -0
- data/app/models/workarea/review.rb +5 -16
- data/app/queries/workarea/reports/reviews_by_product.rb +86 -0
- data/app/queries/workarea/reports/reviews_by_user.rb +71 -0
- data/app/seeds/{reviews.rb → workarea/review_seeds.rb} +17 -6
- data/app/view_models/workarea/admin/dashboards/reports_view_model.decorator +11 -0
- data/app/view_models/workarea/admin/reports/reviews_by_product_view_model.rb +27 -0
- data/app/view_models/workarea/storefront/review_view_model.rb +9 -3
- data/app/views/workarea/admin/dashboards/_reviews_by_product_card.html.haml +17 -0
- data/app/views/workarea/admin/insights/_most_active_reviewers.html.haml +22 -0
- data/app/views/workarea/admin/insights/_most_reviewed_products.html.haml +22 -0
- data/app/views/workarea/admin/insights/_top_rated_products.html.haml +22 -0
- data/app/views/workarea/admin/reports/reviews_by_product.html.haml +44 -0
- data/app/views/workarea/storefront/products/_rating.html.haml +1 -2
- data/app/views/workarea/storefront/products/_reviews.html.haml +5 -5
- data/app/views/workarea/storefront/products/_reviews_aggregate.html.haml +2 -2
- data/app/views/workarea/storefront/review_mailer/review_request.html.haml +2 -0
- data/app/views/workarea/storefront/review_requests/show.html.haml +2 -1
- data/config/initializers/append_points.rb +5 -0
- data/config/initializers/configuration.rb +3 -1
- data/config/initializers/scheduled_jobs.rb +8 -6
- data/config/locales/en.yml +46 -0
- data/config/routes.rb +4 -0
- data/lib/workarea/reviews/engine.rb +4 -0
- data/lib/workarea/reviews/version.rb +1 -1
- data/package.json +9 -0
- data/test/dummy/config/initializers/session_store.rb +3 -1
- data/test/helpers/workarea/storefront/reviews_helper_test.rb +1 -1
- data/test/integration/workarea/admin/reviews_integration_test.rb +5 -1
- data/test/models/workarea/insights/most_active_reviewers_test.rb +32 -0
- data/test/models/workarea/insights/most_reviewed_products_test.rb +32 -0
- data/test/models/workarea/insights/top_rated_products_test.rb +49 -0
- data/test/models/workarea/review_test.rb +29 -18
- data/test/queries/workarea/reports/reviews_by_product_test.rb +104 -0
- data/test/queries/workarea/reports/reviews_by_user_test.rb +102 -0
- data/test/system/workarea/admin/reviews_by_product_system_test.rb +60 -0
- data/test/view_models/workarea/storefront/review_view_model_test.rb +46 -0
- data/workarea-reviews.gemspec +1 -1
- data/yarn.lock +3265 -0
- metadata +33 -8
- data/app/controllers/workarea/admin/import_reviews_controller.rb +0 -35
- data/test/helpers/workarea/admin/reviews_helper_test.rb +0 -17
@@ -0,0 +1,71 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Reports
|
3
|
+
class ReviewsByUser
|
4
|
+
include Report
|
5
|
+
|
6
|
+
self.reporting_class = Review
|
7
|
+
self.sort_fields = %w(reviews verified average_rating activity_score)
|
8
|
+
|
9
|
+
def aggregation
|
10
|
+
[filter_results, project_used_fields, group_by_email, project_fields]
|
11
|
+
end
|
12
|
+
|
13
|
+
def filter_results
|
14
|
+
{
|
15
|
+
'$match' => {
|
16
|
+
'created_at' => { '$gte' => starts_at, '$lte' => ends_at },
|
17
|
+
**approval_query
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def project_used_fields
|
23
|
+
{
|
24
|
+
'$project' => {
|
25
|
+
'email' => 1,
|
26
|
+
'user_id' => 1,
|
27
|
+
'rating' => 1,
|
28
|
+
'verified' => 1
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def group_by_email
|
34
|
+
{
|
35
|
+
'$group' => {
|
36
|
+
'_id' => '$email',
|
37
|
+
'user_id' => { '$max' => '$user_id' },
|
38
|
+
'reviews' => { '$sum' => 1 },
|
39
|
+
'verified' => { '$sum' => { '$cond' => { 'if' => '$verified', 'then' => 1, 'else' => 0 } } },
|
40
|
+
'rating_tally' => { '$sum' => '$rating' }
|
41
|
+
}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def project_fields
|
46
|
+
{
|
47
|
+
'$project' => {
|
48
|
+
'email' => 1,
|
49
|
+
'user_id' => 1,
|
50
|
+
'reviews' => 1,
|
51
|
+
'verified' => 1,
|
52
|
+
'average_rating' => { '$divide' => ['$rating_tally', '$reviews'] },
|
53
|
+
'activity_score' => { '$sum' => ['$reviews', { '$multiply' => ['$verified', 0.75] }] }
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def approval_query
|
61
|
+
if params[:results_filter] == 'approved'
|
62
|
+
{ approved: true }
|
63
|
+
elsif params[:results_filter] == 'unapproved'
|
64
|
+
{ approved: false }
|
65
|
+
else
|
66
|
+
{}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -3,17 +3,26 @@ module Workarea
|
|
3
3
|
def perform
|
4
4
|
puts 'Adding reviews...'
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
Sidekiq::Callbacks.disable do
|
7
|
+
create_reviews_for_catalog
|
8
|
+
create_review_request_email_content
|
8
9
|
end
|
9
|
-
|
10
|
-
create_review_request_email_content
|
11
10
|
end
|
12
11
|
|
13
12
|
private
|
14
13
|
|
14
|
+
def create_reviews_for_catalog
|
15
|
+
Workarea::Catalog::Product.all.each_by(100) do |product|
|
16
|
+
reviews = Array.new(rand(10)) { create_review(product) }
|
17
|
+
next unless reviews.size > 0
|
18
|
+
|
19
|
+
Workarea::Review.collection.insert_many(reviews.map(&:as_document))
|
20
|
+
UpdateProductReviewData.perform_async(product.id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
15
24
|
def create_review(product)
|
16
|
-
Workarea::Review.
|
25
|
+
Workarea::Review.new(
|
17
26
|
product_id: product.id,
|
18
27
|
user_id: BSON::ObjectId.new,
|
19
28
|
rating: rand(5) + 1,
|
@@ -21,7 +30,9 @@ module Workarea
|
|
21
30
|
body: Faker::Lorem.paragraph,
|
22
31
|
approved: [true, false].sample,
|
23
32
|
user_info: Faker::Internet.user_name,
|
24
|
-
verified: [true, false].sample
|
33
|
+
verified: [true, false].sample,
|
34
|
+
created_at: rand(45).days.ago,
|
35
|
+
updated_at: Time.current
|
25
36
|
)
|
26
37
|
end
|
27
38
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Admin::Dashboards::ReportsViewModel, with: :reviews do
|
3
|
+
def reviews_by_product
|
4
|
+
@reviews_by_product ||=
|
5
|
+
Admin::Reports::ReviewsByProductViewModel.wrap(
|
6
|
+
Workarea::Reports::ReviewsByProduct.new(options),
|
7
|
+
options
|
8
|
+
)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -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
|
@@ -2,12 +2,18 @@ module Workarea
|
|
2
2
|
module Storefront
|
3
3
|
class ReviewViewModel < ApplicationViewModel
|
4
4
|
def requires_public_info?
|
5
|
-
anonymous? || user
|
5
|
+
anonymous? || user&.public_info.blank?
|
6
|
+
end
|
7
|
+
|
8
|
+
def anonymous?
|
9
|
+
model.anonymous? || user.nil?
|
6
10
|
end
|
7
11
|
|
8
12
|
def user
|
9
|
-
return if anonymous?
|
10
|
-
@user
|
13
|
+
return if model.anonymous?
|
14
|
+
return @user if defined?(@user)
|
15
|
+
|
16
|
+
@user = User.find(user_id) rescue nil
|
11
17
|
end
|
12
18
|
end
|
13
19
|
end
|
@@ -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
|
@@ -1,4 +1,4 @@
|
|
1
|
-
%p.rating{ title: "#{rating.round(2)} #{t('workarea.storefront.reviews.out_of')} #{t('workarea.storefront.reviews.stars', count: 5)}"
|
1
|
+
%p.rating{ title: "#{rating.round(2)} #{t('workarea.storefront.reviews.out_of')} #{t('workarea.storefront.reviews.stars', count: 5)}" }
|
2
2
|
- full_star_count.times do
|
3
3
|
= inline_svg 'workarea/storefront/icons/star.svg', class: 'rating__star'
|
4
4
|
- if half_star_size > 0
|
@@ -6,5 +6,4 @@
|
|
6
6
|
- empty_star_count.times do
|
7
7
|
= inline_svg 'workarea/storefront/icons/empty_star.svg', class: 'rating__star'
|
8
8
|
%span.rating__text.visually-hidden
|
9
|
-
%meta{ itemprop: 'ratingValue', content: rating.round(2) }
|
10
9
|
#{rating.round(2)} #{t('workarea.storefront.reviews.out_of')} #{t('workarea.storefront.reviews.stars', count: 5)}
|
@@ -10,14 +10,14 @@
|
|
10
10
|
|
11
11
|
%ol.reviews__review-group
|
12
12
|
- product.reviews.each do |review|
|
13
|
-
%li.reviews__review{
|
13
|
+
%li.reviews__review{ data: { product_review_section_entry: { rating: review.rating.to_f, createdAt: review.created_at.to_i }.to_json } }
|
14
14
|
= rating_stars(review.rating)
|
15
15
|
|
16
|
-
%h3.reviews__review-title
|
17
|
-
%p.reviews__review-body
|
16
|
+
%h3.reviews__review-title= review.title
|
17
|
+
%p.reviews__review-body= review.body
|
18
18
|
.reviews__review-meta
|
19
|
-
%p.reviews__review-author
|
20
|
-
%span
|
19
|
+
%p.reviews__review-author
|
20
|
+
%span= review.user_info
|
21
21
|
- if review.verified?
|
22
22
|
%p.reviews__review-verified= t('workarea.storefront.reviews.verified_purchaser')
|
23
23
|
%p.reviews__review-date= local_time(review.created_at, format: :long, itemprop: 'datePublished')
|
@@ -1,5 +1,5 @@
|
|
1
1
|
- if product.has_reviews?
|
2
|
-
.reviews-aggregate
|
2
|
+
.reviews-aggregate
|
3
3
|
= link_to "#{product_path(product, product.browse_link_options)}#reviews", data: { scroll_to_button: '' }, class: 'reviews-aggregate__rating-link' do
|
4
4
|
= rating_stars(product.average_rating, aggregate: true)
|
5
5
|
|
@@ -7,7 +7,7 @@
|
|
7
7
|
%span.reviews-aggregate__count
|
8
8
|
%span.reviews-aggregate__read= t('workarea.storefront.reviews.read_reviews')
|
9
9
|
= surround '(', ')' do
|
10
|
-
%span
|
10
|
+
%span= product.total_reviews
|
11
11
|
|
12
12
|
= link_to t('workarea.storefront.reviews.write_a_review'), new_product_review_path(product), class: 'reviews-aggregate__write-action', data: { dialog_button: '' }
|
13
13
|
- if display_purchase_requirement_message
|
@@ -5,7 +5,8 @@
|
|
5
5
|
|
6
6
|
.grid
|
7
7
|
.grid__cell.grid__cell--25
|
8
|
-
.product-summary
|
8
|
+
.product-summary
|
9
|
+
= render_schema_org(product_schema(@product))
|
9
10
|
= render 'workarea/storefront/products/summary', product: @product
|
10
11
|
|
11
12
|
.grid__cell.grid__cell--75
|
@@ -1,5 +1,5 @@
|
|
1
1
|
Workarea.configure do |config|
|
2
|
-
config.seeds
|
2
|
+
config.seeds.insert('Workarea::InsightsSeeds', 'Workarea::ReviewSeeds')
|
3
3
|
|
4
4
|
config.jump_to_navigation.merge!('Product Reviews' => :reviews_path)
|
5
5
|
|
@@ -11,6 +11,8 @@ Workarea.configure do |config|
|
|
11
11
|
|
12
12
|
config.data_file_ignored_fields << %w(total_reviews average_rating)
|
13
13
|
|
14
|
+
config.insights_model_classes << 'Workarea::User'
|
15
|
+
|
14
16
|
# The amount of time before a Review::Request will auto expire
|
15
17
|
# and be removed from the collection
|
16
18
|
config.review_request_ttl = 6.months
|
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
unless Workarea.config.skip_service_connections
|
2
|
+
Sidekiq::Cron::Job.create(
|
3
|
+
name: 'Workarea::SendReviewRequests',
|
4
|
+
klass: 'Workarea::SendReviewRequests',
|
5
|
+
cron: "0 0 * * * #{Time.zone.tzinfo.identifier}",
|
6
|
+
queue: 'low'
|
7
|
+
)
|
8
|
+
end
|
data/config/locales/en.yml
CHANGED
@@ -15,12 +15,55 @@ en:
|
|
15
15
|
marketing:
|
16
16
|
reviews: Product reviews
|
17
17
|
fields:
|
18
|
+
average_rating: Average Rating
|
18
19
|
body: Body
|
19
20
|
title: Title
|
20
21
|
rating: Rating
|
22
|
+
reviews: Reviews
|
21
23
|
approved: Approved
|
22
24
|
auto_approve: Approve All Reviews
|
23
25
|
verified: Verified Purchaser
|
26
|
+
verified_reviews: Verified
|
27
|
+
weighted_average_rating: Weighted Average Rating
|
28
|
+
insights:
|
29
|
+
most_active_reviewers:
|
30
|
+
info: Your customers that are submitting the most reviews.
|
31
|
+
reviews: Reviews
|
32
|
+
title: Most Active Reviewers
|
33
|
+
user: User
|
34
|
+
verified: Verified Reviews
|
35
|
+
most_reviewed_products:
|
36
|
+
title: Most Reviewed Products
|
37
|
+
info: Your products that have received the most reviews.
|
38
|
+
reviews:
|
39
|
+
one: '%{count} Review'
|
40
|
+
other: '%{count} Reviews'
|
41
|
+
top_rated_products:
|
42
|
+
title: Top Rated Products
|
43
|
+
info: Your products with the highest weighted average rating.
|
44
|
+
rating: '%{rating} Rating'
|
45
|
+
reports:
|
46
|
+
reference:
|
47
|
+
terms:
|
48
|
+
average_rating:
|
49
|
+
name: Average Rating
|
50
|
+
description: The sum of all review ratings divided by the total number of reviews.
|
51
|
+
reviews:
|
52
|
+
name: Reviews
|
53
|
+
description: The total number of reviews.
|
54
|
+
verified:
|
55
|
+
name: Verified
|
56
|
+
description: The total number of reviews made by customers who have purchased the product.
|
57
|
+
weighted_average_rating:
|
58
|
+
name: Weighted Average Rating
|
59
|
+
description: A base rating of 3.0, adjusted up or down by each review rating.
|
60
|
+
reviews_by_product:
|
61
|
+
filters:
|
62
|
+
all: All Reviews
|
63
|
+
approved: Approved Reviews
|
64
|
+
unapproved: Unapproved Reviews
|
65
|
+
results_filter: Results Filter
|
66
|
+
title: Reviews By Product
|
24
67
|
reviews:
|
25
68
|
approved: Approved
|
26
69
|
catalog_products_cards:
|
@@ -66,6 +109,9 @@ en:
|
|
66
109
|
review_request:
|
67
110
|
subject: Review your recent purchase of %{product}
|
68
111
|
link: Write a review
|
112
|
+
email_action:
|
113
|
+
name: Write Review
|
114
|
+
description: Please review your recent purchase
|
69
115
|
fields:
|
70
116
|
username: Username
|
71
117
|
review_requests:
|