storefront 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +76 -0
- data/init.rb +1 -0
- data/lib/storefront.rb +21 -0
- data/lib/storefront/dashboard.rb +184 -0
- data/lib/storefront/form.rb +65 -0
- data/lib/storefront/form/elements.rb +101 -0
- data/lib/storefront/form/errors.rb +57 -0
- data/lib/storefront/form/fields.rb +420 -0
- data/lib/storefront/form/hints.rb +18 -0
- data/lib/storefront/form/inputs.rb +254 -0
- data/lib/storefront/form/labels.rb +81 -0
- data/lib/storefront/form/model.rb +84 -0
- data/lib/storefront/helpers/attribute_helper.rb +60 -0
- data/lib/storefront/helpers/body_helper.rb +18 -0
- data/lib/storefront/helpers/browser_helper.rb +54 -0
- data/lib/storefront/helpers/cache_helper.rb +25 -0
- data/lib/storefront/helpers/collection_helper.rb +14 -0
- data/lib/storefront/helpers/component_helper.rb +35 -0
- data/lib/storefront/helpers/dashboard_helper.rb +37 -0
- data/lib/storefront/helpers/debug_helper.rb +11 -0
- data/lib/storefront/helpers/definition_list_helper.rb +29 -0
- data/lib/storefront/helpers/error_helper.rb +11 -0
- data/lib/storefront/helpers/flash_helper.rb +14 -0
- data/lib/storefront/helpers/form_helper.rb +8 -0
- data/lib/storefront/helpers/format_helper.rb +59 -0
- data/lib/storefront/helpers/head_helper.rb +229 -0
- data/lib/storefront/helpers/image_helper.rb +54 -0
- data/lib/storefront/helpers/list_helper.rb +47 -0
- data/lib/storefront/helpers/locale_helper.rb +175 -0
- data/lib/storefront/helpers/open_graph_helper.rb +5 -0
- data/lib/storefront/helpers/page_helper.rb +73 -0
- data/lib/storefront/helpers/presenter_helper.rb +5 -0
- data/lib/storefront/helpers/request_helper.rb +66 -0
- data/lib/storefront/helpers/semantic/location_helper.rb +18 -0
- data/lib/storefront/helpers/semantic/time_helper.rb +14 -0
- data/lib/storefront/helpers/sidebar_helper.rb +27 -0
- data/lib/storefront/helpers/system_helper.rb +18 -0
- data/lib/storefront/helpers/table_helper.rb +38 -0
- data/lib/storefront/helpers/time_helper.rb +20 -0
- data/lib/storefront/helpers/url_helper.rb +32 -0
- data/lib/storefront/helpers/user_helper.rb +15 -0
- data/lib/storefront/helpers/widget_helper.rb +10 -0
- data/lib/storefront/helpers/workflow_helper.rb +50 -0
- data/lib/storefront/microdata/address.rb +7 -0
- data/lib/storefront/microdata/event.rb +13 -0
- data/lib/storefront/microdata/geo.rb +7 -0
- data/lib/storefront/microdata/organization.rb +7 -0
- data/lib/storefront/microdata/person.rb +7 -0
- data/lib/storefront/microformat/event.rb +7 -0
- data/lib/storefront/microformat/person.rb +7 -0
- data/lib/storefront/railtie.rb +28 -0
- data/lib/storefront/table.rb +191 -0
- data/rails/init.rb +1 -0
- data/test/form_helper_test.rb +5 -0
- data/test/support/mock_controller.rb +15 -0
- data/test/support/mock_response.rb +14 -0
- data/test/support/models.rb +0 -0
- data/test/test_helper.rb +34 -0
- metadata +111 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
module Storefront
|
2
|
+
module ImageHelper
|
3
|
+
def image_tag(source, options = {})
|
4
|
+
options.symbolize_keys!
|
5
|
+
|
6
|
+
src = options[:src] = path_to_image(source)
|
7
|
+
|
8
|
+
unless src =~ /^cid:/
|
9
|
+
options[:alt] = options.fetch(:alt) { File.basename(src, '.*').gsub(/-\d+$/, "").gsub("-", " ").humanize }
|
10
|
+
end
|
11
|
+
|
12
|
+
if size = options.delete(:size)
|
13
|
+
options[:width], options[:height] = size.split("x") if size =~ %{^\d+x\d+$}
|
14
|
+
end
|
15
|
+
|
16
|
+
if mouseover = options.delete(:mouseover)
|
17
|
+
options[:onmouseover] = "this.src='#{path_to_image(mouseover)}'"
|
18
|
+
options[:onmouseout] = "this.src='#{src}'"
|
19
|
+
end
|
20
|
+
|
21
|
+
tag("img", options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_logo(parent, size = "small", link = nil, lightbox = true)
|
25
|
+
if parent && parent.logo_id.present?
|
26
|
+
path = parent.logo.url(size.to_s) rescue nil
|
27
|
+
end
|
28
|
+
|
29
|
+
if path.blank?
|
30
|
+
path = "/images/vendors/no-logo.png"
|
31
|
+
alt = "No logo"
|
32
|
+
else
|
33
|
+
alt = "Logo for #{parent.is_a?(::Group) ? parent.name : parent.vendor_name}"
|
34
|
+
end
|
35
|
+
|
36
|
+
if parent && parent.logo
|
37
|
+
path << "?#{parent.logo.updated_at.to_i}"
|
38
|
+
end
|
39
|
+
if link
|
40
|
+
# , :width => 74, :height => 74
|
41
|
+
clazz = lightbox == true ? 'fancy-ajax logo' : 'logo'
|
42
|
+
link_to [content_tag(:span), image_tag(path, :class => "photo", :alt => alt, :title => alt)].join("").html_safe, link, :class => clazz, :"data-deal-id" => parent.id, :"data-ajax" => "false"
|
43
|
+
else
|
44
|
+
image_tag(path)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# http://snippets.dzone.com/posts/show/805
|
49
|
+
def read_image_size(path)
|
50
|
+
width, height = IO.read("#{Rails.root}/public/images/#{path}")[0x10..0x18].unpack('NN')
|
51
|
+
{:width => width, :height => height}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Storefront
|
2
|
+
module ListHelper
|
3
|
+
def nav(key, path = nil, attributes = {}, &block)
|
4
|
+
condition = extract_condition!(attributes)
|
5
|
+
return if condition == false
|
6
|
+
text = widget_text(key, :nav)
|
7
|
+
if attributes.has_key?(:current)
|
8
|
+
current = attributes.delete(:current) == true
|
9
|
+
else
|
10
|
+
current = on_current_page?(path)
|
11
|
+
end
|
12
|
+
li_class = "primary-navigation-item"
|
13
|
+
if current
|
14
|
+
li_class << " active"
|
15
|
+
attributes[:class] = [attributes[:class], "active"].compact.uniq.join(" ")
|
16
|
+
end
|
17
|
+
as = attributes.delete(:as) || :span
|
18
|
+
li_class << " #{attributes.delete(:li_class)}" if attributes[:li_class]
|
19
|
+
li_class = li_class.present? ? {:class => li_class} : nil
|
20
|
+
separator = attributes.delete(:separator)
|
21
|
+
checkbox = attributes.delete(:checkbox) == true
|
22
|
+
result = capture_haml do
|
23
|
+
haml_tag :li, li_class do
|
24
|
+
if checkbox
|
25
|
+
haml_tag :label, text.strip
|
26
|
+
haml_tag :input, :type => "checkbox"
|
27
|
+
else
|
28
|
+
if block_given?
|
29
|
+
case block.arity
|
30
|
+
when 1
|
31
|
+
yield(text.strip)
|
32
|
+
else
|
33
|
+
yield
|
34
|
+
end
|
35
|
+
elsif current && as == :span
|
36
|
+
haml_tag :span, text.strip, attributes
|
37
|
+
else
|
38
|
+
haml_concat link_to(text.strip, path, attributes)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
haml_tag :span, separator if separator
|
42
|
+
end
|
43
|
+
end
|
44
|
+
result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Storefront
|
2
|
+
module LocaleHelper
|
3
|
+
# t!(:"what.summary", :scope => :"reports.titles", :model => deal)
|
4
|
+
def t?(key, options = {})
|
5
|
+
return key if key.is_a?(::String)
|
6
|
+
model_names = options[:model_names]
|
7
|
+
model_names ||= options[:model].present? ? options[:model].class.ancestor_classes.map { |i| i.name.underscore } : []
|
8
|
+
allow_blank = options.delete(:allow_blank) == true
|
9
|
+
|
10
|
+
keys = [key.to_s]
|
11
|
+
if options[:try].present?
|
12
|
+
keys += Array(options[:default]).map do |extra_key|
|
13
|
+
"#{key}.#{extra_key}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
count = options.delete(:count)
|
18
|
+
# none, one, many, other
|
19
|
+
count_key = count != 1 ? :other : :one
|
20
|
+
|
21
|
+
if options.has_key?(:present) || options.has_key?(:past) || options.has_key?(:future)
|
22
|
+
if options[:future] == true
|
23
|
+
tense_key = :future
|
24
|
+
else
|
25
|
+
tense_key = (options.delete(:present) == true || options.delete(:past) == false) ? :present : :past
|
26
|
+
end
|
27
|
+
else
|
28
|
+
tense_key = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
defaults = []
|
32
|
+
|
33
|
+
keys.each do |key|
|
34
|
+
model_names.each do |model_name|
|
35
|
+
path = '{{model}}.{{key}}'
|
36
|
+
path.gsub!('{{model}}', model_name)
|
37
|
+
path.gsub!('{{key}}', key)
|
38
|
+
path.gsub!('..', '.')
|
39
|
+
defaults << path
|
40
|
+
end
|
41
|
+
|
42
|
+
path = '{{key}}'
|
43
|
+
path.gsub!('{{key}}', key)
|
44
|
+
path.gsub!('..', '.')
|
45
|
+
defaults << path
|
46
|
+
end
|
47
|
+
|
48
|
+
defaults.map!(&:to_sym)
|
49
|
+
defaults << ''
|
50
|
+
|
51
|
+
value = I18n.t(defaults.shift, options.merge(:default => defaults))
|
52
|
+
|
53
|
+
if value.is_a?(::Hash)
|
54
|
+
if value.has_key?(count_key)
|
55
|
+
value = value[count_key]
|
56
|
+
elsif value.has_key?(tense_key)
|
57
|
+
value = value[tense_key]
|
58
|
+
if value.is_a?(::Hash) && value.has_key?(count_key)
|
59
|
+
value = value[count_key]
|
60
|
+
end
|
61
|
+
elsif value.has_key?(count_key)
|
62
|
+
value = value[count_key]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if value.is_a?(::Hash)
|
67
|
+
if value.has_key?(:one)
|
68
|
+
value = value[:one]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
if value.is_a?(::Hash)
|
73
|
+
if value.has_key?(:present)
|
74
|
+
value = value[:present]
|
75
|
+
elsif value.has_key?(:past)
|
76
|
+
value = value[:past]
|
77
|
+
elsif value.has_key?(:future)
|
78
|
+
value = value[:future]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
value.blank? && !allow_blank ? key.to_s.split(".").last.titleize : value
|
83
|
+
end
|
84
|
+
|
85
|
+
# interpolate_hash(report, :scope => "reports", :begins_at_level => 3, :keys => {:bookmark => :selected})
|
86
|
+
def interpolate_hash(hash, options = {})
|
87
|
+
result = {}
|
88
|
+
hash.each do |key, value|
|
89
|
+
result[key.to_sym] = _interpolate_hash(key, value, {}, options)
|
90
|
+
end
|
91
|
+
result
|
92
|
+
end
|
93
|
+
|
94
|
+
protected
|
95
|
+
# This:
|
96
|
+
# {
|
97
|
+
# :who => {
|
98
|
+
# :title => "Who",
|
99
|
+
# :subtitle => "again?",
|
100
|
+
# :averages => {
|
101
|
+
# :title => "Averages",
|
102
|
+
# :first_time => {
|
103
|
+
# :title => "First Time",
|
104
|
+
# :value => 10
|
105
|
+
# }
|
106
|
+
# },
|
107
|
+
# :best => {
|
108
|
+
# :location => {
|
109
|
+
# :key => "work",
|
110
|
+
# :value => 80.0
|
111
|
+
# }
|
112
|
+
# }
|
113
|
+
# }
|
114
|
+
# }
|
115
|
+
#
|
116
|
+
# becomes...
|
117
|
+
#
|
118
|
+
# {
|
119
|
+
# :who => {
|
120
|
+
# :title => "Who",
|
121
|
+
# :subtitle => "again?",
|
122
|
+
# :averages => {
|
123
|
+
# :title => "Averages",
|
124
|
+
# :first_time => {
|
125
|
+
# :title => "First Time",
|
126
|
+
# :value => 10.0
|
127
|
+
# }
|
128
|
+
# },
|
129
|
+
# :best => {
|
130
|
+
# :title => "Most Popular"
|
131
|
+
# :location => {
|
132
|
+
# :title => "Location",
|
133
|
+
# :value => "Work (80%)"
|
134
|
+
# }
|
135
|
+
# }
|
136
|
+
# }
|
137
|
+
# }
|
138
|
+
#
|
139
|
+
# who.summary.title.past
|
140
|
+
# who.summary.title
|
141
|
+
# who.summary.past
|
142
|
+
# who.summary
|
143
|
+
def _interpolate_hash(key, object, result, options = {})
|
144
|
+
return object unless object.is_a?(::Hash)
|
145
|
+
key = key.to_s
|
146
|
+
title = object[:title] || object[:label]
|
147
|
+
subtitle = object[:subtitle]
|
148
|
+
|
149
|
+
title = t!(:"#{key}", options.merge(:try => :title))
|
150
|
+
title = key.to_s.split(".").last.titleize if title.blank? || title.is_a?(::Hash)
|
151
|
+
subtitle = t!(:"#{key}.subtitle", options.merge(:allow_blank => true))
|
152
|
+
|
153
|
+
# everything has to have a title
|
154
|
+
result[:title] = title
|
155
|
+
|
156
|
+
# not everything has to have a subtitle
|
157
|
+
result[:subtitle] = subtitle if subtitle.present?
|
158
|
+
|
159
|
+
# it's a leaf if we're at this point!
|
160
|
+
if object.has_key?(:value)
|
161
|
+
result[:value] = object[:value]
|
162
|
+
else
|
163
|
+
object.each do |child_key, child_value|
|
164
|
+
if child_value.is_a?(::Hash)
|
165
|
+
result[child_key.to_sym] = _interpolate_hash("#{key}.#{child_key}", child_value, {}, options)
|
166
|
+
else
|
167
|
+
result[child_key.to_sym] = child_value
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
result
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Storefront
|
2
|
+
module PageHelper
|
3
|
+
def page(options = {})
|
4
|
+
page_title(options)
|
5
|
+
end
|
6
|
+
|
7
|
+
# = page #=> figures out name from resource (inherited_resources)
|
8
|
+
# = page :step => 1 #=> prepends "Step 1: " to the title
|
9
|
+
# options => [:browser_title, :title, :clazz]
|
10
|
+
def page_title(options = {})
|
11
|
+
if options.is_a?(String)
|
12
|
+
title = browser_title = options
|
13
|
+
title_class = ""
|
14
|
+
elsif options.is_a?(Symbol)
|
15
|
+
title = browser_title = t("page.titles.#{options}")
|
16
|
+
else
|
17
|
+
title_class = options.delete(:title_class)
|
18
|
+
title = options.delete(:title)
|
19
|
+
browser_title = options.delete(:browser_title)
|
20
|
+
end
|
21
|
+
if title
|
22
|
+
capture_page_title((browser_title || title), (title || browser_title), :class => title_class)
|
23
|
+
else
|
24
|
+
return "" unless (defined?(:resource) || defined?(:collection))
|
25
|
+
cont = params[:controller].split("/").last
|
26
|
+
key = "#{cont}.#{params[:action]}"
|
27
|
+
default_key = "resource.#{params[:action]}"
|
28
|
+
parent_exists = parent rescue nil
|
29
|
+
parent_exists = !parent_exists.nil?
|
30
|
+
options[:name] = resource.name if resource rescue nil
|
31
|
+
options[:name] ||= parent.name if parent_exists
|
32
|
+
if parent_exists
|
33
|
+
key << ".nested"
|
34
|
+
default_key << ".nested"
|
35
|
+
end
|
36
|
+
if options[:clazz].blank?
|
37
|
+
options[:clazz] = cont.singularize.titleize
|
38
|
+
options[:clazz] = options[:clazz].pluralize if params[:action] == "index"
|
39
|
+
end
|
40
|
+
browser_title_options = options.merge(:default => t("#{default_key}.browser_title"))
|
41
|
+
page_title_options = options.merge(:default => t("#{default_key}.page_title"))
|
42
|
+
capture_page_title(
|
43
|
+
t("#{key}.browser_title", browser_title_options).strip.squeeze(" "),
|
44
|
+
t(key, page_title_options).strip.squeeze(" "),
|
45
|
+
:class => title_class
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def resource_title(options = {})
|
51
|
+
return options[:default] if options[:default]
|
52
|
+
return "" unless (defined?(:resource) || defined?(:collection))
|
53
|
+
options[:action] ||= params[:action]
|
54
|
+
cont = params[:controller].split("/").last
|
55
|
+
key = "#{cont}.#{options[:action]}"
|
56
|
+
options[:name] = resource.name if resource rescue nil
|
57
|
+
options[:clazz] = cont.singularize.camelize
|
58
|
+
options[:clazz] = options[:clazz].pluralize if options[:action] == "index"
|
59
|
+
page_title_options = options.merge(:default => t("resource.#{options[:action]}.page_title"))
|
60
|
+
t(key, page_title_options).strip.squeeze(" ")
|
61
|
+
end
|
62
|
+
|
63
|
+
def capture_page_title(browser_title, the_page_title, options = {})
|
64
|
+
result = capture_haml do
|
65
|
+
title browser_title
|
66
|
+
haml_tag :header, options.reject{|k,v| v.blank?}.merge(:id => "page-title") do
|
67
|
+
haml_tag :h1, the_page_title
|
68
|
+
end
|
69
|
+
end
|
70
|
+
result
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Storefront
|
2
|
+
module RequestHelper
|
3
|
+
def requesting?(expression)
|
4
|
+
case expression
|
5
|
+
when ::Symbol
|
6
|
+
(request.path =~ /#{expression}\/?$/).present?
|
7
|
+
else
|
8
|
+
(request.path =~ expression).present?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.clear_session
|
13
|
+
before_filter { |controller| controller.session.clear }
|
14
|
+
end
|
15
|
+
|
16
|
+
# ensure_domain :production => "site.com", :staging => "site-development.heroku.com"
|
17
|
+
def self.ensure_domain(options = {})
|
18
|
+
@ensure_domain_options = options.symbolize_keys
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def ensure_domain
|
23
|
+
domain = self.class.ensure_domain_options[Rails.env.to_sym]
|
24
|
+
return true if domain.blank?
|
25
|
+
redirect_to(request.protocol + domain + request.request_uri) if request.env['HTTP_HOST'] != domain
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.ensure_domain_options
|
30
|
+
@ensure_domain_options
|
31
|
+
end
|
32
|
+
|
33
|
+
def on_current_page?(options)
|
34
|
+
url_string = CGI.unescapeHTML(url_for(options))
|
35
|
+
request = controller.request
|
36
|
+
if url_string.index("?")
|
37
|
+
fullpath = request.fullpath
|
38
|
+
else
|
39
|
+
fullpath = request.fullpath.split('?').first
|
40
|
+
end
|
41
|
+
if url_string =~ /^\w+:\/\//
|
42
|
+
url_string == "#{request.protocol}#{request.host_with_port}#{fullpath}"
|
43
|
+
else
|
44
|
+
url_string == fullpath.gsub(/&sort_by=.*/, "").gsub(/&vendor_name=.*/, "")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def with_subdomain(subdomain)
|
49
|
+
subdomain = (subdomain || "")
|
50
|
+
subdomain += "." unless subdomain.empty?
|
51
|
+
[subdomain, request.domain(2), request.port_string].join
|
52
|
+
end
|
53
|
+
|
54
|
+
def url_for(options = {})
|
55
|
+
if options.kind_of?(Hash) && options.has_key?(:subdomain)
|
56
|
+
options[:host] = with_subdomain(options.delete(:subdomain))
|
57
|
+
end
|
58
|
+
|
59
|
+
if options.is_a?(Symbol) && options == :up
|
60
|
+
request.path.split("/")[0..-2].join("/")
|
61
|
+
else
|
62
|
+
super(options)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Storefront
|
2
|
+
module Semantic
|
3
|
+
module LocationHelper
|
4
|
+
def semantic_geo_tag(lat, lng, options = {})
|
5
|
+
capture_haml do
|
6
|
+
haml_tag :span, :itemprop => "geo", :itemtype => "http://data-vocabulary.org/Geo" do
|
7
|
+
haml_tag :span, :itemprop => "latitude" do
|
8
|
+
haml_tag :span, lat, :class => "value-title"
|
9
|
+
end
|
10
|
+
haml_tag :span, :itemprop => "longitude" do
|
11
|
+
haml_tag :span, lng, :class => "value-title"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|