storefront 0.2.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/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,14 @@
|
|
1
|
+
module Storefront
|
2
|
+
module Semantic
|
3
|
+
module TimeHelper
|
4
|
+
def semantic_time_tag(value, time, options = {})
|
5
|
+
capture_haml do
|
6
|
+
haml_tag :time, :class => "dtstart", :itemprop => "startDate", :title => time.xmlschema, :datetime => time.xmlschema do
|
7
|
+
haml_tag :span, :class => "value-title", :title => time.xmlschema
|
8
|
+
haml_concat value
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Storefront
|
2
|
+
module SidebarHelper
|
3
|
+
def sidebar_for(record, options = {}, &block)
|
4
|
+
@sidebar_record = record
|
5
|
+
concat(capture(&block))
|
6
|
+
@sidebar_record = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def sidebar(*args)
|
10
|
+
locals = args.extract_options!
|
11
|
+
path = args.shift
|
12
|
+
if path.blank?
|
13
|
+
path = resource.class.name.underscore.pluralize.to_sym rescue nil
|
14
|
+
end
|
15
|
+
if path.is_a?(Symbol)
|
16
|
+
path = [path_namespace, path.to_s, "sidebar"].compact.join("/")
|
17
|
+
end
|
18
|
+
content_for :sidebar do
|
19
|
+
render :partial => path, :locals => locals
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def sidebar_record
|
24
|
+
@sidebar_record
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Storefront
|
2
|
+
module SystemHelper
|
3
|
+
def windows?
|
4
|
+
# Can't match for just 'win' cause it will match darwin as well.
|
5
|
+
(/win32|mswin|mingw/).match(RUBY_PLATFORM) ? true : false
|
6
|
+
end
|
7
|
+
|
8
|
+
# Works on Debian and Ubuntu, don't have anything else to test on.
|
9
|
+
def linux?
|
10
|
+
(/linux/).match(RUBY_PLATFORM) ? true : false
|
11
|
+
end
|
12
|
+
|
13
|
+
# Works on my MacBook Pro, don't have anything else to test on,
|
14
|
+
def mac?
|
15
|
+
(/darwin/).match(RUBY_PLATFORM) ? true : false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Storefront
|
2
|
+
module TableHelper
|
3
|
+
def table_for(*args, &block)
|
4
|
+
Storefront::Table.new(self, *args, &block).content
|
5
|
+
end
|
6
|
+
|
7
|
+
def table_query_row_class
|
8
|
+
["search-row", query_params.except("page", "sort").blank? ? nil : "search-results"].compact.join(" ")
|
9
|
+
end
|
10
|
+
|
11
|
+
def link_to_sort(title, attribute, options = {})
|
12
|
+
sort_param = sort_value(attribute, opposite_sort_direction(attribute))
|
13
|
+
link_to title, with_params(request.path, :sort => sort_param), options
|
14
|
+
end
|
15
|
+
|
16
|
+
def next_page_path(collection)
|
17
|
+
with_params(request.path, :page => collection.next_page)
|
18
|
+
end
|
19
|
+
|
20
|
+
def prev_page_path(collection)
|
21
|
+
with_params(request.path, :page => collection.prev_page)
|
22
|
+
end
|
23
|
+
|
24
|
+
def first_page_path(collection)
|
25
|
+
with_params(request.path, :page => 1)
|
26
|
+
end
|
27
|
+
|
28
|
+
def last_page_path(collection)
|
29
|
+
with_params(request.path, :page => collection.last_page)
|
30
|
+
end
|
31
|
+
|
32
|
+
def current_page_num
|
33
|
+
page = params[:page] ? params[:page].to_i : 1
|
34
|
+
page = 1 if page < 1
|
35
|
+
page
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Storefront
|
2
|
+
module TimeHelper
|
3
|
+
# (new Date()).getTimezoneOffset() in JavaScript returns (UTC - localtime) in
|
4
|
+
# minutes, while ActiveSupport::TimeZone expects (localtime - UTC) in seconds.
|
5
|
+
def set_time_zone
|
6
|
+
offset = (cookies[:timezone] || 0).to_i * -60
|
7
|
+
# User.time_zone = ActiveSupport::TimeZone[-min.minutes]
|
8
|
+
User.time_zone = ActiveSupport::TimeZone.us_zones.find { |z| z.utc_offset == offset.to_i }
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def record_post_time
|
13
|
+
cookies[:last_post_at] = Time.zone.now.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
def html5_time(date_or_time)
|
17
|
+
date_or_time.acts_like?(:time) ? date_or_time.xmlschema : date_or_time.rfc3339
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Storefront
|
2
|
+
module UrlHelper
|
3
|
+
def current_subdomain
|
4
|
+
subdomain = request.subdomain.to_s.split(".").first
|
5
|
+
subdomain = nil if subdomain == App.name
|
6
|
+
(subdomain.blank? || subdomain == "www") ? nil : subdomain
|
7
|
+
end
|
8
|
+
|
9
|
+
def path_namespace?(*args)
|
10
|
+
args.present? ? args.any? { |is| path_namespace == is.to_s } : path_namespace.present?
|
11
|
+
end
|
12
|
+
|
13
|
+
def path_namespace
|
14
|
+
if @path_namespace.nil?
|
15
|
+
if current_subdomain.present?
|
16
|
+
@path_namespace = current_subdomain
|
17
|
+
elsif params[:path_namespace]
|
18
|
+
@path_namespace = params[:path_namespace]
|
19
|
+
else
|
20
|
+
parts = params[:controller].split("/")
|
21
|
+
@path_namespace = parts.length > 1 ? parts.first : ""
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
@path_namespace
|
26
|
+
end
|
27
|
+
|
28
|
+
def with_current_params(path_method, *args)
|
29
|
+
send path_method, *(args << Rack::Utils.parse_query(request.query_string).merge(args.extract_options!))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Storefront
|
2
|
+
module UserHelper
|
3
|
+
def globalize_current_user
|
4
|
+
current_user.request = request if current_user
|
5
|
+
User.current = current_user
|
6
|
+
Rails.logger.info "Current User: [#{ip_address}] #{current_user.present? ? current_user.email : 'Unknown'} (#{user_agent})"
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def deglobalize_current_user
|
11
|
+
User.current = nil
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Storefront
|
2
|
+
module WidgetHelper
|
3
|
+
def widget(*args, &block)
|
4
|
+
options = args.extract_options!
|
5
|
+
options.reverse_merge(:locale => nil)
|
6
|
+
options.merge!(:yielded_content => block_given? ? capture(&block) : nil)
|
7
|
+
render(:partial => "shared/widgets/#{name}", :locals => options)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Storefront
|
2
|
+
module WorkflowHelper
|
3
|
+
def current_workflow
|
4
|
+
params[:flow]
|
5
|
+
end
|
6
|
+
|
7
|
+
def flow?(*args)
|
8
|
+
args.present? ? args.any? { |flow| current_workflow == flow.to_s } : current_workflow.present?
|
9
|
+
end
|
10
|
+
|
11
|
+
def workflow_steps(current, *labels)
|
12
|
+
steps = labels.flatten.map do |label|
|
13
|
+
if label.is_a?(Hash)
|
14
|
+
label.symbolize_keys
|
15
|
+
else
|
16
|
+
{:title => label, :description => ""}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
steps.each_with_index do |step, index|
|
20
|
+
step[:active] = index == (current - 1)
|
21
|
+
end
|
22
|
+
steps
|
23
|
+
end
|
24
|
+
|
25
|
+
def workflow_step(label, current, desired)
|
26
|
+
image_name = "step_#{desired}"
|
27
|
+
image_name << "_active" if current == desired
|
28
|
+
image_name << ".png"
|
29
|
+
td_class = current == desired ? "step_active" : "step"
|
30
|
+
result = capture_haml do
|
31
|
+
haml_tag :td, :class => :number do
|
32
|
+
haml_tag :img, :class => :step_number, :src => "/images/#{image_name}"
|
33
|
+
end
|
34
|
+
haml_tag :td, :class => td_class do
|
35
|
+
haml_concat label
|
36
|
+
end
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
|
41
|
+
def next_step_tag(resource = self.resource)
|
42
|
+
result = capture_haml do
|
43
|
+
haml_concat hidden_field_tag(:event, current_step)
|
44
|
+
if resource && resource.id
|
45
|
+
haml_concat hidden_field_tag(:id, resource.id)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# https://gist.github.com/af7e572c2dc973add221
|
2
|
+
module Storefront
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
initializer "storefront.insert_into_action_view" do
|
5
|
+
ActiveSupport.on_load :action_view do
|
6
|
+
base = "#{File.expand_path(File.dirname(__FILE__))}/helpers"
|
7
|
+
Dir["#{base}/*"].each do |path|
|
8
|
+
next if File.directory?(path)
|
9
|
+
constant_name = File.basename(path, File.extname(path)).gsub("/", "::").camelize
|
10
|
+
ActionView::Base.send :include, "Storefront::#{constant_name}".constantize
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
ActiveSupport.on_load :active_record do
|
15
|
+
#
|
16
|
+
end
|
17
|
+
|
18
|
+
ActiveSupport.on_load :action_controller do
|
19
|
+
base = "#{File.expand_path(File.dirname(__FILE__))}/helpers"
|
20
|
+
Dir["#{base}/*"].each do |path|
|
21
|
+
next if File.directory?(path) || File.basename(path) =~ /(form|table|dashboard)/
|
22
|
+
constant_name = File.basename(path, File.extname(path)).gsub("/", "::").camelize
|
23
|
+
ActionController::Base.send :include, "Storefront::#{constant_name}".constantize
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
module Storefront
|
2
|
+
class Table
|
3
|
+
attr_reader :content, :template, :key
|
4
|
+
|
5
|
+
def initialize(template, *args, &block)
|
6
|
+
@template = template
|
7
|
+
options = args.extract_options!
|
8
|
+
record_or_key = args.shift
|
9
|
+
@key = record_key(record_or_key)
|
10
|
+
@row_index = 0
|
11
|
+
@cell_index = 0
|
12
|
+
@scope = :table
|
13
|
+
@headers = []
|
14
|
+
options[:summary] ||= "Table for #{key.titleize}"
|
15
|
+
options[:class] = ["data-table", options[:class]].compact.uniq.join(" ")
|
16
|
+
options[:role] = :grid
|
17
|
+
data = options.delete(:data) || {}
|
18
|
+
data[:url] = options[:url] || @template.controller.request.path
|
19
|
+
data[:for] = options[:for] || options[:model] || @key
|
20
|
+
data[:total] = options[:total] if options[:total]
|
21
|
+
data[:page] = options[:page] if options[:page]
|
22
|
+
data[:count] = options[:count] if options[:count]
|
23
|
+
aria = options.delete(:aria) || {}
|
24
|
+
aria[:"aria-multiselectable"] = false unless aria.has_key?(:"aria-multiselectable") || options[:multiselect] == true
|
25
|
+
options[:data] = data
|
26
|
+
options[:id] ||= "#{record_or_key.to_s}-table"
|
27
|
+
|
28
|
+
@content = template.capture_haml do
|
29
|
+
template.haml_tag :table, options do
|
30
|
+
yield(self)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def caption
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# scope='col'
|
40
|
+
def head(attributes = {}, &block)
|
41
|
+
@hide_header = attributes.delete(:visible) == false
|
42
|
+
template.capture_haml do
|
43
|
+
@row_index = 0
|
44
|
+
@scope = :head
|
45
|
+
template.haml_tag :thead, attributes, &block
|
46
|
+
@row_index = 0
|
47
|
+
@scope = :table
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# scope='row'
|
52
|
+
# <td headers='x'/>
|
53
|
+
def body(attributes = {}, &block)
|
54
|
+
template.capture_haml do
|
55
|
+
@row_index = 0
|
56
|
+
@scope = :body
|
57
|
+
template.haml_tag :tbody, attributes, &block
|
58
|
+
@row_index = 0
|
59
|
+
@scope = :table
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def foot(attributes = {}, &block)
|
64
|
+
template.capture_haml do
|
65
|
+
@row_index = 0
|
66
|
+
@scope = :foot
|
67
|
+
template.haml_tag :tfoot, attributes, &block
|
68
|
+
@row_index = 0
|
69
|
+
@scope = :table
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def row(*args, &block)
|
74
|
+
attributes = args.extract_options!
|
75
|
+
if @scope == :body
|
76
|
+
attributes[:class] = [template.cycle("odd", "even"), attributes[:class]].compact.uniq.join(" ")
|
77
|
+
end
|
78
|
+
attributes[:role] = :row
|
79
|
+
attributes[:scope] = :row
|
80
|
+
template.capture_haml do
|
81
|
+
@row_index += 1
|
82
|
+
@cell_index = 0
|
83
|
+
template.haml_tag :tr, attributes, &block
|
84
|
+
@cell_index = 0
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def column(*args, &block)
|
89
|
+
attributes = args.extract_options!
|
90
|
+
value = args.shift
|
91
|
+
attributes[:id] ||= id_for(:header, key, value, @row_index, @cell_index)
|
92
|
+
[:width, :height].each do |size|
|
93
|
+
attributes[size] = pixelate(attributes[size]) unless attributes[size].nil?
|
94
|
+
end
|
95
|
+
@headers.push(attributes[:id])
|
96
|
+
|
97
|
+
template.capture_haml do
|
98
|
+
template.haml_tag :col, attributes
|
99
|
+
@cell_index += 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# direction => "ascending"
|
104
|
+
# valid directions: ascending, descending, none, other
|
105
|
+
# abbr is what the header controls (for sorting)
|
106
|
+
def header(*args, &block)
|
107
|
+
attributes = args.extract_options!
|
108
|
+
value = args.shift
|
109
|
+
if value.is_a?(::Symbol)
|
110
|
+
attributes[:abbr] ||= value.to_s
|
111
|
+
end
|
112
|
+
# aria-selected if sorted
|
113
|
+
attributes[:role] = :columnheader
|
114
|
+
attributes[:id] ||= id_for(:header, key, value, @row_index, @cell_index)
|
115
|
+
attributes[:scope] = :col
|
116
|
+
attributes[:abbr] ||= attributes.delete(:for) if attributes.has_key?(:for)
|
117
|
+
[:width, :height].each do |size|
|
118
|
+
attributes[size] = pixelate(attributes[size]) unless attributes[size].nil?
|
119
|
+
end
|
120
|
+
sort = attributes.delete(:sort) == true
|
121
|
+
label = attributes.delete(:label) || (value.is_a?(::String) ? value.strip : value.to_s.titleize)
|
122
|
+
|
123
|
+
if sort
|
124
|
+
attributes[:class] = [attributes[:class], attributes.delete(:sort_class) || "sortable"].compact.uniq.join(" ")
|
125
|
+
attributes[:direction] ||= template.sort_class(value)
|
126
|
+
end
|
127
|
+
|
128
|
+
direction = attributes.delete(:direction)
|
129
|
+
if direction.present?
|
130
|
+
attributes[:"aria-sort"] = direction
|
131
|
+
attributes[:class] = [attributes[:class], direction].join(" ")
|
132
|
+
attributes[:"aria-selected"] = true
|
133
|
+
else
|
134
|
+
attributes[:"aria-sort"] = "none"
|
135
|
+
attributes[:"aria-selected"] = false
|
136
|
+
end
|
137
|
+
|
138
|
+
@headers.push(attributes[:id])
|
139
|
+
template.capture_haml do
|
140
|
+
if block_given?
|
141
|
+
template.haml_tag :th, attributes, &block
|
142
|
+
else
|
143
|
+
if sort
|
144
|
+
template.haml_tag :th, attributes do
|
145
|
+
template.haml_concat template.link_to_sort(label, value)
|
146
|
+
end
|
147
|
+
else
|
148
|
+
template.haml_tag :th, label, attributes
|
149
|
+
end
|
150
|
+
end
|
151
|
+
@cell_index += 1
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def cell(*args, &block)
|
156
|
+
attributes = args.extract_options!
|
157
|
+
value = args.shift
|
158
|
+
attributes[:role] = :gridcell
|
159
|
+
attributes[:id] ||= id_for(:cell, key, value, @row_index, @cell_index)
|
160
|
+
#attributes[:"aria-describedby"] = @headers[@cell_index]
|
161
|
+
attributes[:headers] = @headers[@cell_index]
|
162
|
+
template.capture_haml do
|
163
|
+
if block_given?
|
164
|
+
template.haml_tag :td, attributes, &block
|
165
|
+
else
|
166
|
+
template.haml_tag :td, value.to_s.strip, attributes
|
167
|
+
end
|
168
|
+
@cell_index += 1
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def record_key(record_or_key)
|
173
|
+
if record_or_key.is_a?(String) || record_or_key.is_a?(Symbol)
|
174
|
+
record_or_key.to_s
|
175
|
+
else
|
176
|
+
record_or_key.class.name
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def id_for(type, key, value, row_index = @row_index, column_index = @column_index)
|
181
|
+
[key, type, row_index, column_index].compact.map do |node|
|
182
|
+
node.to_s.gsub(/[\s_]/, "-")
|
183
|
+
end.join("-")
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
def pixelate(value)
|
188
|
+
value.is_a?(::String) ? value : "#{value}px"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|