workarea-reviews 3.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +20 -0
- data/.eslintignore +2 -0
- data/.eslintrc +24 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.gitignore +16 -0
- data/.scss-lint.yml +188 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +763 -0
- data/CODE_OF_CONDUCT.md +3 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +6 -0
- data/LICENSE +52 -0
- data/README.md +107 -0
- data/Rakefile +54 -0
- data/app/assets/images/workarea/admin/icons/star.svg +1 -0
- data/app/assets/images/workarea/storefront/icons/empty_star.svg +1 -0
- data/app/assets/images/workarea/storefront/icons/half_star.svg +1 -0
- data/app/assets/images/workarea/storefront/icons/star.svg +1 -0
- data/app/assets/javascripts/workarea/storefront/reviews/modules/product_review_ajax_submit.js +39 -0
- data/app/assets/javascripts/workarea/storefront/reviews/modules/product_reviews_sort_menus.js +82 -0
- data/app/assets/javascripts/workarea/storefront/reviews/modules/rating_buttons.js +103 -0
- data/app/assets/javascripts/workarea/storefront/reviews/templates/sort_by_property.jst.ejs +11 -0
- data/app/assets/stylesheets/workarea/storefront/reviews/components/_rating.scss +28 -0
- data/app/assets/stylesheets/workarea/storefront/reviews/components/_reviews.scss +59 -0
- data/app/assets/stylesheets/workarea/storefront/reviews/components/_reviews_aggregate.scss +38 -0
- data/app/assets/stylesheets/workarea/storefront/reviews/components/_write_review.scss +63 -0
- data/app/controllers/workarea/admin/catalog_products_controller.decorator +9 -0
- data/app/controllers/workarea/admin/import_reviews_controller.rb +35 -0
- data/app/controllers/workarea/admin/reviews_controller.rb +51 -0
- data/app/controllers/workarea/storefront/review_requests_controller.rb +50 -0
- data/app/controllers/workarea/storefront/reviews_controller.rb +53 -0
- data/app/helpers/workarea/admin/reviews_helper.rb +12 -0
- data/app/helpers/workarea/storefront/reviews_helper.rb +24 -0
- data/app/mailers/workarea/admin/status_report_mailer.decorator +8 -0
- data/app/mailers/workarea/storefront/review_mailer.rb +23 -0
- data/app/models/workarea/catalog/product.decorator +15 -0
- data/app/models/workarea/fulfillment.decorator +11 -0
- data/app/models/workarea/review.rb +135 -0
- data/app/models/workarea/review/request.rb +62 -0
- data/app/models/workarea/search/admin/review.rb +72 -0
- data/app/models/workarea/search/storefront/product.decorator +9 -0
- data/app/models/workarea/sort.decorator +17 -0
- data/app/queries/workarea/review_request_params.rb +47 -0
- data/app/queries/workarea/review_summary.rb +11 -0
- data/app/queries/workarea/search/admin_reviews.rb +40 -0
- data/app/queries/workarea/search/category_browse.decorator +9 -0
- data/app/queries/workarea/search/product_search.decorator +9 -0
- data/app/seeds/review_seeds.rb +49 -0
- data/app/services/workarea/create_review.rb +99 -0
- data/app/view_models/workarea/admin/product_view_model.decorator +7 -0
- data/app/view_models/workarea/admin/review_view_model.rb +23 -0
- data/app/view_models/workarea/admin/reviews_search_view_model.rb +46 -0
- data/app/view_models/workarea/storefront/product_view_model.decorator +13 -0
- data/app/view_models/workarea/storefront/review_view_model.rb +14 -0
- data/app/views/workarea/admin/activities/_review_create.html.haml +12 -0
- data/app/views/workarea/admin/activities/_review_destroy.html.haml +10 -0
- data/app/views/workarea/admin/activities/_review_update.html.haml +10 -0
- data/app/views/workarea/admin/reviews/_aux_navigation.html.haml +5 -0
- data/app/views/workarea/admin/reviews/_catalog_products_aux_link.html.haml +5 -0
- data/app/views/workarea/admin/reviews/_dashboard_navigation.html.haml +1 -0
- data/app/views/workarea/admin/reviews/_menu.html.haml +3 -0
- data/app/views/workarea/admin/reviews/_summary.html.haml +12 -0
- data/app/views/workarea/admin/reviews/edit.html.haml +77 -0
- data/app/views/workarea/admin/reviews/index.html.haml +74 -0
- data/app/views/workarea/admin/status_report_mailer/_reviews.html.haml +5 -0
- data/app/views/workarea/storefront/products/_rating.html.haml +10 -0
- data/app/views/workarea/storefront/products/_reviews.html.haml +23 -0
- data/app/views/workarea/storefront/products/_reviews_aggregate.html.haml +22 -0
- data/app/views/workarea/storefront/products/_reviews_summary.html.haml +2 -0
- data/app/views/workarea/storefront/review_mailer/review_request.html.haml +22 -0
- data/app/views/workarea/storefront/review_requests/show.html.haml +44 -0
- data/app/views/workarea/storefront/reviews/new.html.haml +68 -0
- data/app/views/workarea/storefront/style_guides/_reviews_product_summary_docs.html.haml +13 -0
- data/app/views/workarea/storefront/style_guides/components/_reviews.html.haml +17 -0
- data/app/workers/workarea/create_review_requests.rb +33 -0
- data/app/workers/workarea/schedule_review_requests.rb +44 -0
- data/app/workers/workarea/send_review_requests.rb +12 -0
- data/app/workers/workarea/update_product_review_data.rb +26 -0
- data/bin/rails +18 -0
- data/config/initializers/append_points.rb +70 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/configuration.rb +29 -0
- data/config/initializers/rack_attack.rb +11 -0
- data/config/initializers/recaptcha.rb +19 -0
- data/config/initializers/scheduled_jobs.rb +8 -0
- data/config/locales/en.yml +104 -0
- data/config/routes.rb +21 -0
- data/lib/tasks/verify.rake +16 -0
- data/lib/workarea/mailer_previews/storefront/review_mailer_preview.rb +10 -0
- data/lib/workarea/reviews.rb +13 -0
- data/lib/workarea/reviews/engine.rb +12 -0
- data/lib/workarea/reviews/version.rb +5 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +4 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +34 -0
- data/test/dummy/bin/update +29 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/config/application.rb +25 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +9 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +55 -0
- data/test/dummy/config/environments/production.rb +86 -0
- data/test/dummy/config/environments/test.rb +43 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/workarea.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/puma.rb +47 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/db/seeds.rb +2 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/factories/reviews.rb +32 -0
- data/test/fixtures/reviews.csv +5 -0
- data/test/helpers/workarea/admin/reviews_helper_test.rb +17 -0
- data/test/helpers/workarea/storefront/reviews_helper_test.rb +19 -0
- data/test/integration/workarea/admin/reviews_integration_test.rb +33 -0
- data/test/integration/workarea/storefront/review_requests_integration_test.rb +63 -0
- data/test/integration/workarea/storefront/reviews_integration_test.rb +82 -0
- data/test/javascripts/fixtures/product_review_ajax_submit.html.haml +4 -0
- data/test/javascripts/product_review_ajax_submit_spec.js +28 -0
- data/test/javascripts/spec_helper.js +23 -0
- data/test/models/workarea/review/request_test.rb +18 -0
- data/test/models/workarea/review_test.rb +94 -0
- data/test/models/workarea/search/storefront/product_test.decorator +14 -0
- data/test/queries/workarea/review_request_params_test.rb +64 -0
- data/test/services/workarea/create_review_test.rb +131 -0
- data/test/system/workarea/admin/review_system_test.rb +96 -0
- data/test/system/workarea/storefront/review_request_system_test.rb +34 -0
- data/test/system/workarea/storefront/review_system_test.rb +113 -0
- data/test/teaspoon_env.rb +10 -0
- data/test/test_helper.rb +11 -0
- data/test/workers/workarea/create_review_requests_test.rb +38 -0
- data/test/workers/workarea/schedule_review_requests_test.rb +115 -0
- data/test/workers/workarea/send_review_requests_test.rb +30 -0
- data/workarea-reviews.gemspec +22 -0
- metadata +241 -0
@@ -0,0 +1,5 @@
|
|
1
|
+
%tr
|
2
|
+
%td
|
3
|
+
%h2= t('workarea.admin.status_report_mailer.reviews.title')
|
4
|
+
%p= t('workarea.admin.status_report_mailer.reviews.recent_html', count: link_to(pluralize(@reviews_summary.recent_reviews_count, t('workarea.admin.status_report_mailer.reviews.review')), reviews_url(sort: :newest), style: "color: #{@link_color};"))
|
5
|
+
%p= t('workarea.admin.status_report_mailer.reviews.pending_html', count: link_to(pluralize(@reviews_summary.pending_reviews_count, t('workarea.admin.status_report_mailer.reviews.review')), reviews_url(state: %w(Pending)), style: "color: #{@link_color};"))
|
@@ -0,0 +1,10 @@
|
|
1
|
+
%p.rating{ title: "#{rating.round(2)} #{t('workarea.storefront.reviews.out_of')} #{t('workarea.storefront.reviews.stars', count: 5)}", itemprop: itemprop, itemscope: true, itemtype: itemtype }
|
2
|
+
- full_star_count.times do
|
3
|
+
= inline_svg 'workarea/storefront/icons/star.svg', class: 'rating__star'
|
4
|
+
- if half_star_size > 0
|
5
|
+
= inline_svg 'workarea/storefront/icons/half_star.svg', class: 'rating__star'
|
6
|
+
- empty_star_count.times do
|
7
|
+
= inline_svg 'workarea/storefront/icons/empty_star.svg', class: 'rating__star'
|
8
|
+
%span.rating__text.visually-hidden
|
9
|
+
%meta{ itemprop: 'ratingValue', content: rating.round(2) }
|
10
|
+
#{rating.round(2)} #{t('workarea.storefront.reviews.out_of')} #{t('workarea.storefront.reviews.stars', count: 5)}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
- if product.has_reviews?
|
2
|
+
#reviews.reviews
|
3
|
+
%h2= t('workarea.storefront.reviews.heading')
|
4
|
+
|
5
|
+
.reviews__header
|
6
|
+
%p.reviews__count= t('workarea.storefront.reviews.reviews', count: product.reviews.length)
|
7
|
+
%p.reviews__write-action= link_to t('workarea.storefront.reviews.write_a_review'), new_product_review_path(product), class: 'button', data: { dialog_button: '' }
|
8
|
+
- if display_purchase_requirement_message
|
9
|
+
%span.reviews__write-purchase-requirement= t('workarea.storefront.reviews.purchase_requirement')
|
10
|
+
|
11
|
+
%ol.reviews__review-group
|
12
|
+
- product.reviews.each do |review|
|
13
|
+
%li.reviews__review{ itemprop: 'review', itemscope: true, itemtype: 'http://schema.org/Review', data: { product_review_section_entry: { rating: review.rating.to_f, createdAt: review.created_at.to_i }.to_json } }
|
14
|
+
= rating_stars(review.rating)
|
15
|
+
|
16
|
+
%h3.reviews__review-title{ itemprop: 'name' }= review.title
|
17
|
+
%p.reviews__review-body{ itemprop: 'reviewBody' }= review.body
|
18
|
+
.reviews__review-meta
|
19
|
+
%p.reviews__review-author{ itemprop: 'author', itemscope: true, itemtype: 'http://schema.org/Person' }
|
20
|
+
%span{ itemprop: 'name' }= review.user_info
|
21
|
+
- if review.verified?
|
22
|
+
%p.reviews__review-verified= t('workarea.storefront.reviews.verified_purchaser')
|
23
|
+
%p.reviews__review-date= local_time(review.created_at, format: :long, itemprop: 'datePublished')
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- if product.has_reviews?
|
2
|
+
.reviews-aggregate{ itemprop: 'aggregateRating', itemscope: true, itemtype: 'http://schema.org/AggregateRating' }
|
3
|
+
= link_to "#{product_path(product, product.browse_link_options)}#reviews", data: { scroll_to_button: '' }, class: 'reviews-aggregate__rating-link' do
|
4
|
+
= rating_stars(product.average_rating, aggregate: true)
|
5
|
+
|
6
|
+
= link_to "#{product_path(product, product.browse_link_options)}#reviews", data: { scroll_to_button: '' } do
|
7
|
+
%span.reviews-aggregate__count
|
8
|
+
%span.reviews-aggregate__read= t('workarea.storefront.reviews.read_reviews')
|
9
|
+
= surround '(', ')' do
|
10
|
+
%span{ itemprop: 'reviewCount' }= product.total_reviews
|
11
|
+
|
12
|
+
= link_to t('workarea.storefront.reviews.write_a_review'), new_product_review_path(product), class: 'reviews-aggregate__write-action', data: { dialog_button: '' }
|
13
|
+
- if display_purchase_requirement_message
|
14
|
+
%span.write-review__purchase-requirement= t('workarea.storefront.reviews.purchase_requirement')
|
15
|
+
|
16
|
+
- else
|
17
|
+
.reviews-aggregate
|
18
|
+
%p.reviews-aggregate__count= t('workarea.storefront.reviews.reviews', count: 0)
|
19
|
+
= link_to t('workarea.storefront.reviews.write_a_review'), new_product_review_path(product), class: 'reviews-aggregate__write-action', data: { dialog_button: '' }
|
20
|
+
- if display_purchase_requirement_message
|
21
|
+
%p.write-review__purchase-requirement
|
22
|
+
= t('workarea.storefront.reviews.purchase_requirement')
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- content_for :preheader_text do
|
2
|
+
= @content
|
3
|
+
|
4
|
+
%tr
|
5
|
+
%td
|
6
|
+
!= @content
|
7
|
+
|
8
|
+
%table.product-grid
|
9
|
+
%tr
|
10
|
+
%td.stack-column-center
|
11
|
+
%table.product-grid__product{ role: 'presentation', width: '100%' }
|
12
|
+
%tr
|
13
|
+
%td.product-grid__image
|
14
|
+
= link_to product_url(@product), class: 'product-grid__link' do
|
15
|
+
= image_tag(product_image_url(@product.primary_image, :medium_thumb), alt: @product.name)
|
16
|
+
%tr
|
17
|
+
%td.product-grid__info
|
18
|
+
= link_to product_url(@product), class: 'product-grid__link' do
|
19
|
+
.product-grid__name= @product.name
|
20
|
+
|
21
|
+
%p
|
22
|
+
%strong= link_to t('workarea.storefront.email.review_request.link'), review_request_url(@request.token), class: 'button'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
- @title = t('workarea.storefront.reviews.write_a_review_title', name: @product.browser_title)
|
2
|
+
|
3
|
+
.write-review.view
|
4
|
+
%h1= t('workarea.storefront.reviews.write_a_review_title', name: @product.name)
|
5
|
+
|
6
|
+
.grid
|
7
|
+
.grid__cell.grid__cell--25
|
8
|
+
.product-summary{ itemscope: true, itemtype: 'http://schema.org/Product' }
|
9
|
+
= render 'workarea/storefront/products/summary', product: @product
|
10
|
+
|
11
|
+
.grid__cell.grid__cell--75
|
12
|
+
- unless request.get?
|
13
|
+
- if @review.errors.any?
|
14
|
+
- @review.errors.full_messages.each do |message|
|
15
|
+
= render_message 'error', message, data: { analytics: validation_error_analytics_data('review').to_json }
|
16
|
+
|
17
|
+
= form_tag complete_review_request_path(@request.token), method: 'post', id: 'review_request_form' do
|
18
|
+
.property
|
19
|
+
= label_tag 'review[rating]', nil, class: 'property__name' do
|
20
|
+
%span.property__text= t('workarea.storefront.reviews.rating')
|
21
|
+
%ul.write-review__ratings
|
22
|
+
- (1..5).each do |i|
|
23
|
+
%li.write-review__rating
|
24
|
+
= radio_button_tag 'review[rating]', i, (i == @review.rating || i == 5) ? true : false, class: 'write-review__rating-input', data: { rating_button: '' }
|
25
|
+
= label_tag "review[rating][#{i}]", nil, class: 'write-review__star' do
|
26
|
+
= inline_svg 'workarea/storefront/icons/star.svg', class: 'write-review__star-icon', title: t('workarea.storefront.reviews.stars', count: i)
|
27
|
+
|
28
|
+
.property
|
29
|
+
= label_tag 'review[title]', nil, class: 'property__name' do
|
30
|
+
%span.property__text= t('workarea.storefront.reviews.review_title')
|
31
|
+
%span.property__requirement.property__requirement--optional= t('workarea.storefront.forms.optional')
|
32
|
+
.value= text_field_tag 'review[title]', @review.title, class: 'text-box'
|
33
|
+
|
34
|
+
.property
|
35
|
+
= label_tag 'review[body]', nil, class: 'property__name' do
|
36
|
+
%span.property__requirement.property__requirement--required= t('workarea.storefront.forms.required')
|
37
|
+
%span.property__text= t('workarea.storefront.reviews.your_review')
|
38
|
+
.value= text_area_tag 'review[body]', @review.body, class: 'text-box text-box--multi-line', required: true
|
39
|
+
|
40
|
+
.property= recaptcha_tags
|
41
|
+
|
42
|
+
.grid.grid--auto
|
43
|
+
%p.grid__cell= button_tag t('workarea.storefront.reviews.submit'), value: 'submit_review', class: 'button', data: { disable_with: loading_indicator(t('workarea.storefront.reviews.submit_disabled')) }
|
44
|
+
%p.grid__cell= link_to t('workarea.storefront.forms.cancel'), product_path(@product), class: 'text-button', data: { dialog_close_button: '' }
|
@@ -0,0 +1,68 @@
|
|
1
|
+
- @title = t('workarea.storefront.reviews.write_a_review_title', name: @product.browser_title)
|
2
|
+
|
3
|
+
.write-review.view
|
4
|
+
%h1= t('workarea.storefront.reviews.write_a_review_title', name: @product.browser_title)
|
5
|
+
|
6
|
+
- unless request.get?
|
7
|
+
- if @create_review.errors.any?
|
8
|
+
- @create_review.errors.full_messages.each do |message|
|
9
|
+
= render_message 'error', message, data: { analytics: validation_error_analytics_data('review').to_json }
|
10
|
+
|
11
|
+
= form_tag create_product_review_path(@product), method: 'post', id: 'review_form', data: { product_review_ajax_submit: '' } do
|
12
|
+
= hidden_field_tag 'review[product_id]', @product.id
|
13
|
+
|
14
|
+
- if display_purchase_requirement_message
|
15
|
+
%span.write-review__purchase-requirement= t('workarea.storefront.reviews.purchase_requirement')
|
16
|
+
|
17
|
+
- if @review.requires_public_info?
|
18
|
+
.property
|
19
|
+
= label_tag 'review[first_name]', nil, class: 'property__name' do
|
20
|
+
%span.property__requirement.property__requirement--required= t('workarea.storefront.forms.required')
|
21
|
+
%span.property__text= t('workarea.storefront.users.first_name')
|
22
|
+
.value
|
23
|
+
= text_field_tag 'review[first_name]', @review.first_name, class: 'text-box', required: true
|
24
|
+
.value__note= t('workarea.storefront.reviews.notes.display_name')
|
25
|
+
.property
|
26
|
+
= label_tag 'review[last_name]', nil, class: 'property__name' do
|
27
|
+
%span.property__requirement.property__requirement--required= t('workarea.storefront.forms.required')
|
28
|
+
%span.property__text= t('workarea.storefront.users.last_name')
|
29
|
+
.value
|
30
|
+
= text_field_tag 'review[last_name]', @review.last_name, class: 'text-box', required: true
|
31
|
+
.value__note= t('workarea.storefront.reviews.notes.display_name')
|
32
|
+
|
33
|
+
- if @review.anonymous?
|
34
|
+
.property
|
35
|
+
= label_tag 'review[email]', nil, class: 'property__name' do
|
36
|
+
%span.property__text= t('workarea.storefront.users.email')
|
37
|
+
%span.property__requirement.property__requirement--optional= t('workarea.storefront.forms.optional')
|
38
|
+
.value
|
39
|
+
= email_field_tag 'review[email]', @review.email, class: 'text-box', autocapitalize: 'off', autocorrect: 'off', autocomplete: 'email'
|
40
|
+
.value__note= t('workarea.storefront.reviews.notes.email')
|
41
|
+
|
42
|
+
.property
|
43
|
+
= label_tag 'review[rating]', nil, class: 'property__name' do
|
44
|
+
%span.property__text= t('workarea.storefront.reviews.rating')
|
45
|
+
%ul.write-review__ratings
|
46
|
+
- (1..5).each do |i|
|
47
|
+
%li.write-review__rating
|
48
|
+
= radio_button_tag 'review[rating]', i, (i == @review.rating || i == 5) ? true : false, class: 'write-review__rating-input', data: { rating_button: '' }
|
49
|
+
= label_tag "review[rating][#{i}]", nil, class: 'write-review__star' do
|
50
|
+
= inline_svg 'workarea/storefront/icons/star.svg', class: 'write-review__star-icon', title: t('workarea.storefront.reviews.stars', count: i)
|
51
|
+
|
52
|
+
.property
|
53
|
+
= label_tag 'review[title]', nil, class: 'property__name' do
|
54
|
+
%span.property__text= t('workarea.storefront.reviews.review_title')
|
55
|
+
%span.property__requirement.property__requirement--optional= t('workarea.storefront.forms.optional')
|
56
|
+
.value= text_field_tag 'review[title]', @review.title, class: 'text-box'
|
57
|
+
|
58
|
+
.property
|
59
|
+
= label_tag 'review[body]', nil, class: 'property__name' do
|
60
|
+
%span.property__requirement.property__requirement--required= t('workarea.storefront.forms.required')
|
61
|
+
%span.property__text= t('workarea.storefront.reviews.your_review')
|
62
|
+
.value= text_area_tag 'review[body]', @review.body, class: 'text-box text-box--multi-line', required: true
|
63
|
+
|
64
|
+
.property= recaptcha_tags
|
65
|
+
|
66
|
+
.grid.grid--auto
|
67
|
+
%p.grid__cell= button_tag t('workarea.storefront.reviews.submit'), value: 'submit_review', class: 'button', data: { disable_with: loading_indicator(t('workarea.storefront.reviews.submit_disabled')) }
|
68
|
+
%p.grid__cell= link_to t('workarea.storefront.forms.cancel'), product_path(@product), class: 'text-button', data: { dialog_close_button: '' }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%p With reviews:
|
2
|
+
.style-guide__example-block
|
3
|
+
.product-summary
|
4
|
+
%p.product-summary__media
|
5
|
+
= link_to('#', class: 'product-summary__media-link') do
|
6
|
+
= image_tag('workarea/storefront/style_guide_product.jpg', alt: 'Product Name', class: 'product-summary__media-image')
|
7
|
+
.product-summary__info
|
8
|
+
%p.product-summary__name= link_to('Product Name', '#')
|
9
|
+
.product-summary__price-group
|
10
|
+
%p.product-summary__price
|
11
|
+
%span= number_to_currency(109.99)
|
12
|
+
= rating_stars(3.5, aggregate: true)
|
13
|
+
%p.product-summary__quickview= link_to('Quick View', '#', class: 'button button--small', rel: 'nofollow', data: { dialog_button: '' })
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#rating.style-guide__subsection
|
2
|
+
|
3
|
+
%h3= link_to_style_guide('components', 'rating')
|
4
|
+
|
5
|
+
%p Displays a graphical rating scale for a numerical rating (1.0 - 5.0). Use the <code>rating_stars(rating, options = {})</code> helper to generate the rating stars.
|
6
|
+
|
7
|
+
%h4 Options
|
8
|
+
%ul
|
9
|
+
%li
|
10
|
+
<code>aggregate</code> (default: false)
|
11
|
+
%ul
|
12
|
+
%li Passing <code>aggregate: true</code> will change schema.org rating type from `reviewRating` to `aggregateRating` (an average rating from multiple reviews). See <a href="https://schema.org/AggregateRating">https://schema.org/AggregateRating</a> for more info.
|
13
|
+
|
14
|
+
- [1.5, 2.0, 3.75, 4.1, 4.8].each do |rating|
|
15
|
+
%p Example: rating of #{rating}
|
16
|
+
.style-guide__example-block
|
17
|
+
= rating_stars(rating, aggregate: true)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Workarea
|
2
|
+
class CreateReviewRequests
|
3
|
+
include Sidekiq::Worker
|
4
|
+
include Sidekiq::CallbacksWorker
|
5
|
+
|
6
|
+
sidekiq_options(
|
7
|
+
enqueue_on: {
|
8
|
+
Order => :place,
|
9
|
+
only_if: -> { Workarea.config.send_transactional_emails }
|
10
|
+
},
|
11
|
+
queue: 'low'
|
12
|
+
)
|
13
|
+
|
14
|
+
def perform(order_id)
|
15
|
+
order = Order.find(order_id)
|
16
|
+
product_ids = order.items
|
17
|
+
.sort_by(&:original_unit_price)
|
18
|
+
.reverse
|
19
|
+
.map(&:product_id)
|
20
|
+
.uniq
|
21
|
+
.take(Workarea.config.review_requests_per_order)
|
22
|
+
|
23
|
+
product_ids.each do |product_id|
|
24
|
+
Review::Request.create(
|
25
|
+
email: order.email,
|
26
|
+
order_id: order.id,
|
27
|
+
user_id: order.user_id,
|
28
|
+
product_id: product_id
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Workarea
|
2
|
+
class ScheduleReviewRequests
|
3
|
+
include Sidekiq::Worker
|
4
|
+
|
5
|
+
sidekiq_options queue: 'low'
|
6
|
+
|
7
|
+
def perform(order_id, shipped_items)
|
8
|
+
requests = Review::Request.by_order(order_id).to_a
|
9
|
+
return if requests.all?(&:send_after)
|
10
|
+
|
11
|
+
order = Order.find(order_id)
|
12
|
+
product_ids =
|
13
|
+
shipped_items.map do |item|
|
14
|
+
order_item = order.items.detect { |i| i.id.to_s == item['id'] }
|
15
|
+
order_item&.product_id
|
16
|
+
end
|
17
|
+
.compact
|
18
|
+
|
19
|
+
schedule_requests(
|
20
|
+
requests.select { |request| request.product_id.in?(product_ids) },
|
21
|
+
requests
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def schedule_requests(affected_requests, all_requests)
|
26
|
+
affected_requests.each do |request|
|
27
|
+
next if request.send_after.present?
|
28
|
+
|
29
|
+
last_scheduled =
|
30
|
+
all_requests.select(&:send_after).sort_by(&:send_after).last
|
31
|
+
|
32
|
+
date_to_send =
|
33
|
+
if last_scheduled.present?
|
34
|
+
last_scheduled.send_after +
|
35
|
+
Workarea.config.review_request_secondary_delivery_delay
|
36
|
+
else
|
37
|
+
Workarea.config.review_request_initial_delivery_delay.from_now
|
38
|
+
end
|
39
|
+
|
40
|
+
request.update_attributes(send_after: date_to_send)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Workarea
|
2
|
+
class UpdateProductReviewData
|
3
|
+
include Sidekiq::Worker
|
4
|
+
include Sidekiq::CallbacksWorker
|
5
|
+
|
6
|
+
sidekiq_options(
|
7
|
+
enqueue_on: {
|
8
|
+
Workarea::Review => [:save, :destroy],
|
9
|
+
with: -> { [product_id] }
|
10
|
+
},
|
11
|
+
unique: :until_and_while_executing
|
12
|
+
)
|
13
|
+
|
14
|
+
def perform(product_id)
|
15
|
+
product = Workarea::Catalog::Product.find(product_id)
|
16
|
+
review_data = Review.find_single_aggregates(product_id)
|
17
|
+
|
18
|
+
product.update_attributes!(
|
19
|
+
total_reviews: review_data[:count],
|
20
|
+
average_rating: review_data[:average]
|
21
|
+
)
|
22
|
+
rescue Mongoid::Errors::DocumentNotFound
|
23
|
+
# we're ok if the product doesn't exist
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/bin/rails
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails gems
|
3
|
+
# installed from the root of your application.
|
4
|
+
|
5
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
6
|
+
ENGINE_PATH = File.expand_path('../../lib/workarea/reviews/engine', __FILE__)
|
7
|
+
|
8
|
+
# Set up gems listed in the Gemfile.
|
9
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
10
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
11
|
+
|
12
|
+
require 'action_controller/railtie'
|
13
|
+
require 'action_view/railtie'
|
14
|
+
require 'action_mailer/railtie'
|
15
|
+
require 'rails/test_unit/railtie'
|
16
|
+
require 'sprockets/railtie'
|
17
|
+
|
18
|
+
require 'rails/engine/commands'
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Workarea
|
2
|
+
#
|
3
|
+
# Storefront
|
4
|
+
#
|
5
|
+
#
|
6
|
+
|
7
|
+
Plugin.append_stylesheets(
|
8
|
+
'storefront.components',
|
9
|
+
'workarea/storefront/reviews/components/rating',
|
10
|
+
'workarea/storefront/reviews/components/reviews',
|
11
|
+
'workarea/storefront/reviews/components/reviews_aggregate',
|
12
|
+
'workarea/storefront/reviews/components/write_review',
|
13
|
+
)
|
14
|
+
|
15
|
+
Plugin.append_javascripts(
|
16
|
+
'storefront.templates',
|
17
|
+
'workarea/storefront/reviews/templates/sort_by_property'
|
18
|
+
)
|
19
|
+
|
20
|
+
Plugin.append_javascripts(
|
21
|
+
'storefront.modules',
|
22
|
+
'workarea/storefront/reviews/modules/product_review_ajax_submit',
|
23
|
+
'workarea/storefront/reviews/modules/product_reviews_sort_menus',
|
24
|
+
'workarea/storefront/reviews/modules/rating_buttons',
|
25
|
+
)
|
26
|
+
|
27
|
+
Plugin.append_partials(
|
28
|
+
'storefront.style_guide_product_summary',
|
29
|
+
'workarea/storefront/style_guides/reviews_product_summary_docs'
|
30
|
+
)
|
31
|
+
|
32
|
+
Plugin.append_partials(
|
33
|
+
'storefront.product_details',
|
34
|
+
'workarea/storefront/products/reviews_aggregate'
|
35
|
+
)
|
36
|
+
|
37
|
+
Plugin.append_partials(
|
38
|
+
'storefront.product_show',
|
39
|
+
'workarea/storefront/products/reviews'
|
40
|
+
)
|
41
|
+
|
42
|
+
Plugin.append_partials(
|
43
|
+
'storefront.product_summary',
|
44
|
+
'workarea/storefront/products/reviews_summary'
|
45
|
+
)
|
46
|
+
|
47
|
+
#
|
48
|
+
# Admin
|
49
|
+
#
|
50
|
+
#
|
51
|
+
Plugin.append_partials(
|
52
|
+
'admin.marketing_menu',
|
53
|
+
'workarea/admin/reviews/menu'
|
54
|
+
)
|
55
|
+
|
56
|
+
Plugin.append_partials(
|
57
|
+
'admin.catalog_product_aux_navigation',
|
58
|
+
'workarea/admin/reviews/catalog_products_aux_link'
|
59
|
+
)
|
60
|
+
|
61
|
+
Plugin.append_partials(
|
62
|
+
'admin.status_report_mailer',
|
63
|
+
'workarea/admin/status_report_mailer/reviews'
|
64
|
+
)
|
65
|
+
|
66
|
+
Workarea.append_partials(
|
67
|
+
'admin.marketing_dashboard_navigation',
|
68
|
+
'workarea/admin/reviews/dashboard_navigation'
|
69
|
+
)
|
70
|
+
end
|