dugway 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|