workarea-reviews 3.0.8 → 3.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|