workarea-core 3.5.17 → 3.5.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d24b6af137b806311dbd5d13fb13a57f8693f99d767f94fb3144994fe9c7028
4
- data.tar.gz: dbbfb80358c11fc03b2e470ac741f615dc2d68e5f9c6c0d55b3b69567eaa4d02
3
+ metadata.gz: 84d99f1dbf010e7d67b9dbc7785720bbed5cd17c22528dfe57e194dfbb660892
4
+ data.tar.gz: c5453a27cf96335ae9d35fe857ccc770a0412117579b37dc1cb84e9221cd6efe
5
5
  SHA512:
6
- metadata.gz: a7f587ddc4e1e9c425eaace526f562f99ec5885002f833fd33a134164d3d20a405938a1e762b3cfd221824a77f435ebb79383591ae2bd0c3b81bd407ba0ceb12
7
- data.tar.gz: 61da7b2aa4a72d5e0b5456b401f9124769fa5f43c601d33e6e14b6a64bf820910bed36faf6992a1865e603455710b05647fa62b62488fa8fd973d33edac02564
6
+ metadata.gz: 4605fd9a72741e6cac8ab7a32d2408ba1b8f2bfb79ac875875461ab59fe660ffd5254e3b0eb69d5534222217de0ec2fc3d60351bee5e7575d93d2393fb8d9221
7
+ data.tar.gz: e2946da1f9618bc92f65ceca4281c426747f4c75d162b33e68a6fe629008507c43e07dcde39e12f871b2f0011225f40bfd5d9ecdc8d7f563586b90900f43c447
@@ -39,7 +39,8 @@ module Workarea
39
39
  end
40
40
 
41
41
  def current_impersonation
42
- @current_impersonation ||= User.find(session[:user_id])
42
+ return @current_impersonation if defined?(@current_impersonation)
43
+ @current_impersonation = User.find(session[:user_id]) rescue nil
43
44
  end
44
45
 
45
46
  def admin_browse_as_guest
@@ -1,12 +1,15 @@
1
1
  module Workarea
2
2
  class ApplicationMiddleware
3
+ ASSET_REGEX = /(jpe?g|png|ico|gif|bmp|webp|tif?f|css|js|svg|otf|ttf|woff|woff2)$/
4
+
3
5
  def initialize(app)
4
6
  @app = app
5
7
  end
6
8
 
7
9
  def call(env)
8
10
  request = Rack::Request.new(env)
9
- return @app.call(env) if request.path =~ /(jpe?g|png|ico|gif|css|js|svg)$/
11
+ env['workarea.asset_request'] = request.path =~ ASSET_REGEX
12
+ return @app.call(env) if env['workarea.asset_request']
10
13
 
11
14
  set_locale(env, request)
12
15
  setup_environment(env, request)
@@ -25,7 +28,7 @@ module Workarea
25
28
  env['workarea.visit'] = Visit.new(env)
26
29
  env['workarea.cache_varies'] = Cache::Varies.new(env['workarea.visit']).to_s
27
30
  env['rack-cache.cache_key'] = Cache::RackCacheKey
28
- env['rack-cache.force-pass'] = env['workarea.visit'].admin?
31
+ env['rack-cache.force-pass'] = env['workarea.visit'].admin? && !env['workarea.asset_request']
29
32
  end
30
33
 
31
34
  def set_segment_request_headers(env)
@@ -11,6 +11,10 @@ module Workarea
11
11
  def self.available_sorts
12
12
  AdminSorting.available_sorts
13
13
  end
14
+
15
+ def default_admin_sort
16
+ [{ _score: :desc }, { updated_at: :desc }]
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -16,7 +16,7 @@ module Workarea
16
16
  end
17
17
 
18
18
  def default_admin_sort
19
- [{ _score: :desc }, { updated_at: :desc }]
19
+ [{ updated_at: :desc }, { _score: :desc }]
20
20
  end
21
21
 
22
22
  def user_selected_sort
@@ -156,14 +156,15 @@ Workarea::Configuration.define_fields do
156
156
  end
157
157
 
158
158
  fieldset 'Communication', namespaced: false do
159
+
159
160
  field 'Email From',
160
161
  type: :string,
161
- default: 'noreply@example.com',
162
+ default: -> { "#{Workarea.config.site_name} <noreply@#{Workarea.config.host}>" },
162
163
  description: 'The email address used as the sender of system emails'
163
164
 
164
165
  field 'Email To',
165
166
  type: :string,
166
- default: 'customerservice@example.com',
167
+ default: -> { "#{Workarea.config.site_name} <customerservice@#{Workarea.config.host}>" },
167
168
  description: 'The email address that receives user generated emails, e.g. contact us inquiries'
168
169
 
169
170
  field 'Inquiry Subjects',
@@ -7,16 +7,4 @@ Workarea.configure do |config|
7
7
  'development' => 'localhost',
8
8
  'production' => 'www.<%= app_name.dasherize %>.com' # TODO
9
9
  }[Rails.env]
10
-
11
- config.email_to = {
12
- 'test' => "#{config.site_name} <customerservice@example.com>",
13
- 'development' => "#{config.site_name} <customerservice@<%= app_name %>.test>",
14
- 'production' => "#{config.site_name} <customerservice@<%= app_name.dasherize %>.com>" # TODO
15
- }[Rails.env]
16
-
17
- config.email_from = {
18
- 'test' => "#{config.site_name} <noreply@example.com>",
19
- 'development' => "#{config.site_name} <noreply@<%= app_name %>.test",
20
- 'production' => "#{config.site_name} <noreply@<%= app_name.dasherize %>.com>" # TODO
21
- }[Rails.env]
22
10
  end
@@ -1,40 +1,10 @@
1
+ require 'workarea/tasks/cache'
2
+
1
3
  namespace :workarea do
2
4
  namespace :cache do
3
5
  desc 'Prime images cache'
4
6
  task prime_images: :environment do
5
- include Rails.application.routes.url_helpers
6
- include Workarea::Storefront::ProductsHelper
7
- include Workarea::Core::Engine.routes.url_helpers
8
-
9
- built_in_jobs = [:thumb, :gif, :jpg, :png, :strip, :convert, :optimized]
10
-
11
- jobs = Dragonfly.app(:workarea).processor_methods.reject do |job|
12
- built_in_jobs.include?(job)
13
- end
14
-
15
- Workarea::Catalog::Product.all.each_by(50) do |product|
16
- product.images.each do |image|
17
- jobs.each do |job|
18
- url = URI.join(
19
- "https://#{Workarea.config.host}",
20
- dynamic_product_image_url(
21
- image.product.slug,
22
- image.option,
23
- image.id,
24
- job,
25
- only_path: true
26
- )
27
- ).to_s
28
-
29
- begin
30
- `curl #{url}`
31
- puts "Downloaded image #{url}"
32
- rescue StandardError => e
33
- puts e.inspect
34
- end
35
- end
36
- end
37
- end
7
+ Workarea::Tasks::Cache.prime_images
38
8
  end
39
9
  end
40
10
  end
@@ -1,11 +1,10 @@
1
+ require 'workarea/tasks/help'
2
+
1
3
  namespace :workarea do
2
4
  desc 'Drop and recreate help articles (Warning: all current help will be deleted!)'
3
5
  task reload_help: :environment do
4
6
  puts 'Deleting help articles...'
5
- Workarea::Help::Article.delete_all
6
- Workarea::Help::Asset.delete_all
7
-
8
- Workarea::HelpSeeds.new.perform
7
+ Workarea::Tasks::Help.reload
9
8
  Rake::Task['workarea:search_index:help'].invoke
10
9
  end
11
10
 
@@ -16,44 +15,6 @@ namespace :workarea do
16
15
  end
17
16
 
18
17
  task dump_help: :environment do
19
- Workarea::Help::Article.all.each_by(50) do |article|
20
- article_root = Rails.root.join(
21
- 'data',
22
- 'help',
23
- article.category.systemize,
24
- article.name.systemize
25
- )
26
-
27
- asset_path = article_root.join('assets')
28
-
29
- FileUtils.mkdir_p(article_root)
30
-
31
- if article.thumbnail.present?
32
- article.thumbnail.to_file(article_root.join(article.thumbnail.name))
33
- end
34
-
35
- Workarea::Help::Asset.all.each_by(50) do |asset|
36
- if article.summary.include?(asset.url) || article.body.include?(asset.url)
37
- FileUtils.mkdir_p(asset_path)
38
- asset.to_file(asset_path.join(asset.name))
39
- reference = "<%= #{asset.name.split('.').first} %>"
40
-
41
- article.summary.gsub!(asset.url, reference)
42
- article.body.gsub!(asset.url, reference)
43
- end
44
- end
45
-
46
- if article.summary.present?
47
- File.open(article_root.join('summary.md'), 'w') do |file|
48
- file.write(article.summary)
49
- end
50
- end
51
-
52
- if article.body.present?
53
- File.open(article_root.join('body.md'), 'w') do |file|
54
- file.write(article.body)
55
- end
56
- end
57
- end
18
+ Workarea::Tasks::Help.dump
58
19
  end
59
20
  end
@@ -1,49 +1,17 @@
1
- require 'active_support/testing/time_helpers'
1
+ require 'workarea/tasks/insights'
2
2
 
3
3
  namespace :workarea do
4
4
  namespace :insights do
5
5
  desc 'Creates metrics and insights based on orders'
6
6
  task generate: :environment do
7
- include ActiveSupport::Testing::TimeHelpers
8
- batch_size = ENV['WORKAREA_INSIGHTS_BATCH_SIZE'].presence || 1000
9
-
10
- Workarea::Order
11
- .placed
12
- .each_by(batch_size.to_i) { |o| Workarea::SaveOrderMetrics.perform(o) }
13
-
14
- 8.times do |i|
15
- travel_to (i.weeks.ago.beginning_of_week + 1.hour)
16
- Workarea::GenerateInsights.generate_all!
17
- end
18
-
7
+ Workarea::Tasks::Insights.generate
19
8
  puts "Success! Generated #{Workarea::Insights::Base.count} insights."
20
9
  end
21
10
 
22
11
  # Clear the metrics/insights environment - deletes lots of data, this task
23
12
  # is very dangerous! Useful for testing/debugging.
24
13
  task reset: :environment do
25
- Workarea::Order
26
- .where(:metrics_saved_at.gt => 0)
27
- .update_all(metrics_saved_at: nil)
28
-
29
-
30
- Workarea::Metrics::CategoryByDay.delete_all
31
- Workarea::Metrics::CountryByDay.delete_all
32
- Workarea::Metrics::DiscountByDay.delete_all
33
- Workarea::Metrics::MenuByDay.delete_all
34
- Workarea::Metrics::ProductByDay.delete_all
35
- Workarea::Metrics::ProductByWeek.delete_all
36
- Workarea::Metrics::ProductForLastWeek.delete_all
37
- Workarea::Metrics::SalesByDay.delete_all
38
- Workarea::Metrics::SearchByDay.delete_all
39
- Workarea::Metrics::SearchByWeek.delete_all
40
- Workarea::Metrics::SearchForLastWeek.delete_all
41
- Workarea::Metrics::SkuByDay.delete_all
42
- Workarea::Metrics::TenderByDay.delete_all
43
- Workarea::Metrics::TrafficReferrerByDay.delete_all
44
- Workarea::Metrics::User.delete_all
45
- Workarea::Insights::Base.delete_all
46
-
14
+ Workarea::Tasks::Insights.reset!
47
15
  puts "Success! Insights and metrics have been cleared."
48
16
  end
49
17
  end
@@ -1,103 +1,10 @@
1
+ require 'workarea/tasks/migrate'
2
+
1
3
  namespace :workarea do
2
4
  namespace :migrate do
3
5
  desc 'Migrate the database from v3.4 to v3.5'
4
6
  task v3_5: :environment do
5
- count = 0
6
-
7
- Workarea::Release.where(:undo_at.gte => Time.current).each do |release|
8
- undo = release.build_undo(publish_at: release.undo_at).tap(&:save!)
9
-
10
- release.changesets.each do |changeset|
11
- changeset.build_undo(release: undo).save!
12
- end
13
-
14
- Workarea::Scheduler.delete(release.undo_job_id)
15
-
16
- release.update_attributes!(undo_at: nil, undo_job_id: nil)
17
- count += 1
18
- end
19
-
20
- Workarea::Release.all.each { |r| Workarea::IndexAdminSearch.perform(r) }
21
-
22
- puts "✅ #{count} undo releases have been created."
23
-
24
- count = 0
25
-
26
- Workarea::Tax::Category.all.each_by(100) do |category|
27
- category.rates.each_by(500) do |rate|
28
- rate.postal_code_percentage = rate.percentage
29
- rate.percentage = nil
30
- end
31
-
32
- category.save!
33
- count += 1
34
- end
35
-
36
- puts "✅ #{count} tax categories updated."
37
-
38
- count = 0
39
- failed_ids = []
40
- backup = Mongo::Collection.new(Mongoid::Clients.default.database, 'workarea_legacy_segments')
41
-
42
- legacy_segments = Workarea::Segment.collection.find.to_a
43
- legacy_segments.each do |doc|
44
- backup.insert_one(doc)
45
- Workarea::Segment.collection.delete_one(doc.slice('_id'))
46
-
47
- segment = Workarea::Segment.new(
48
- id: doc['_id'],
49
- name: doc['name'],
50
- subscribed_user_ids: doc['subscribed_user_ids'],
51
- created_at: doc['created_at'],
52
- updated_at: doc['updated_at']
53
- )
54
-
55
- doc['conditions'].each do |condition|
56
- if condition['_type'] =~ /UserTag/
57
- segment.rules << Workarea::Segment::Rules::Tags.new(tags: condition['tags'])
58
- elsif condition['_type'] =~ /TotalSpent/
59
- rule = Workarea::Segment::Rules::Revenue.new
60
-
61
- if condition['operator'] == 'equals'
62
- rule.minimum = rule.maximum = Money.demongoize(condition['amount'])
63
- elsif condition['operator'] == 'less_than_or_equals'
64
- rule.maximum = Money.demongoize(condition['amount'])
65
- elsif condition['operator'] == 'less_than'
66
- rule.maximum = (Money.demongoize(condition['amount']) - 0.01.to_m)
67
- elsif condition['operator'] == 'greater_than_or_equals'
68
- rule.minimum = Money.demongoize(condition['amount'])
69
- elsif condition['operator'] == 'greater_than'
70
- rule.minimum = (Money.demongoize(condition['amount']) + 0.01.to_m)
71
- end
72
-
73
- segment.rules << rule
74
- end
75
- end
76
-
77
- if doc['conditions'].size == segment.rules.size && segment.save
78
- count += 1
79
- else
80
- failed_ids << doc['_id']
81
- end
82
- end
83
-
84
- puts "✅ #{count} segments have been migrated." if count > 0
85
- if failed_ids.any?
86
- puts "⛔️ #{failed_ids.count} segments failed to migrate."
87
- puts "You can find copies of the original segments in the workarea_legacy_segments collection."
88
- puts "The segments that failed are #{failed_ids.to_sentence}."
89
- end
90
-
91
- Workarea::Segment::LifeCycle.create!
92
- puts "✅ Life cycle segments have been created."
93
-
94
- admin_ids = Workarea::User.admins.pluck(:id)
95
- admin_ids.each do |id|
96
- Workarea::SynchronizeUserMetrics.new.perform(id)
97
- end
98
- puts "✅ #{admin_ids.count} admins have had their metrics synchronized." if admin_ids.count > 0
99
-
100
- puts "\nMigration complete!"
7
+ Workarea::Tasks::Migrate.v3_5
101
8
  end
102
9
  end
103
10
  end
@@ -1,8 +1,9 @@
1
+ require 'workarea/tasks/search'
2
+
1
3
  namespace :workarea do
2
4
  namespace :search_index do
3
5
  def setup
4
- require 'sidekiq/testing/inline' unless ENV['INLINE'] == 'false'
5
- Workarea.config.bulk_index_batch_size = ENV['BATCH_SIZE'].to_i if ENV['BATCH_SIZE'].present?
6
+ Workarea::Tasks::Search.setup
6
7
  end
7
8
 
8
9
  desc 'Reindex all data'
@@ -16,84 +17,21 @@ namespace :workarea do
16
17
  task admin: :environment do
17
18
  setup
18
19
  puts 'Indexing admin...'
19
- Workarea::QueuesPauser.with_paused_queues do
20
- Workarea::Search::Admin.reset_indexes!
21
- end
22
-
23
- Mongoid.models.each do |klass|
24
- next unless Workarea::Search::Admin.for(klass.first).present?
25
-
26
- klass.all.each_slice_of(Workarea.config.bulk_index_batch_size) do |models|
27
- Workarea::BulkIndexAdmin.perform_by_models(models)
28
- end
29
- end
30
-
31
- Workarea.config.jump_to_navigation.to_a.each do |tuple|
32
- Workarea::Search::Admin::Navigation.new(tuple).save
33
- end
20
+ Workarea::Tasks::Search.index_admin
34
21
  end
35
22
 
36
23
  desc 'Reindex storefront'
37
24
  task storefront: :environment do
38
25
  setup
39
26
  puts 'Indexing storefront...'
40
-
41
- Workarea::QueuesPauser.with_paused_queues do
42
- Workarea::Search::Storefront.reset_indexes!
43
- Workarea::Search::Storefront.ensure_dynamic_mappings
44
- end
45
-
46
- # This code finds all unique filters for products so we can index a sample
47
- # product for each to ensure the dynamic mappings get created.
48
- #
49
- # This is necessary to fix mapping errors from Elasticsearch when trying
50
- # to index category percolations against fields which have no mapping.
51
- #
52
- map = %{
53
- function() {
54
- for (var key in this.filters.#{I18n.locale}) {
55
- emit(key, null);
56
- }
57
- }
58
- }
59
- reduce = 'function(key) { return null; }'
60
- results = Workarea::Catalog::Product.map_reduce(map, reduce).out(inline: 1)
61
- unique_filters = results.map { |r| r['_id'] }
62
-
63
- sample_products = unique_filters.reduce([]) do |memo, filter|
64
- filter = "filters.#{I18n.locale}.#{filter}"
65
- memo << Workarea::Catalog::Product.exists(filter => true).sample
66
- end
67
-
68
- sample_products.each do |product|
69
- Workarea::Search::Storefront::Product.new(product).save
70
- end
71
-
72
- Workarea::Catalog::Category.all.each_by(Workarea.config.bulk_index_batch_size) do |category|
73
- Workarea::Search::Storefront::CategoryQuery.new(category).create
74
- Workarea::Search::Storefront::Category.new(category).save
75
- end
76
-
77
- Workarea::Content::Page.all.each_by(Workarea.config.bulk_index_batch_size) do |page|
78
- Workarea::Search::Storefront::Page.new(page).save
79
- end
80
-
81
- Workarea::BulkIndexProducts.perform
82
- Workarea::BulkIndexSearches.perform
27
+ Workarea::Tasks::Search.index_storefront
83
28
  end
84
29
 
85
30
  desc 'Reindex help'
86
31
  task help: :environment do
87
32
  setup
88
33
  puts 'Indexing help...'
89
-
90
- Workarea::QueuesPauser.with_paused_queues do
91
- Workarea::Search::Help.reset_indexes!
92
- end
93
-
94
- Workarea::Help::Article.all.each_by(Workarea.config.bulk_index_batch_size) do |help_article|
95
- Workarea::Search::Help.new(help_article).save
96
- end
34
+ Workarea::Tasks::Search.index_help
97
35
  end
98
36
  end
99
37
  end
@@ -1,73 +1,23 @@
1
- require 'workarea/version'
1
+ require 'workarea/tasks/services'
2
2
 
3
3
  namespace :workarea do
4
4
  namespace :services do
5
- def assert_docker_compose_installed!
6
- unless system('docker-compose -v > /dev/null 2>&1')
7
- STDERR.puts <<~eos
8
- **************************************************
9
- ⛔️ ERROR: workarea:services tasks depend on Docker Compose being installed. \
10
- See https://docs.docker.com/compose/install/ for how to install.
11
- **************************************************
12
- eos
13
- exit
14
- end
15
- end
16
-
17
- def compose_file_path
18
- File.join(Gem::Specification.find_by_name('workarea').gem_dir, 'docker-compose.yml')
19
- end
20
-
21
- def compose_env
22
- {
23
- 'COMPOSE_FILE' => compose_file_path,
24
- 'COMPOSE_PROJECT_NAME' => File.basename(Dir.pwd),
25
-
26
- 'MONGODB_VERSION' => Workarea::VERSION::MONGODB::STRING,
27
- 'MONGODB_PORT' => ENV['WORKAREA_MONGODB_PORT'] || '27017',
28
-
29
- 'REDIS_VERSION' => Workarea::VERSION::REDIS::STRING,
30
- 'REDIS_PORT' => ENV['WORKAREA_REDIS_PORT'] || '6379',
31
-
32
- 'ELASTICSEARCH_VERSION' => Workarea::VERSION::ELASTICSEARCH::STRING,
33
- 'ELASTICSEARCH_PORT' => ENV['WORKAREA_ELASTICSEARCH_PORT'] || '9200'
34
- }
35
- end
36
-
37
5
  desc 'Start Workarea background services for this app'
38
6
  task :up do
39
7
  puts 'Starting Workarea services...'
40
- assert_docker_compose_installed!
41
-
42
- if system(compose_env, "docker-compose up -d #{ENV['COMPOSE_ARGUMENTS']} #{ENV['WORKAREA_SERVICES']}")
43
- puts '✅ Success! Workarea services are running in the background. Run workarea:services:down to stop them.'
44
- else
45
- STDERR.puts '⛔️ Error! There was an error starting Workarea services.'
46
- end
8
+ Workarea::Tasks::Services.up
47
9
  end
48
10
 
49
11
  desc 'Stop Workarea external services for this app'
50
12
  task :down do
51
13
  puts 'Stopping Workarea services...'
52
- assert_docker_compose_installed!
53
-
54
- if system(compose_env, "docker-compose down #{ENV['COMPOSE_ARGUMENTS']}")
55
- puts '✅ Success! Workarea services are stopped. Run workarea:services:up to start them.'
56
- else
57
- STDERR.puts '⛔️ Error! There was an error stopping Workarea services.'
58
- end
14
+ Workarea::Tasks::Services.down
59
15
  end
60
16
 
61
17
  desc 'Remove data volumes associated with Workarea external services. Stops containers.'
62
18
  task :clean do
63
19
  puts 'Removing Workarea service data...'
64
- assert_docker_compose_installed!
65
-
66
- if system(compose_env, "docker-compose down -v #{ENV['COMPOSE_ARGUMENTS']}")
67
- puts '✅ Success! Workarea service volumes have been removed. Run workarea:services:up to start services and recreate volumes.'
68
- else
69
- STDERR.puts '⛔️ Error! There was an error removing Workarea service volumes.'
70
- end
20
+ Workarea::Tasks::Services.clean
71
21
  end
72
22
  end
73
23
  end
@@ -26,8 +26,6 @@ module Workarea
26
26
 
27
27
  config.site_name = 'Workarea'
28
28
  config.host = 'www.example.com'
29
- config.email_to = 'customerservice@example.com'
30
- config.email_from = 'noreply@example.com'
31
29
 
32
30
  # Config sent to the ImageMagick through Dragonfly for optimizing jpgs
33
31
  # All metadata profiles are removed, comments cleared by comment -set ""
@@ -78,6 +78,10 @@ module Workarea
78
78
  # get autoloaded. Without this, admin actions like updating product
79
79
  # attributes raises a {NameError} "uninitialized constant BulkIndexProducts".
80
80
  require_dependency 'workarea/bulk_index_products'
81
+
82
+ # Fixes a constant error raised in middleware (when doing segmentation)
83
+ # No idea what the cause is. TODO revisit after Zeitwerk.
84
+ require_dependency 'workarea/metrics/user'
81
85
  end
82
86
  end
83
87
  end
@@ -0,0 +1,43 @@
1
+ module Workarea
2
+ module Tasks
3
+ module Cache
4
+ extend self
5
+
6
+ def prime_images
7
+ include Rails.application.routes.url_helpers
8
+ include Workarea::Storefront::ProductsHelper
9
+ include Workarea::Core::Engine.routes.url_helpers
10
+
11
+ built_in_jobs = [:thumb, :gif, :jpg, :png, :strip, :convert, :optimized]
12
+
13
+ jobs = Dragonfly.app(:workarea).processor_methods.reject do |job|
14
+ built_in_jobs.include?(job)
15
+ end
16
+
17
+ Workarea::Catalog::Product.all.each_by(50) do |product|
18
+ product.images.each do |image|
19
+ jobs.each do |job|
20
+ url = URI.join(
21
+ "https://#{Workarea.config.host}",
22
+ dynamic_product_image_url(
23
+ image.product.slug,
24
+ image.option,
25
+ image.id,
26
+ job,
27
+ only_path: true
28
+ )
29
+ ).to_s
30
+
31
+ begin
32
+ `curl #{url}`
33
+ puts "Downloaded image #{url}"
34
+ rescue StandardError => e
35
+ puts e.inspect
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ module Workarea
2
+ module Tasks
3
+ module Help
4
+ extend self
5
+
6
+ def reload
7
+ Workarea::Help::Article.delete_all
8
+ Workarea::Help::Asset.delete_all
9
+ Workarea::HelpSeeds.new.perform
10
+ end
11
+
12
+ def dump
13
+ Workarea::Help::Article.all.each_by(50) do |article|
14
+ article_root = Rails.root.join(
15
+ 'data',
16
+ 'help',
17
+ article.category.systemize,
18
+ article.name.systemize
19
+ )
20
+
21
+ asset_path = article_root.join('assets')
22
+
23
+ FileUtils.mkdir_p(article_root)
24
+
25
+ if article.thumbnail.present?
26
+ article.thumbnail.to_file(article_root.join(article.thumbnail.name))
27
+ end
28
+
29
+ Workarea::Help::Asset.all.each_by(50) do |asset|
30
+ if article.summary.include?(asset.url) || article.body.include?(asset.url)
31
+ FileUtils.mkdir_p(asset_path)
32
+ asset.to_file(asset_path.join(asset.name))
33
+ reference = "<%= #{asset.name.split('.').first} %>"
34
+
35
+ article.summary.gsub!(asset.url, reference)
36
+ article.body.gsub!(asset.url, reference)
37
+ end
38
+ end
39
+
40
+ if article.summary.present?
41
+ File.open(article_root.join('summary.md'), 'w') do |file|
42
+ file.write(article.summary)
43
+ end
44
+ end
45
+
46
+ if article.body.present?
47
+ File.open(article_root.join('body.md'), 'w') do |file|
48
+ file.write(article.body)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,47 @@
1
+ module Workarea
2
+ module Tasks
3
+ module Insights
4
+ extend self
5
+
6
+ def generate
7
+ require 'active_support/testing/time_helpers'
8
+ include ActiveSupport::Testing::TimeHelpers
9
+ batch_size = ENV['WORKAREA_INSIGHTS_BATCH_SIZE'].presence || 1000
10
+
11
+ Workarea::Order
12
+ .placed
13
+ .each_by(batch_size.to_i) { |o| Workarea::SaveOrderMetrics.perform(o) }
14
+
15
+ 8.times do |i|
16
+ travel_to (i.weeks.ago.beginning_of_week + 1.hour)
17
+ Workarea::GenerateInsights.generate_all!
18
+ end
19
+ end
20
+
21
+ # Clear the metrics/insights environment - deletes lots of data, this task
22
+ # is very dangerous! Useful for testing/debugging.
23
+ def reset!
24
+ Workarea::Order
25
+ .where(:metrics_saved_at.gt => 0)
26
+ .update_all(metrics_saved_at: nil)
27
+
28
+ Workarea::Metrics::CategoryByDay.delete_all
29
+ Workarea::Metrics::CountryByDay.delete_all
30
+ Workarea::Metrics::DiscountByDay.delete_all
31
+ Workarea::Metrics::MenuByDay.delete_all
32
+ Workarea::Metrics::ProductByDay.delete_all
33
+ Workarea::Metrics::ProductByWeek.delete_all
34
+ Workarea::Metrics::ProductForLastWeek.delete_all
35
+ Workarea::Metrics::SalesByDay.delete_all
36
+ Workarea::Metrics::SearchByDay.delete_all
37
+ Workarea::Metrics::SearchByWeek.delete_all
38
+ Workarea::Metrics::SearchForLastWeek.delete_all
39
+ Workarea::Metrics::SkuByDay.delete_all
40
+ Workarea::Metrics::TenderByDay.delete_all
41
+ Workarea::Metrics::TrafficReferrerByDay.delete_all
42
+ Workarea::Metrics::User.delete_all
43
+ Workarea::Insights::Base.delete_all
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,106 @@
1
+ module Workarea
2
+ module Tasks
3
+ module Migrate
4
+ extend self
5
+
6
+ def v3_5
7
+ count = 0
8
+
9
+ Workarea::Release.where(:undo_at.gte => Time.current).each do |release|
10
+ undo = release.build_undo(publish_at: release.undo_at).tap(&:save!)
11
+
12
+ release.changesets.each do |changeset|
13
+ changeset.build_undo(release: undo).save!
14
+ end
15
+
16
+ Workarea::Scheduler.delete(release.undo_job_id)
17
+
18
+ release.update_attributes!(undo_at: nil, undo_job_id: nil)
19
+ count += 1
20
+ end
21
+
22
+ Workarea::Release.all.each { |r| Workarea::IndexAdminSearch.perform(r) }
23
+
24
+ puts "✅ #{count} undo releases have been created."
25
+
26
+ count = 0
27
+
28
+ Workarea::Tax::Category.all.each_by(100) do |category|
29
+ category.rates.each_by(500) do |rate|
30
+ rate.postal_code_percentage = rate.percentage
31
+ rate.percentage = nil
32
+ end
33
+
34
+ category.save!
35
+ count += 1
36
+ end
37
+
38
+ puts "✅ #{count} tax categories updated."
39
+
40
+ count = 0
41
+ failed_ids = []
42
+ backup = Mongo::Collection.new(Mongoid::Clients.default.database, 'workarea_legacy_segments')
43
+
44
+ legacy_segments = Workarea::Segment.collection.find.to_a
45
+ legacy_segments.each do |doc|
46
+ backup.insert_one(doc)
47
+ Workarea::Segment.collection.delete_one(doc.slice('_id'))
48
+
49
+ segment = Workarea::Segment.new(
50
+ id: doc['_id'],
51
+ name: doc['name'],
52
+ subscribed_user_ids: doc['subscribed_user_ids'],
53
+ created_at: doc['created_at'],
54
+ updated_at: doc['updated_at']
55
+ )
56
+
57
+ doc['conditions'].each do |condition|
58
+ if condition['_type'] =~ /UserTag/
59
+ segment.rules << Workarea::Segment::Rules::Tags.new(tags: condition['tags'])
60
+ elsif condition['_type'] =~ /TotalSpent/
61
+ rule = Workarea::Segment::Rules::Revenue.new
62
+
63
+ if condition['operator'] == 'equals'
64
+ rule.minimum = rule.maximum = Money.demongoize(condition['amount'])
65
+ elsif condition['operator'] == 'less_than_or_equals'
66
+ rule.maximum = Money.demongoize(condition['amount'])
67
+ elsif condition['operator'] == 'less_than'
68
+ rule.maximum = (Money.demongoize(condition['amount']) - 0.01.to_m)
69
+ elsif condition['operator'] == 'greater_than_or_equals'
70
+ rule.minimum = Money.demongoize(condition['amount'])
71
+ elsif condition['operator'] == 'greater_than'
72
+ rule.minimum = (Money.demongoize(condition['amount']) + 0.01.to_m)
73
+ end
74
+
75
+ segment.rules << rule
76
+ end
77
+ end
78
+
79
+ if doc['conditions'].size == segment.rules.size && segment.save
80
+ count += 1
81
+ else
82
+ failed_ids << doc['_id']
83
+ end
84
+ end
85
+
86
+ puts "✅ #{count} segments have been migrated." if count > 0
87
+ if failed_ids.any?
88
+ puts "⛔️ #{failed_ids.count} segments failed to migrate."
89
+ puts "You can find copies of the original segments in the workarea_legacy_segments collection."
90
+ puts "The segments that failed are #{failed_ids.to_sentence}."
91
+ end
92
+
93
+ Workarea::Segment::LifeCycle.create!
94
+ puts "✅ Life cycle segments have been created."
95
+
96
+ admin_ids = Workarea::User.admins.pluck(:id)
97
+ admin_ids.each do |id|
98
+ Workarea::SynchronizeUserMetrics.new.perform(id)
99
+ end
100
+ puts "✅ #{admin_ids.count} admins have had their metrics synchronized." if admin_ids.count > 0
101
+
102
+ puts "\nMigration complete!"
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,105 @@
1
+ module Workarea
2
+ module Tasks
3
+ module Search
4
+ extend self
5
+
6
+ def setup
7
+ require 'sidekiq/testing/inline' unless ENV['INLINE'] == 'false'
8
+ Workarea.config.bulk_index_batch_size = ENV['BATCH_SIZE'].to_i if ENV['BATCH_SIZE'].present?
9
+ end
10
+
11
+ def index_admin
12
+ Workarea::QueuesPauser.with_paused_queues do
13
+ Workarea::Search::Admin.reset_indexes!
14
+ end
15
+
16
+ Mongoid.models.each do |klass|
17
+ next unless Workarea::Search::Admin.for(klass.first).present?
18
+
19
+ klass.all.each_slice_of(Workarea.config.bulk_index_batch_size) do |models|
20
+ Workarea::BulkIndexAdmin.perform_by_models(models)
21
+ end
22
+ end
23
+
24
+ Workarea.config.jump_to_navigation.to_a.each do |tuple|
25
+ Workarea::Search::Admin::Navigation.new(tuple).save
26
+ end
27
+ end
28
+
29
+ def index_storefront
30
+ Workarea::QueuesPauser.with_paused_queues do
31
+ Workarea::Search::Storefront.reset_indexes!
32
+ Workarea::Search::Storefront.ensure_dynamic_mappings
33
+ end
34
+
35
+ ensure_dynamic_mappings_for_current_product_filters
36
+
37
+ index_storefront_categories
38
+ index_storefront_content_pages
39
+ index_storefront_products
40
+ index_storefront_searches
41
+ end
42
+
43
+ def index_help
44
+ Workarea::QueuesPauser.with_paused_queues do
45
+ Workarea::Search::Help.reset_indexes!
46
+ end
47
+
48
+ Workarea::Help::Article.all.each_by(Workarea.config.bulk_index_batch_size) do |help_article|
49
+ Workarea::Search::Help.new(help_article).save
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # This code finds all unique filters for products so we can index a sample
56
+ # product for each to ensure the dynamic mappings get created.
57
+ #
58
+ # This is necessary to fix mapping errors from Elasticsearch when trying
59
+ # to index category percolations against fields which have no mapping.
60
+ #
61
+ def ensure_dynamic_mappings_for_current_product_filters
62
+ map = %{
63
+ function() {
64
+ for (var key in this.filters.#{I18n.locale}) {
65
+ emit(key, null);
66
+ }
67
+ }
68
+ }
69
+ reduce = 'function(key) { return null; }'
70
+ results = Workarea::Catalog::Product.map_reduce(map, reduce).out(inline: 1)
71
+ unique_filters = results.map { |r| r['_id'] }
72
+
73
+ sample_products = unique_filters.reduce([]) do |memo, filter|
74
+ filter = "filters.#{I18n.locale}.#{filter}"
75
+ memo << Workarea::Catalog::Product.exists(filter => true).sample
76
+ end
77
+
78
+ sample_products.each do |product|
79
+ Workarea::Search::Storefront::Product.new(product).save
80
+ end
81
+ end
82
+
83
+ def index_storefront_categories
84
+ Workarea::Catalog::Category.all.each_by(Workarea.config.bulk_index_batch_size) do |category|
85
+ Workarea::Search::Storefront::CategoryQuery.new(category).create
86
+ Workarea::Search::Storefront::Category.new(category).save
87
+ end
88
+ end
89
+
90
+ def index_storefront_content_pages
91
+ Workarea::Content::Page.all.each_by(Workarea.config.bulk_index_batch_size) do |page|
92
+ Workarea::Search::Storefront::Page.new(page).save
93
+ end
94
+ end
95
+
96
+ def index_storefront_products
97
+ Workarea::BulkIndexProducts.perform
98
+ end
99
+
100
+ def index_storefront_searches
101
+ Workarea::BulkIndexSearches.perform
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,71 @@
1
+ module Workarea
2
+ module Tasks
3
+ module Services
4
+ extend self
5
+
6
+ def assert_docker_compose_installed!
7
+ unless system('docker-compose -v > /dev/null 2>&1')
8
+ STDERR.puts <<~eos
9
+ **************************************************
10
+ ⛔️ ERROR: workarea:services tasks depend on Docker Compose being installed. \
11
+ See https://docs.docker.com/compose/install/ for how to install.
12
+ **************************************************
13
+ eos
14
+ exit
15
+ end
16
+ end
17
+
18
+ def compose_file_path
19
+ File.join(Gem::Specification.find_by_name('workarea').gem_dir, 'docker-compose.yml')
20
+ end
21
+
22
+ def compose_env
23
+ require 'workarea/version'
24
+
25
+ {
26
+ 'COMPOSE_FILE' => compose_file_path,
27
+ 'COMPOSE_PROJECT_NAME' => File.basename(Dir.pwd),
28
+
29
+ 'MONGODB_VERSION' => Workarea::VERSION::MONGODB::STRING,
30
+ 'MONGODB_PORT' => ENV['WORKAREA_MONGODB_PORT'] || '27017',
31
+
32
+ 'REDIS_VERSION' => Workarea::VERSION::REDIS::STRING,
33
+ 'REDIS_PORT' => ENV['WORKAREA_REDIS_PORT'] || '6379',
34
+
35
+ 'ELASTICSEARCH_VERSION' => Workarea::VERSION::ELASTICSEARCH::STRING,
36
+ 'ELASTICSEARCH_PORT' => ENV['WORKAREA_ELASTICSEARCH_PORT'] || '9200'
37
+ }
38
+ end
39
+
40
+ def up
41
+ assert_docker_compose_installed!
42
+
43
+ if system(compose_env, "docker-compose up -d #{ENV['COMPOSE_ARGUMENTS']} #{ENV['WORKAREA_SERVICES']}")
44
+ puts '✅ Success! Workarea services are running in the background. Run workarea:services:down to stop them.'
45
+ else
46
+ STDERR.puts '⛔️ Error! There was an error starting Workarea services.'
47
+ end
48
+ end
49
+
50
+ def down
51
+ assert_docker_compose_installed!
52
+
53
+ if system(compose_env, "docker-compose down #{ENV['COMPOSE_ARGUMENTS']}")
54
+ puts '✅ Success! Workarea services are stopped. Run workarea:services:up to start them.'
55
+ else
56
+ STDERR.puts '⛔️ Error! There was an error stopping Workarea services.'
57
+ end
58
+ end
59
+
60
+ def clean
61
+ assert_docker_compose_installed!
62
+
63
+ if system(compose_env, "docker-compose down -v #{ENV['COMPOSE_ARGUMENTS']}")
64
+ puts '✅ Success! Workarea service volumes have been removed. Run workarea:services:up to start services and recreate volumes.'
65
+ else
66
+ STDERR.puts '⛔️ Error! There was an error removing Workarea service volumes.'
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -2,7 +2,7 @@ module Workarea
2
2
  module VERSION
3
3
  MAJOR = 3
4
4
  MINOR = 5
5
- PATCH = 17
5
+ PATCH = 18
6
6
  PRE = nil
7
7
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
8
8
 
@@ -55,8 +55,6 @@ module Workarea
55
55
  assert_file 'config/initializers/workarea.rb' do |file|
56
56
  assert_match(%(config.site_name =), file)
57
57
  assert_match(%(config.host =), file)
58
- assert_match(%(config.email_to =), file)
59
- assert_match(%(config.email_from =), file)
60
58
  end
61
59
  end
62
60
 
@@ -81,6 +81,16 @@ module Workarea
81
81
  assert_equal(results.reverse, search.results)
82
82
  end
83
83
 
84
+ def test_default_sort_by_score
85
+ # Unlike other admin searches (primarily indexes), we want searching to
86
+ # default sort by score. Testing scores directly is unreliable so just
87
+ # do a simple check here.
88
+ assert_equal(
89
+ [{ _score: :desc }, { updated_at: :desc }],
90
+ AdminSearch.new.default_admin_sort
91
+ )
92
+ end
93
+
84
94
  def test_selected_sorting
85
95
  results = [
86
96
  create_product(name: 'A', variants: []),
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workarea-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.17
4
+ version: 3.5.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Crouse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-19 00:00:00.000000000 Z
11
+ date: 2020-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -1990,6 +1990,12 @@ files:
1990
1990
  - lib/workarea/string_id.rb
1991
1991
  - lib/workarea/svg_asset_finder.rb
1992
1992
  - lib/workarea/swappable_list.rb
1993
+ - lib/workarea/tasks/cache.rb
1994
+ - lib/workarea/tasks/help.rb
1995
+ - lib/workarea/tasks/insights.rb
1996
+ - lib/workarea/tasks/migrate.rb
1997
+ - lib/workarea/tasks/search.rb
1998
+ - lib/workarea/tasks/services.rb
1993
1999
  - lib/workarea/url_token.rb
1994
2000
  - lib/workarea/validators/email_validator.rb
1995
2001
  - lib/workarea/validators/ip_address_validator.rb