shoperb-theme-editor 0.8.0

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.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +40 -0
  3. data/LICENSE.md +21 -0
  4. data/README.md +124 -0
  5. data/bin/shoperb +313 -0
  6. data/lib/shoperb_theme_editor/api/server.rb +10 -0
  7. data/lib/shoperb_theme_editor/api/views/callback.erb +53 -0
  8. data/lib/shoperb_theme_editor/api.rb +264 -0
  9. data/lib/shoperb_theme_editor/build/json.rb +167 -0
  10. data/lib/shoperb_theme_editor/build/liquid.rb +38 -0
  11. data/lib/shoperb_theme_editor/build/section.rb +51 -0
  12. data/lib/shoperb_theme_editor/build/settings.rb +224 -0
  13. data/lib/shoperb_theme_editor/build.rb +68 -0
  14. data/lib/shoperb_theme_editor/configuration.rb +98 -0
  15. data/lib/shoperb_theme_editor/error.rb +35 -0
  16. data/lib/shoperb_theme_editor/ext/array.rb +17 -0
  17. data/lib/shoperb_theme_editor/ext/nil_class.rb +7 -0
  18. data/lib/shoperb_theme_editor/ext/sequel.rb +82 -0
  19. data/lib/shoperb_theme_editor/ext.rb +2 -0
  20. data/lib/shoperb_theme_editor/init.rb +87 -0
  21. data/lib/shoperb_theme_editor/logger.rb +58 -0
  22. data/lib/shoperb_theme_editor/mounter/models/address.rb +65 -0
  23. data/lib/shoperb_theme_editor/mounter/models/attribute.rb +11 -0
  24. data/lib/shoperb_theme_editor/mounter/models/attribute_key.rb +17 -0
  25. data/lib/shoperb_theme_editor/mounter/models/base.rb +196 -0
  26. data/lib/shoperb_theme_editor/mounter/models/blog_category.rb +47 -0
  27. data/lib/shoperb_theme_editor/mounter/models/blog_post.rb +45 -0
  28. data/lib/shoperb_theme_editor/mounter/models/brand.rb +11 -0
  29. data/lib/shoperb_theme_editor/mounter/models/cart.rb +35 -0
  30. data/lib/shoperb_theme_editor/mounter/models/cart_item.rb +71 -0
  31. data/lib/shoperb_theme_editor/mounter/models/category.rb +99 -0
  32. data/lib/shoperb_theme_editor/mounter/models/collection.rb +40 -0
  33. data/lib/shoperb_theme_editor/mounter/models/country.rb +18 -0
  34. data/lib/shoperb_theme_editor/mounter/models/currency.rb +17 -0
  35. data/lib/shoperb_theme_editor/mounter/models/custom_field.rb +22 -0
  36. data/lib/shoperb_theme_editor/mounter/models/customer.rb +77 -0
  37. data/lib/shoperb_theme_editor/mounter/models/customer_customer_group.rb +12 -0
  38. data/lib/shoperb_theme_editor/mounter/models/customer_group.rb +13 -0
  39. data/lib/shoperb_theme_editor/mounter/models/customer_subscription.rb +40 -0
  40. data/lib/shoperb_theme_editor/mounter/models/customer_subscription_plan.rb +32 -0
  41. data/lib/shoperb_theme_editor/mounter/models/discount.rb +40 -0
  42. data/lib/shoperb_theme_editor/mounter/models/discount_variant.rb +15 -0
  43. data/lib/shoperb_theme_editor/mounter/models/image.rb +51 -0
  44. data/lib/shoperb_theme_editor/mounter/models/language.rb +17 -0
  45. data/lib/shoperb_theme_editor/mounter/models/link.rb +61 -0
  46. data/lib/shoperb_theme_editor/mounter/models/media_file.rb +19 -0
  47. data/lib/shoperb_theme_editor/mounter/models/menu.rb +21 -0
  48. data/lib/shoperb_theme_editor/mounter/models/meta.rb +10 -0
  49. data/lib/shoperb_theme_editor/mounter/models/news_item.rb +11 -0
  50. data/lib/shoperb_theme_editor/mounter/models/order.rb +133 -0
  51. data/lib/shoperb_theme_editor/mounter/models/order_item.rb +137 -0
  52. data/lib/shoperb_theme_editor/mounter/models/order_item_attribute.rb +17 -0
  53. data/lib/shoperb_theme_editor/mounter/models/order_return.rb +42 -0
  54. data/lib/shoperb_theme_editor/mounter/models/order_return_item.rb +29 -0
  55. data/lib/shoperb_theme_editor/mounter/models/order_return_item_entity.rb +25 -0
  56. data/lib/shoperb_theme_editor/mounter/models/order_return_parcel.rb +20 -0
  57. data/lib/shoperb_theme_editor/mounter/models/page.rb +26 -0
  58. data/lib/shoperb_theme_editor/mounter/models/payment_card.rb +21 -0
  59. data/lib/shoperb_theme_editor/mounter/models/payment_method.rb +67 -0
  60. data/lib/shoperb_theme_editor/mounter/models/payment_provider.rb +23 -0
  61. data/lib/shoperb_theme_editor/mounter/models/product.rb +144 -0
  62. data/lib/shoperb_theme_editor/mounter/models/product_attribute.rb +32 -0
  63. data/lib/shoperb_theme_editor/mounter/models/product_search.rb +53 -0
  64. data/lib/shoperb_theme_editor/mounter/models/product_type.rb +21 -0
  65. data/lib/shoperb_theme_editor/mounter/models/review.rb +38 -0
  66. data/lib/shoperb_theme_editor/mounter/models/search.rb +11 -0
  67. data/lib/shoperb_theme_editor/mounter/models/shipping_method.rb +39 -0
  68. data/lib/shoperb_theme_editor/mounter/models/shop.rb +58 -0
  69. data/lib/shoperb_theme_editor/mounter/models/state.rb +17 -0
  70. data/lib/shoperb_theme_editor/mounter/models/theme.rb +89 -0
  71. data/lib/shoperb_theme_editor/mounter/models/variant.rb +96 -0
  72. data/lib/shoperb_theme_editor/mounter/models/variant_attribute.rb +46 -0
  73. data/lib/shoperb_theme_editor/mounter/models/vendor.rb +38 -0
  74. data/lib/shoperb_theme_editor/mounter/server/assets.rb +35 -0
  75. data/lib/shoperb_theme_editor/mounter/server/defaults.rb +44 -0
  76. data/lib/shoperb_theme_editor/mounter/server/exception_handler.rb +22 -0
  77. data/lib/shoperb_theme_editor/mounter/server/partials/_shoperb_footer.liquid +0 -0
  78. data/lib/shoperb_theme_editor/mounter/server/partials/_shoperb_header.liquid +0 -0
  79. data/lib/shoperb_theme_editor/mounter/server/partials/_shoperb_stylesheets.liquid +3 -0
  80. data/lib/shoperb_theme_editor/mounter/server/renderer.rb +166 -0
  81. data/lib/shoperb_theme_editor/mounter/server/routes/cart.rb +127 -0
  82. data/lib/shoperb_theme_editor/mounter/server/routes/dummy.rb +34 -0
  83. data/lib/shoperb_theme_editor/mounter/server/routes/locale.rb +31 -0
  84. data/lib/shoperb_theme_editor/mounter/server/routes/pages.rb +33 -0
  85. data/lib/shoperb_theme_editor/mounter/server/routes/search.rb +18 -0
  86. data/lib/shoperb_theme_editor/mounter/server/routes.rb +366 -0
  87. data/lib/shoperb_theme_editor/mounter/server/routes_helper.rb +278 -0
  88. data/lib/shoperb_theme_editor/mounter/server.rb +66 -0
  89. data/lib/shoperb_theme_editor/mounter.rb +30 -0
  90. data/lib/shoperb_theme_editor/os.rb +13 -0
  91. data/lib/shoperb_theme_editor/package.rb +81 -0
  92. data/lib/shoperb_theme_editor/sync/images.rb +69 -0
  93. data/lib/shoperb_theme_editor/sync/pagination.rb +52 -0
  94. data/lib/shoperb_theme_editor/sync.rb +229 -0
  95. data/lib/shoperb_theme_editor/translations.rb +22 -0
  96. data/lib/shoperb_theme_editor/utils.rb +50 -0
  97. data/lib/shoperb_theme_editor.rb +159 -0
  98. data/shoperb_theme_editor.gemspec +60 -0
  99. metadata +510 -0
@@ -0,0 +1,38 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ class Review < Sequel::Model
5
+ extend Base::SequelClass
6
+ include Base::Sequel
7
+
8
+ fields :id,
9
+ :product_id,
10
+ :customer_id,
11
+ :state,
12
+ :title,
13
+ :body,
14
+ :rating,
15
+ :created_at,
16
+ :updated_at
17
+
18
+ def self.primary_key
19
+ :id
20
+ end
21
+
22
+ belongs_to :customer
23
+ belongs_to :product
24
+
25
+ dataset_module do
26
+ def visible
27
+ as_dataset(to_a.select { |r| ['new', 'accepted'].include?(r.state) })
28
+ end
29
+
30
+ def with_content
31
+ as_dataset(to_a.select { |r| r.title.present? || r.body.present? })
32
+ end
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end end end
@@ -0,0 +1,11 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ class Search < Sequel::Model
5
+ extend Base::SequelClass
6
+ include Base::Sequel
7
+ # todo: TODOREF3
8
+ end
9
+ end
10
+ end
11
+ end end end
@@ -0,0 +1,39 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ class ShippingMethod < Sequel::Model
5
+ extend Base::SequelClass
6
+ include Base::Sequel
7
+
8
+ c_fields :order_id, cast: Integer
9
+ c_fields :rate, cast: BigDecimal
10
+ c_fields :name,:provider,:provider_box,:tracking_number, cast: String
11
+
12
+ belongs_to :order
13
+
14
+ def self.raw_data
15
+ [
16
+ {
17
+ id: 1,
18
+ order_id: 1,
19
+ name: "Delivery by courier",
20
+ rate: 0.0,
21
+ provider: nil,
22
+ provider_box: nil,
23
+ tracking_number: nil,
24
+ },
25
+ {
26
+ id: 2,
27
+ order_id: 1,
28
+ name: "Omniva",
29
+ rate: 0.2e1,
30
+ provider: "post24",
31
+ provider_box: "Haapsalu Uuemõisa Konsumi pakiautomaat",
32
+ tracking_number: "23131414212312",
33
+ },
34
+ ]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end end end
@@ -0,0 +1,58 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ class Shop < Sequel::Model(:shop)
5
+ extend Base::SequelClass
6
+ include Base::Sequel
7
+
8
+ fields :id, :name, :domain, :email, :time_zone, :unit_system,
9
+ :tax_included, :tax_shipping, :meta_description,
10
+ :meta_keywords, :meta_title, :reviews,
11
+ :customer_accounts, :account_types
12
+ c_fields :possible_languages, cast: Array
13
+ c_fields :language_id, cast: Integer
14
+ c_fields :currency_id, cast: Integer
15
+
16
+ def self.primary_key
17
+ :domain
18
+ end
19
+
20
+ def self.instance
21
+ all.first
22
+ end
23
+
24
+ def metric?
25
+ unit_system == "METRIC"
26
+ end
27
+
28
+ def imperial?
29
+ unit_system == "IMPERIAL"
30
+ end
31
+
32
+ def external_hostname
33
+ domain
34
+ end
35
+
36
+ def address
37
+ Model::Address.all.detect { |address| address.owner_type == "Shop" && address.owner_id == attributes[:id] }
38
+ end
39
+
40
+ def grouped_integrations
41
+ { head: [], start_body: [], end_body: [] }.stringify_keys
42
+ end
43
+
44
+ def all_languages
45
+ ([language.code] + possible_languages).compact.uniq
46
+ end
47
+
48
+ belongs_to :currency
49
+ belongs_to :language
50
+
51
+ def language_code
52
+ language.code
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end end end
@@ -0,0 +1,17 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ class State < Sequel::Model
5
+ extend Base::SequelClass
6
+ include Base::Sequel
7
+ fields :id, :country_id, :name, :code
8
+
9
+ def self.primary_key
10
+ :code
11
+ end
12
+
13
+ belongs_to :country
14
+ end
15
+ end
16
+ end
17
+ end end end
@@ -0,0 +1,89 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ #
5
+ # Aggregating all theme data that we have
6
+ # into Theme object, which might be used in
7
+ # liquid drops/filters/tags
8
+ #
9
+ class Theme
10
+
11
+ def self.all
12
+ [Theme.new]
13
+ end
14
+
15
+ def spec
16
+ Spec.new
17
+ end
18
+
19
+ def settings_data
20
+ SettingsData.new
21
+ end
22
+
23
+ def settings_defaults
24
+ SettingsDefaults.new
25
+ end
26
+
27
+ def cache_key
28
+ SecureRandom.hex
29
+ end
30
+
31
+ def attributes
32
+ {}
33
+ end
34
+
35
+ def updated_at
36
+ Time.now
37
+ end
38
+
39
+ class Spec
40
+ def compile
41
+ data["compile"]
42
+ end
43
+
44
+ def data
45
+ JSON.parse(File.read(file).presence || "{}")
46
+ end
47
+
48
+ private
49
+
50
+ def file
51
+ File.join(Dir.pwd, "config", "spec.json")
52
+ end
53
+ end
54
+
55
+ class SettingsData
56
+ def data
57
+ JSON.parse(File.read(file).presence || "{}")
58
+ end
59
+
60
+ private
61
+
62
+ def file
63
+ if File.exist?('config/settings_data.json')
64
+ File.join(Dir.pwd, "config", "settings_data.json")
65
+ elsif File.exist?('config/settings_defaults.json')
66
+ File.join(Dir.pwd, "config", "settings_defaults.json")
67
+ end
68
+ end
69
+ end
70
+
71
+ class SettingsDefaults
72
+ def data
73
+ JSON.parse(File.read(file).presence || "{}")
74
+ end
75
+
76
+ private
77
+
78
+ def file
79
+ if File.exist?('config/settings_defaults.json')
80
+ File.join(Dir.pwd, "config", "settings_defaults.json")
81
+ elsif File.exist?('config/settings_data.json')
82
+ File.join(Dir.pwd, "config", "settings_data.json")
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end end end
@@ -0,0 +1,96 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ class Variant < Sequel::Model
5
+ extend Base::SequelClass
6
+ include Base::Sequel
7
+
8
+ fields :id, :sku, :warehouse_stock, :weight, :width, :height, :depth,
9
+ :barcode, :discount_start, :discount_end,
10
+ :charge_taxes,
11
+ :digital, :url, :position, :stock_amounts, :product_id, :compare_at,
12
+ :gift_card_value, :num_in_pack, :amount_step,:amount_step_unit
13
+ c_fields :track_inventory, cast: TrueClass
14
+ c_fields :allow_backorder, cast: TrueClass
15
+ c_fields :require_shipping, cast: TrueClass
16
+ c_fields :charge_taxes, cast: TrueClass
17
+ c_fields :price, :price_original, :price_discount, cast: BigDecimal
18
+
19
+ belongs_to :product
20
+ has_many :variant_attributes
21
+ has_many :discount_variants
22
+
23
+ attr_accessor :customer
24
+ attr_accessor :discount
25
+
26
+ def discounts
27
+ discount_variants.map(&:discount).compact
28
+ end
29
+
30
+ def discount
31
+ @discount || discounts.first
32
+ end
33
+
34
+ def name
35
+ "".tap do |name|
36
+ name << product.name
37
+ name << " - #{names.join(" / ")}" unless names.empty?
38
+ end
39
+ end
40
+
41
+ def names
42
+ variant_attributes.map(&:value)
43
+ end
44
+
45
+ dataset_module do
46
+ def available
47
+ to_a.select(&:available?)
48
+ end
49
+ end
50
+
51
+ def available?(_ = nil, amount = 1)
52
+ !track_inventory? || allow_backorder? || (!stock || stock >= amount)
53
+ end
54
+
55
+ def stock(*args)
56
+ warehouse_stock
57
+ end
58
+
59
+ def warehouse_stock
60
+ attributes[__method__].to_d
61
+ end
62
+ def amount_step
63
+ attributes[__method__].to_d
64
+ end
65
+
66
+ def active_price
67
+ discount_active? ? price_discount : price
68
+ end
69
+
70
+ def discount_active?
71
+ price_discount.present? || (has_discount_range? && (discount_start..discount_end).include?(Date.today))
72
+ end
73
+
74
+ def has_discount_range?
75
+ discount_start.present? && discount_end.present?
76
+ end
77
+
78
+ def formatted_discount_start
79
+ discount.stard_date.to_s if discount && discount.stard_date.present?
80
+ end
81
+
82
+ def formatted_discount_end
83
+ discount.end_date.to_s if discount && discount.end_date.present?
84
+ end
85
+
86
+ def images
87
+ Image.all.select { |image| image.entity == self }
88
+ end
89
+
90
+ def image
91
+ images.first
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end end end
@@ -0,0 +1,46 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ class VariantAttribute < Sequel::Model
5
+ extend Base::SequelClass
6
+ include Base::Sequel
7
+
8
+ fields :id, :value, :translations, :attribute_key
9
+ c_fields :variant_id, cast: Integer
10
+
11
+ translates :value
12
+
13
+ belongs_to :variant
14
+
15
+
16
+ def self.primary_key
17
+ :id
18
+ end
19
+
20
+ dataset_module do
21
+ def from_variant
22
+ where(Sequel.lit("1=1"))
23
+ end
24
+
25
+ def from_product
26
+ where(Sequel.lit("1=1"))
27
+ end
28
+ end
29
+
30
+ def initialize(*args)
31
+ super(*args)
32
+ @attributes[:name] = name
33
+ end
34
+
35
+ def name
36
+ attribute_key['name']
37
+ end
38
+
39
+ def handle
40
+ attribute_key['handle']
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end end end
@@ -0,0 +1,38 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ module Model
4
+ class Vendor < Sequel::Model
5
+ extend Base::SequelClass
6
+ include Base::Sequel
7
+
8
+ fields :id, :handle, :permalink, :name, :description, :code, :fax, :phone,
9
+ :email, :website, :contact_name, :contact_phone, :contact_email,
10
+ :translations
11
+
12
+ translates :name, :description, :display_name
13
+
14
+ def self.primary_key
15
+ :permalink
16
+ end
17
+
18
+ has_many :products
19
+
20
+ def self.not_empty
21
+ all.select { |c| c.products.size > 0 }
22
+ end
23
+
24
+ def images
25
+ Image.all.select { |image| image.entity == self }
26
+ end
27
+
28
+ def image
29
+ images.first
30
+ end
31
+
32
+ def address
33
+ Address.all.detect { |address| address.owner == self }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end end end
@@ -0,0 +1,35 @@
1
+ require 'artisans'
2
+
3
+ module Shoperb module Theme module Editor
4
+ module Mounter
5
+ class Server
6
+ module Assets
7
+
8
+ def self.asset_wrapper app, root
9
+ compiler = Editor.compiler(root, domain: Editor["oauth-site"], theme: Editor.handle, digests: false)
10
+ app.get "#{root}*" do |path|
11
+ env_sprockets = request.env.dup
12
+ env_sprockets['PATH_INFO'] = path
13
+ compiler.rack_response(env_sprockets)
14
+ end
15
+ end
16
+
17
+ def self.registered(app)
18
+ asset_wrapper app, "/system/assets/#{Editor["oauth-site"]}/#{Editor.handle}/"
19
+ asset_wrapper app, "/system/assets/"
20
+
21
+ app.get "/#{Editor["oauth-site"]}/images/*/*" do |id, filename|
22
+ env_sprockets = request.env.dup
23
+ env_sprockets['PATH_INFO'] = "images/#{filename}"
24
+ Model::Image.find(id: id)
25
+ ::Sprockets::Environment.new do |env|
26
+ env.append_path "data/assets"
27
+ end.call(env_sprockets)
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end end end
@@ -0,0 +1,44 @@
1
+ Sinatra.autoload :Flash, "sinatra/flash"
2
+
3
+ module Shoperb module Theme module Editor
4
+ module Mounter
5
+ class Server
6
+ module Defaults
7
+ module Helpers
8
+
9
+ def default_locals locals={}
10
+ set_pagination_defaults
11
+
12
+ request.define_singleton_method(:query_parameters) do
13
+ env['rack.request.query_hash']
14
+ end
15
+
16
+ locals = locals.merge(
17
+ shop: shop,
18
+ template: template
19
+ )
20
+
21
+ ShoperbLiquid.options(self, **locals)
22
+ end
23
+
24
+ def set_pagination_defaults
25
+ params["pagination"] ||= {}
26
+ params["page"] = params["page"].present? ? params["page"].to_i : 1
27
+ params["pagination"]["size"] ||= (1..25).to_a.sample
28
+ min = params["page"] * params["pagination"]["size"].to_i
29
+ params["pagination"]["total"] ||= (min..min+200).to_a.sample
30
+ params["pagination"]["pages"] ||= (params["pagination"]["total"].to_i / params["pagination"]["size"].to_i)
31
+ params["pagination"]["last"] ||= params["pagination"]["total"].to_i - 1
32
+ params["pagination"]["offset"] ||= ((params["page"].to_i - 1) * params["pagination"]["size"].to_i)
33
+ end
34
+
35
+ end
36
+
37
+ def self.registered app
38
+ app.helpers Helpers
39
+ app.register Sinatra::Flash
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end end end
@@ -0,0 +1,22 @@
1
+ module Shoperb module Theme module Editor
2
+ module Mounter
3
+ class Server
4
+ class ExceptionHandler
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ begin
12
+ @app.call env
13
+ rescue Exception => e
14
+ Error.report_rack(e, env)
15
+ raise e
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end end end
@@ -0,0 +1,3 @@
1
+ {% for style in stylesheets %}
2
+ {{ style | stylesheet_path | asset_url | stylesheet_tag }}
3
+ {% endfor %}