workarea-core 3.5.8 → 3.5.13
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/app/controllers/workarea/application_controller.rb +0 -5
- data/app/controllers/workarea/authentication.rb +6 -0
- data/app/helpers/workarea/i18n_helper.rb +1 -1
- data/app/middleware/workarea/application_middleware.rb +18 -0
- data/app/models/workarea/bulk_action/product_edit.rb +6 -6
- data/app/models/workarea/order.rb +3 -3
- data/app/models/workarea/releasable.rb +3 -1
- data/app/models/workarea/release/changeset.rb +1 -0
- data/app/models/workarea/search/admin/pricing_discount.rb +1 -1
- data/app/models/workarea/search/storefront.rb +9 -1
- data/app/models/workarea/search/storefront/category_query.rb +2 -2
- data/app/models/workarea/search/storefront/product.rb +11 -2
- data/app/models/workarea/user/password_reset.rb +3 -1
- data/app/queries/workarea/product_releases.rb +6 -0
- data/app/queries/workarea/search/pagination.rb +4 -1
- data/app/queries/workarea/search/product_entries.rb +7 -5
- data/app/queries/workarea/search/storefront_search.rb +1 -1
- data/app/services/workarea/direct_upload.rb +17 -13
- data/app/services/workarea/hash_update.rb +15 -1
- data/app/workers/workarea/bulk_index_admin.rb +1 -1
- data/app/workers/workarea/bulk_index_products.rb +3 -2
- data/app/workers/workarea/bulk_index_searches.rb +4 -4
- data/app/workers/workarea/index_category_changes.rb +16 -3
- data/app/workers/workarea/process_import.rb +3 -3
- data/app/workers/workarea/reindex_release.rb +42 -0
- data/app/workers/workarea/synchronize_user_metrics.rb +12 -2
- data/lib/tasks/search.rake +10 -4
- data/lib/workarea/cache.rb +1 -1
- data/lib/workarea/changelog.rake +1 -1
- data/lib/workarea/core.rb +3 -0
- data/lib/workarea/elasticsearch/document.rb +15 -8
- data/lib/workarea/ext/freedom_patches/i18n_js.rb +27 -0
- data/lib/workarea/ext/freedom_patches/mongoid_localized_defaults.rb +25 -0
- data/lib/workarea/geolocation.rb +1 -9
- data/lib/workarea/queues_pauser.rb +26 -0
- data/lib/workarea/version.rb +1 -1
- data/lib/workarea/visit.rb +8 -1
- data/lib/workarea/warnings.rb +3 -4
- data/test/helpers/workarea/i18n_helper_test.rb +2 -0
- data/test/integration/workarea/authentication_test.rb +10 -0
- data/test/integration/workarea/cache_varies_integration_test.rb +31 -0
- data/test/lib/workarea/elasticsearch/document_test.rb +20 -0
- data/test/lib/workarea/ext/freedom_patches/mongoid_localized_defaults_test.rb +25 -0
- data/test/lib/workarea/geolocation_test.rb +3 -3
- data/test/models/workarea/releasable_test.rb +13 -0
- data/test/models/workarea/search/storefront/product_releases_test.rb +60 -0
- data/test/models/workarea/search/storefront_test.rb +13 -0
- data/test/models/workarea/segment/rules/geolocation_test.rb +9 -7
- data/test/models/workarea/user/password_reset_test.rb +12 -4
- data/test/queries/workarea/search/category_browse_test.rb +23 -0
- data/test/queries/workarea/search/pagination_test.rb +9 -0
- data/test/queries/workarea/search/product_entries_test.rb +11 -0
- data/test/queries/workarea/search/product_search_test.rb +16 -0
- data/test/services/workarea/direct_upload_test.rb +20 -3
- data/test/services/workarea/hash_update_test.rb +12 -12
- data/test/workers/workarea/process_import_test.rb +6 -0
- data/test/workers/workarea/reindex_release_test.rb +81 -0
- data/workarea-core.gemspec +4 -3
- metadata +29 -9
- data/test/queries/workarea/product_releases_test.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b15a5824ab2746ddff9941773fefcaec1829d2a721a65893b3dac3a2fc7aad8a
|
4
|
+
data.tar.gz: 90b49ae058315ad91c7427c0b94c39a86016ed1898bb44d4bad99c9377053d53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ee0b818334a756cbeceacf3be95347e8fa0d46090c0fd3729073c67a04e4c2e17530adc50e772e3bc4f759fdc5d62d7d775e5e2cb0281a5541e063d82fe7526
|
7
|
+
data.tar.gz: bd4eb10892770ef2b332a25203f54e703940cec8d45fce3f13a3316636b4ec3c78c0ce4088e504845e7f017ebf75eaa8a0036251f37ed9207d90f3fe6a86be5e
|
@@ -7,7 +7,6 @@ module Workarea
|
|
7
7
|
|
8
8
|
protect_from_forgery
|
9
9
|
|
10
|
-
before_action :set_locale
|
11
10
|
after_action :set_flash_header
|
12
11
|
|
13
12
|
# Cache templates within the scope of a request for development
|
@@ -33,10 +32,6 @@ module Workarea
|
|
33
32
|
|
34
33
|
private
|
35
34
|
|
36
|
-
def set_locale
|
37
|
-
I18n.locale = params[:locale] || I18n.default_locale
|
38
|
-
end
|
39
|
-
|
40
35
|
def set_flash_header
|
41
36
|
messages = flash.map { |k, v| [k, ERB::Util.h(v)] }
|
42
37
|
response.headers['X-Flash-Messages'] = Hash[messages].to_json
|
@@ -89,6 +89,12 @@ module Workarea
|
|
89
89
|
else
|
90
90
|
uri = URI.parse(params[:return_to])
|
91
91
|
|
92
|
+
if I18n.locale != I18n.default_locale
|
93
|
+
query_hash = Rack::Utils.parse_nested_query(uri.query)
|
94
|
+
query_hash['locale'] ||= I18n.locale
|
95
|
+
uri.query = query_hash.to_query
|
96
|
+
end
|
97
|
+
|
92
98
|
if uri.fragment.present?
|
93
99
|
"#{uri.request_uri}##{uri.fragment}"
|
94
100
|
else
|
@@ -8,6 +8,7 @@ module Workarea
|
|
8
8
|
request = Rack::Request.new(env)
|
9
9
|
return @app.call(env) if request.path =~ /(jpe?g|png|ico|gif|css|js|svg)$/
|
10
10
|
|
11
|
+
set_locale(env, request)
|
11
12
|
setup_environment(env, request)
|
12
13
|
set_segment_request_headers(env)
|
13
14
|
status, headers, body = @app.call(env)
|
@@ -16,6 +17,10 @@ module Workarea
|
|
16
17
|
[status, headers, body]
|
17
18
|
end
|
18
19
|
|
20
|
+
def set_locale(env, request)
|
21
|
+
I18n.locale = locale_from_request(env, request) || I18n.default_locale
|
22
|
+
end
|
23
|
+
|
19
24
|
def setup_environment(env, request)
|
20
25
|
env['workarea.visit'] = Visit.new(env)
|
21
26
|
env['workarea.cache_varies'] = Cache::Varies.new(env['workarea.visit']).to_s
|
@@ -37,6 +42,19 @@ module Workarea
|
|
37
42
|
|
38
43
|
private
|
39
44
|
|
45
|
+
def locale_from_request(env, request)
|
46
|
+
return request.params['locale'] if request.params['locale'].present?
|
47
|
+
|
48
|
+
env_with_method = env.merge(
|
49
|
+
method: request.params[Rack::MethodOverride::METHOD_OVERRIDE_PARAM_KEY].presence ||
|
50
|
+
request.request_method
|
51
|
+
)
|
52
|
+
Rails.application.routes.recognize_path(request.path, env_with_method)[:locale]
|
53
|
+
|
54
|
+
rescue ActionController::RoutingError
|
55
|
+
# Return nil since we can't get locale out of this request
|
56
|
+
end
|
57
|
+
|
40
58
|
def normalize_segment_ids(visit)
|
41
59
|
visit.applied_segments.map(&:id).sort.join(',')
|
42
60
|
end
|
@@ -36,15 +36,15 @@ module Workarea
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def apply_details!(product)
|
39
|
-
HashUpdate
|
40
|
-
.new(adds: add_details, removes: remove_details)
|
41
|
-
.
|
39
|
+
product.details = HashUpdate
|
40
|
+
.new(original: product.details, adds: add_details, removes: remove_details)
|
41
|
+
.result
|
42
42
|
end
|
43
43
|
|
44
44
|
def apply_filters!(product)
|
45
|
-
HashUpdate
|
46
|
-
.new(adds: add_filters, removes: remove_filters)
|
47
|
-
.
|
45
|
+
product.filters = HashUpdate
|
46
|
+
.new(original: product.filters, adds: add_filters, removes: remove_filters)
|
47
|
+
.result
|
48
48
|
end
|
49
49
|
|
50
50
|
def apply_pricing!(product)
|
@@ -47,13 +47,13 @@ module Workarea
|
|
47
47
|
{
|
48
48
|
placed_at: 1,
|
49
49
|
reminded_at: 1,
|
50
|
+
fraud_suspected_at: 1,
|
50
51
|
checkout_started_at: 1,
|
51
52
|
email: 1,
|
52
|
-
"items[0]._id": 1
|
53
|
-
fraud_suspected_at: 1
|
53
|
+
"items[0]._id": 1
|
54
54
|
},
|
55
55
|
{
|
56
|
-
name: '
|
56
|
+
name: 'abandoned_order_email_with_fraud_index_v2',
|
57
57
|
background: true
|
58
58
|
}
|
59
59
|
)
|
@@ -72,7 +72,9 @@ module Workarea
|
|
72
72
|
release.preview.changesets_for(self).each { |cs| cs.apply_to(result) }
|
73
73
|
result
|
74
74
|
else
|
75
|
-
Release.with_current(release)
|
75
|
+
Release.with_current(release) do
|
76
|
+
Mongoid::QueryCache.uncached { self.class.find(id) }
|
77
|
+
end
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
@@ -18,6 +18,7 @@ module Workarea
|
|
18
18
|
index({ 'document_path.type' => 1, 'document_path.document_id' => 1 })
|
19
19
|
index('changeset.product_ids' => 1)
|
20
20
|
index('original.product_ids' => 1)
|
21
|
+
index('releasable_type' => 1, 'releasable_id' => 1)
|
21
22
|
|
22
23
|
# Finds changeset by whether the passed document is in the document
|
23
24
|
# path of the changeset. Useful for showing embedded changes in the
|
@@ -82,6 +82,14 @@ module Workarea
|
|
82
82
|
@changesets ||= Array.wrap(model.try(:changesets_with_children))
|
83
83
|
end
|
84
84
|
|
85
|
+
def releases
|
86
|
+
changesets
|
87
|
+
.uniq(&:release)
|
88
|
+
.reject { |cs| cs.release.blank? }
|
89
|
+
.flat_map { |cs| [cs.release] + cs.release.scheduled_after }
|
90
|
+
.uniq
|
91
|
+
end
|
92
|
+
|
85
93
|
def as_document
|
86
94
|
Release.with_current(release_id) do
|
87
95
|
{
|
@@ -91,7 +99,7 @@ module Workarea
|
|
91
99
|
active: active,
|
92
100
|
active_segment_ids: active_segment_ids,
|
93
101
|
release_id: release_id,
|
94
|
-
changeset_release_ids:
|
102
|
+
changeset_release_ids: releases.map(&:id),
|
95
103
|
suggestion_content: suggestion_content,
|
96
104
|
created_at: model.created_at,
|
97
105
|
updated_at: model.updated_at,
|
@@ -113,7 +113,7 @@ module Workarea
|
|
113
113
|
id: category.id,
|
114
114
|
release_id: 'live',
|
115
115
|
changeset_release_ids: changesets.map(&:release_id).uniq,
|
116
|
-
query: Categorization.new(rules: category.product_rules).query
|
116
|
+
query: Workarea::Search::Categorization.new(rules: category.product_rules).query
|
117
117
|
}
|
118
118
|
|
119
119
|
Storefront.current_index.save(document, type: 'category')
|
@@ -130,7 +130,7 @@ module Workarea
|
|
130
130
|
document = {
|
131
131
|
id: "#{category.id}-#{changeset.release_id}",
|
132
132
|
release_id: changeset.release_id,
|
133
|
-
query: Categorization.new(rules: category.product_rules).query
|
133
|
+
query: Workarea::Search::Categorization.new(rules: category.product_rules).query
|
134
134
|
}
|
135
135
|
|
136
136
|
Storefront.current_index.save(document, type: 'category')
|
@@ -122,12 +122,21 @@ module Workarea
|
|
122
122
|
ProductPrimaryImageUrl.new(model).path
|
123
123
|
end
|
124
124
|
|
125
|
-
#
|
125
|
+
# All {Releasable}s that could affect the product's Elasticsearch document
|
126
|
+
# should add their changesets to this method.
|
127
|
+
#
|
128
|
+
# @example Add to the changesets affecting a product in a decorator
|
129
|
+
# def changesets
|
130
|
+
# super.merge(SomeReleasable.for_product(product.id).changesets_with_children)
|
131
|
+
# end
|
126
132
|
#
|
127
133
|
# @return [Mongoid::Criteria]
|
128
134
|
#
|
129
135
|
def changesets
|
130
|
-
|
136
|
+
criteria = model.changesets_with_children
|
137
|
+
pricing.each { |ps| criteria.merge!(ps.changesets_with_children) }
|
138
|
+
criteria.merge!(FeaturedProducts.changesets(model.id))
|
139
|
+
criteria.includes(:release)
|
131
140
|
end
|
132
141
|
|
133
142
|
private
|
@@ -4,7 +4,7 @@ module Workarea
|
|
4
4
|
include ApplicationDocument
|
5
5
|
include UrlToken
|
6
6
|
|
7
|
-
belongs_to :user, class_name: 'Workarea::User'
|
7
|
+
belongs_to :user, class_name: 'Workarea::User', index: true
|
8
8
|
|
9
9
|
index(
|
10
10
|
{ created_at: 1 },
|
@@ -14,6 +14,8 @@ module Workarea
|
|
14
14
|
def self.setup!(email)
|
15
15
|
user = User.find_by_email(email)
|
16
16
|
return nil unless user
|
17
|
+
|
18
|
+
where(user_id: user.id).destroy_all
|
17
19
|
create!(user: user)
|
18
20
|
end
|
19
21
|
|
@@ -7,7 +7,10 @@ module Workarea
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def per_page
|
10
|
-
params[:per_page].
|
10
|
+
return Workarea.config.per_page if params[:per_page].blank?
|
11
|
+
|
12
|
+
tmp = params[:per_page].to_i
|
13
|
+
tmp > 0 ? tmp : Workarea.config.per_page
|
11
14
|
end
|
12
15
|
|
13
16
|
def size
|
@@ -17,15 +17,17 @@ module Workarea
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def live_entries
|
20
|
-
@live_entries ||= @products.
|
21
|
-
index_entries_for(product.without_release)
|
20
|
+
@live_entries ||= @products.reduce([]) do |memo, product|
|
21
|
+
memo + Array.wrap(index_entries_for(product.without_release))
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
def release_entries
|
26
|
-
@release_entries ||= @products.
|
27
|
-
ProductReleases.new(product).releases
|
28
|
-
|
26
|
+
@release_entries ||= @products.reduce([]) do |results, product|
|
27
|
+
releases = ProductReleases.new(product).releases
|
28
|
+
|
29
|
+
results + releases.reduce([]) do |memo, release|
|
30
|
+
memo + Array.wrap(index_entries_for(product.in_release(release)))
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -6,22 +6,26 @@ module Workarea
|
|
6
6
|
uri = URI.parse(request_url)
|
7
7
|
url = "#{uri.scheme}://#{uri.host}"
|
8
8
|
url += ":#{uri.port}" unless uri.port.in? [80, 443]
|
9
|
+
id = "direct_upload_#{url}"
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
response = begin
|
12
|
+
Workarea.s3.get_bucket_cors(Configuration::S3.bucket)
|
13
|
+
rescue Excon::Error::NotFound
|
14
|
+
Excon::Response.new(body: { 'CORSConfiguration' => [] })
|
15
|
+
end
|
12
16
|
|
13
|
-
response = Workarea.s3.get_bucket_cors(Configuration::S3.bucket)
|
14
17
|
cors = response.data[:body]
|
15
|
-
|
16
|
-
|
17
|
-
'
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
|
19
|
+
unless cors['CORSConfiguration'].pluck('ID').include?(id)
|
20
|
+
cors['CORSConfiguration'] << {
|
21
|
+
'ID' => id,
|
22
|
+
'AllowedMethod' => 'PUT',
|
23
|
+
'AllowedOrigin' => url,
|
24
|
+
'AllowedHeader' => '*'
|
25
|
+
}
|
26
|
+
|
27
|
+
Workarea.s3.put_bucket_cors(Configuration::S3.bucket, cors)
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
attr_reader :type, :filename
|
@@ -5,13 +5,27 @@ module Workarea
|
|
5
5
|
parsed.map(&:to_s).map(&:strip).reject(&:blank?) if parsed.present?
|
6
6
|
end
|
7
7
|
|
8
|
-
def initialize(adds: [], updates: [], removes: [])
|
8
|
+
def initialize(original: {}, adds: [], updates: [], removes: [])
|
9
|
+
@original = original
|
9
10
|
@adds = Array(adds).flatten.each_slice(2).to_a
|
10
11
|
@updates = Array(updates).flatten.each_slice(2).to_a
|
11
12
|
@removes = Array(removes).flatten
|
12
13
|
end
|
13
14
|
|
15
|
+
def result
|
16
|
+
apply_to(@original.deep_dup)
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO v3.6 remove this method, doesn't work when the field is localized
|
20
|
+
# @deprecated
|
14
21
|
def apply(hash)
|
22
|
+
Workarea.deprecation.deprecate_methods(self.class, apply: :result)
|
23
|
+
apply_to(hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def apply_to(hash)
|
15
29
|
@adds.each do |tuple|
|
16
30
|
key, value = *tuple
|
17
31
|
hash[key] = self.class.parse_values(value)
|
@@ -15,8 +15,9 @@ module Workarea
|
|
15
15
|
return if products.blank?
|
16
16
|
products = Array.wrap(products)
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
Search::Storefront.bulk do
|
19
|
+
Search::ProductEntries.new(products).map(&:as_bulk_document)
|
20
|
+
end
|
20
21
|
|
21
22
|
Catalog::Product.in(id: products.map(&:id)).set(last_indexed_at: Time.current)
|
22
23
|
end
|
@@ -18,11 +18,11 @@ module Workarea
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def perform_by_models(searches)
|
21
|
-
|
22
|
-
|
21
|
+
Search::Storefront.bulk do
|
22
|
+
searches.map do |model|
|
23
|
+
Search::Storefront::Search.new(model).as_bulk_document
|
24
|
+
end
|
23
25
|
end
|
24
|
-
|
25
|
-
Search::Storefront.bulk(documents)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -4,16 +4,29 @@ module Workarea
|
|
4
4
|
include Sidekiq::CallbacksWorker
|
5
5
|
|
6
6
|
sidekiq_options(
|
7
|
-
enqueue_on: {
|
7
|
+
enqueue_on: {
|
8
|
+
Catalog::Category => [:save, :save_release_changes],
|
9
|
+
with: -> { [changes, Release.current.present?] }
|
10
|
+
},
|
8
11
|
ignore_if: -> { changes['product_ids'].blank? },
|
9
12
|
lock: :until_executing,
|
10
13
|
query_cache: true
|
11
14
|
)
|
12
15
|
|
13
|
-
def perform(changes)
|
16
|
+
def perform(changes, for_release = false)
|
14
17
|
return unless changes['product_ids'].present?
|
15
18
|
|
16
|
-
ids =
|
19
|
+
ids = if for_release
|
20
|
+
# This is a shortcut because if you're resorting products within a release,
|
21
|
+
# the `changes` hash doesn't reflect the repositioning within the release,
|
22
|
+
# only the difference between what's live and what's in the release.
|
23
|
+
#
|
24
|
+
# Reindexing all of them is a shortcut to having to manually build a diff
|
25
|
+
# between the changesets in the possible affected releases.
|
26
|
+
changes['product_ids'].flatten.uniq
|
27
|
+
else
|
28
|
+
require_index_ids(*changes['product_ids'])
|
29
|
+
end
|
17
30
|
|
18
31
|
if ids.size > max_count
|
19
32
|
ids.each { |id| IndexProduct.perform_async(id) }
|