dugway 0.5.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.
- data/.gitignore +7 -0
- data/.travis.yml +3 -0
- data/Gemfile +2 -0
- data/README.md +151 -0
- data/Rakefile +12 -0
- data/bin/dugway +7 -0
- data/dugway.gemspec +43 -0
- data/lib/dugway.rb +66 -0
- data/lib/dugway/application.rb +147 -0
- data/lib/dugway/cart.rb +144 -0
- data/lib/dugway/cli.rb +22 -0
- data/lib/dugway/cli/build.rb +56 -0
- data/lib/dugway/cli/create.rb +71 -0
- data/lib/dugway/cli/server.rb +37 -0
- data/lib/dugway/cli/templates/Gemfile.tt +2 -0
- data/lib/dugway/cli/templates/config.tt +24 -0
- data/lib/dugway/cli/templates/gitignore.tt +9 -0
- data/lib/dugway/cli/templates/source/cart.html +40 -0
- data/lib/dugway/cli/templates/source/checkout.html +33 -0
- data/lib/dugway/cli/templates/source/contact.html +37 -0
- data/lib/dugway/cli/templates/source/home.html +25 -0
- data/lib/dugway/cli/templates/source/images/badge.png +0 -0
- data/lib/dugway/cli/templates/source/javascripts/cart.js.coffee +7 -0
- data/lib/dugway/cli/templates/source/javascripts/product.js.coffee +7 -0
- data/lib/dugway/cli/templates/source/layout.html +101 -0
- data/lib/dugway/cli/templates/source/maintenance.html +20 -0
- data/lib/dugway/cli/templates/source/product.html +65 -0
- data/lib/dugway/cli/templates/source/products.html +25 -0
- data/lib/dugway/cli/templates/source/screenshot.jpg +0 -0
- data/lib/dugway/cli/templates/source/scripts.js +19 -0
- data/lib/dugway/cli/templates/source/settings.json +71 -0
- data/lib/dugway/cli/templates/source/styles.css +27 -0
- data/lib/dugway/cli/templates/source/stylesheets/cart.css.sass +38 -0
- data/lib/dugway/cli/templates/source/stylesheets/layout.css.sass +103 -0
- data/lib/dugway/cli/templates/source/stylesheets/product.css.sass +19 -0
- data/lib/dugway/cli/templates/source/stylesheets/products.css.sass +20 -0
- data/lib/dugway/cli/templates/source/stylesheets/vendor/normalize.css +396 -0
- data/lib/dugway/cli/templates/source/success.html +5 -0
- data/lib/dugway/controller.rb +148 -0
- data/lib/dugway/data/locales/cs.yml +26 -0
- data/lib/dugway/data/locales/da.yml +26 -0
- data/lib/dugway/data/locales/en-AU.yml +26 -0
- data/lib/dugway/data/locales/en-GB.yml +26 -0
- data/lib/dugway/data/locales/en-PH.yml +27 -0
- data/lib/dugway/data/locales/en-US.yml +26 -0
- data/lib/dugway/data/locales/es-MX.yml +26 -0
- data/lib/dugway/data/locales/eu.yml +26 -0
- data/lib/dugway/data/locales/gsw-CH.yml +26 -0
- data/lib/dugway/data/locales/hu.yml +26 -0
- data/lib/dugway/data/locales/il.yml +26 -0
- data/lib/dugway/data/locales/ja.yml +30 -0
- data/lib/dugway/data/locales/ms-MY.yml +26 -0
- data/lib/dugway/data/locales/nb.yml +22 -0
- data/lib/dugway/data/locales/pl.yml +27 -0
- data/lib/dugway/data/locales/pt-BR.yml +26 -0
- data/lib/dugway/data/locales/sv-SE.yml +26 -0
- data/lib/dugway/data/locales/th.yml +26 -0
- data/lib/dugway/data/locales/tr.yml +29 -0
- data/lib/dugway/data/locales/zh-TW.yml +30 -0
- data/lib/dugway/data/theme_fonts.yml +151 -0
- data/lib/dugway/extensions/time.rb +15 -0
- data/lib/dugway/liquid/drops/account_drop.rb +17 -0
- data/lib/dugway/liquid/drops/artist_drop.rb +9 -0
- data/lib/dugway/liquid/drops/artists_drop.rb +13 -0
- data/lib/dugway/liquid/drops/base_drop.rb +59 -0
- data/lib/dugway/liquid/drops/cart_drop.rb +13 -0
- data/lib/dugway/liquid/drops/cart_item_drop.rb +21 -0
- data/lib/dugway/liquid/drops/categories_drop.rb +13 -0
- data/lib/dugway/liquid/drops/category_drop.rb +9 -0
- data/lib/dugway/liquid/drops/contact_drop.rb +29 -0
- data/lib/dugway/liquid/drops/country_drop.rb +6 -0
- data/lib/dugway/liquid/drops/currency_drop.rb +6 -0
- data/lib/dugway/liquid/drops/image_drop.rb +6 -0
- data/lib/dugway/liquid/drops/page_drop.rb +13 -0
- data/lib/dugway/liquid/drops/pages_drop.rb +9 -0
- data/lib/dugway/liquid/drops/product_drop.rb +101 -0
- data/lib/dugway/liquid/drops/product_option_drop.rb +27 -0
- data/lib/dugway/liquid/drops/products_drop.rb +75 -0
- data/lib/dugway/liquid/drops/shipping_option_drop.rb +13 -0
- data/lib/dugway/liquid/drops/theme_drop.rb +23 -0
- data/lib/dugway/liquid/filters/comparison_filters.rb +48 -0
- data/lib/dugway/liquid/filters/core_filters.rb +138 -0
- data/lib/dugway/liquid/filters/default_pagination.rb +35 -0
- data/lib/dugway/liquid/filters/font_filters.rb +9 -0
- data/lib/dugway/liquid/filters/url_filters.rb +66 -0
- data/lib/dugway/liquid/filters/util_filters.rb +119 -0
- data/lib/dugway/liquid/tags/checkout_form.rb +9 -0
- data/lib/dugway/liquid/tags/get.rb +58 -0
- data/lib/dugway/liquid/tags/paginate.rb +129 -0
- data/lib/dugway/liquifier.rb +122 -0
- data/lib/dugway/logger.rb +16 -0
- data/lib/dugway/request.rb +36 -0
- data/lib/dugway/store.rb +166 -0
- data/lib/dugway/template.rb +44 -0
- data/lib/dugway/theme.rb +145 -0
- data/lib/dugway/theme_font.rb +68 -0
- data/lib/dugway/version.rb +3 -0
- data/spec/fixtures/store/page/about-us.js +1 -0
- data/spec/fixtures/store/products.js +1 -0
- data/spec/fixtures/store/store.js +1 -0
- data/spec/fixtures/theme/cart.html +33 -0
- data/spec/fixtures/theme/checkout.html +31 -0
- data/spec/fixtures/theme/contact.html +37 -0
- data/spec/fixtures/theme/home.html +38 -0
- data/spec/fixtures/theme/images/bc_badge.png +0 -0
- data/spec/fixtures/theme/javascripts/one.js +3 -0
- data/spec/fixtures/theme/javascripts/two.js.coffee +2 -0
- data/spec/fixtures/theme/layout.html +77 -0
- data/spec/fixtures/theme/maintenance.html +17 -0
- data/spec/fixtures/theme/product.html +73 -0
- data/spec/fixtures/theme/products.html +41 -0
- data/spec/fixtures/theme/screenshot.jpg +0 -0
- data/spec/fixtures/theme/scripts.js +2 -0
- data/spec/fixtures/theme/settings.json +55 -0
- data/spec/fixtures/theme/styles.css +4 -0
- data/spec/fixtures/theme/stylesheets/one.css +3 -0
- data/spec/fixtures/theme/stylesheets/two.css.sass +4 -0
- data/spec/fixtures/theme/success.html +5 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/units/dugway/request_spec.rb +206 -0
- data/spec/units/dugway/store_spec.rb +194 -0
- data/spec/units/dugway/template_spec.rb +145 -0
- data/spec/units/dugway/theme_font_spec.rb +136 -0
- data/spec/units/dugway_spec.rb +9 -0
- metadata +549 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Dugway
|
|
2
|
+
module Drops
|
|
3
|
+
class BaseDrop < Liquid::Drop
|
|
4
|
+
attr_reader :source
|
|
5
|
+
attr_reader :request
|
|
6
|
+
attr_reader :params
|
|
7
|
+
|
|
8
|
+
def initialize(source=nil)
|
|
9
|
+
@source = source
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def context=(current_context)
|
|
13
|
+
@request = current_context.registers[:request]
|
|
14
|
+
@params = current_context.registers[:params]
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def store
|
|
19
|
+
Dugway.store
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def theme
|
|
23
|
+
Dugway.theme
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def cart
|
|
27
|
+
Dugway.cart
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def before_method(method_or_key)
|
|
31
|
+
if respond_to?(method_or_key)
|
|
32
|
+
# don't do anything, just let it default here
|
|
33
|
+
elsif source.respond_to?(method_or_key)
|
|
34
|
+
return source.send(method_or_key)
|
|
35
|
+
elsif source.respond_to?('has_key?') && source.has_key?(method_or_key)
|
|
36
|
+
return source[method_or_key]
|
|
37
|
+
elsif source.is_a?(Array) && source.first.has_key?('permalink')
|
|
38
|
+
for item in source
|
|
39
|
+
return item if item['permalink'] == method_or_key.to_s
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def method_missing(method, *args, &block)
|
|
47
|
+
before_method(method.to_s)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def errors
|
|
51
|
+
@context['errors']
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def error(msg)
|
|
55
|
+
errors << msg
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Dugway
|
|
2
|
+
module Drops
|
|
3
|
+
class CartItemDrop < BaseDrop
|
|
4
|
+
def price
|
|
5
|
+
unit_price * quantity
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def product
|
|
9
|
+
ProductDrop.new(source['product'])
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def option
|
|
13
|
+
ProductOptionDrop.new(source['option'])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def shipping
|
|
17
|
+
0.0
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Dugway
|
|
2
|
+
module Drops
|
|
3
|
+
class ContactDrop < BaseDrop
|
|
4
|
+
def name
|
|
5
|
+
params[:name] ||= ''
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def email
|
|
9
|
+
params[:email] ||= ''
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def subject
|
|
13
|
+
params[:subject] ||= ''
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def message
|
|
17
|
+
params[:message] ||= ''
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def captcha
|
|
21
|
+
%{<img id="captcha_image" src="https://s3.amazonaws.com/bigcartel/captcha/28e3d1288cbc70c0cd1a2d10845f8e11e1a90d14.png">}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def sent
|
|
25
|
+
request.path == '/contact' && request.post? && errors.blank?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Dugway
|
|
2
|
+
module Drops
|
|
3
|
+
class ProductDrop < BaseDrop
|
|
4
|
+
def price
|
|
5
|
+
nil # price is deprecated in favor of default_price
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def min_price
|
|
9
|
+
@min_price ||= price_min_max.first
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def max_price
|
|
13
|
+
@max_price ||= price_min_max.last
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def variable_pricing
|
|
17
|
+
@variable_pricing ||= min_price != max_price
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def has_default_option
|
|
21
|
+
@has_default_option ||= options.size == 1 && option.default
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def option
|
|
25
|
+
@option ||= options.blank? ? nil : options.first
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def options
|
|
29
|
+
@options ||= source['options'].each_with_index.map { |o,i| ProductOptionDrop.new(o.update('position' => i+1, 'product' => self)) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def options_in_stock
|
|
33
|
+
@options_in_stock ||= options
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def shipping
|
|
37
|
+
@shipping ||= source['shipping'].map { |o| ShippingOptionDrop.new(o.update('product' => self)) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def image
|
|
41
|
+
@image ||= images.blank? ? nil : images.first
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def images
|
|
45
|
+
@images ||= source['images'].present? ? source['images'].map { |image| ImageDrop.new(image) } : []
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def image_count
|
|
49
|
+
@image_count ||= images.size
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def previous_product
|
|
53
|
+
@previous_product ||= begin
|
|
54
|
+
if previous_product = store.previous_product(permalink)
|
|
55
|
+
ProductDrop.new(previous_product)
|
|
56
|
+
else
|
|
57
|
+
nil
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def next_product
|
|
63
|
+
@next_product ||= begin
|
|
64
|
+
if next_product = store.next_product(permalink)
|
|
65
|
+
ProductDrop.new(next_product)
|
|
66
|
+
else
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def edit_url
|
|
73
|
+
"http://bigcartel.com"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def categories
|
|
77
|
+
@categories ||= CategoriesDrop.new(source['categories'].map { |c| CategoryDrop.new(c) }) rescue []
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def artists
|
|
81
|
+
@artists ||= ArtistsDrop.new(source['artists'].map { |a| ArtistDrop.new(a) }) rescue []
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def css_class
|
|
85
|
+
@css_class ||= begin
|
|
86
|
+
c = 'product'
|
|
87
|
+
c += ' sold' if status == 'sold-out'
|
|
88
|
+
c += ' soon' if status == 'coming-soon'
|
|
89
|
+
c += ' sale' if on_sale
|
|
90
|
+
c
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def price_min_max
|
|
97
|
+
@price_min_max ||= options.collect(&:price).uniq.minmax
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Dugway
|
|
2
|
+
module Drops
|
|
3
|
+
class ProductOptionDrop < BaseDrop
|
|
4
|
+
def default
|
|
5
|
+
name.downcase == 'default'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def has_custom_price
|
|
9
|
+
price != product.default_price
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Make up inventory numbers since we obviously don't want that from the API
|
|
13
|
+
|
|
14
|
+
def quantity
|
|
15
|
+
@quantity ||= sold_out ? 0 : rand(100)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def sold
|
|
19
|
+
@sold ||= rand(100)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def inventory
|
|
23
|
+
((quantity.to_f / (quantity + sold).to_f) * 100).round
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'will_paginate/array'
|
|
2
|
+
|
|
3
|
+
module Dugway
|
|
4
|
+
module Drops
|
|
5
|
+
class ProductsDrop < BaseDrop
|
|
6
|
+
def all
|
|
7
|
+
sort_and_paginate source
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def current
|
|
11
|
+
sort_and_paginate begin
|
|
12
|
+
if artist.present?
|
|
13
|
+
dropify store.artist_products(artist)
|
|
14
|
+
elsif category.present?
|
|
15
|
+
dropify store.category_products(category)
|
|
16
|
+
elsif search_terms.present?
|
|
17
|
+
dropify store.search_products(search_terms)
|
|
18
|
+
else
|
|
19
|
+
source
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def on_sale
|
|
25
|
+
sort_and_paginate source.select { |p| p['on_sale'] }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def order
|
|
31
|
+
begin case @context['internal']['order']
|
|
32
|
+
when 'newest', 'date'
|
|
33
|
+
'date'
|
|
34
|
+
# We don't pass these in the API, so fake it
|
|
35
|
+
when 'sales', 'sells', 'views'
|
|
36
|
+
'shuffle'
|
|
37
|
+
else
|
|
38
|
+
'position'
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def sort_and_paginate(array)
|
|
44
|
+
if order == 'shuffle'
|
|
45
|
+
array.shuffle!
|
|
46
|
+
elsif order == 'date'
|
|
47
|
+
array.sort! { |a,b| b['id'] <=> a['id'] }
|
|
48
|
+
else
|
|
49
|
+
array.sort_by! { |p| p[order] }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
array.paginate({
|
|
53
|
+
:page => (@context.registers[:params][:page] || 1).to_i,
|
|
54
|
+
:per_page => @context['internal']['per_page']
|
|
55
|
+
})
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def artist
|
|
59
|
+
@context.registers[:artist]['permalink'] rescue nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def category
|
|
63
|
+
@context.registers[:category]['permalink'] rescue nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def search_terms
|
|
67
|
+
params[:search]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def dropify(products)
|
|
71
|
+
products.map { |p| ProductDrop.new(p) }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Dugway
|
|
2
|
+
module Drops
|
|
3
|
+
class ShippingOptionDrop < BaseDrop
|
|
4
|
+
def country
|
|
5
|
+
@country ||= CountryDrop.new(source['country'])
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def strict
|
|
9
|
+
@strict ||= product.shipping.size > 1 || product.shipping.first.country.name.present?
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Dugway
|
|
2
|
+
module Drops
|
|
3
|
+
class ThemeDrop < BaseDrop
|
|
4
|
+
def before_method(method_or_key)
|
|
5
|
+
if source.respond_to?('has_key?') && source.has_key?(method_or_key) && images.find { |image| image['variable'] == method_or_key.to_s }
|
|
6
|
+
return ImageDrop.new(source[method_or_key].stringify_keys)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
super
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def images
|
|
15
|
+
@images ||= settings.has_key?('images') ? settings['images'] : []
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def settings
|
|
19
|
+
@settings ||= @context.registers[:settings]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|