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.
Files changed (59) hide show
  1. data/Rakefile +76 -0
  2. data/init.rb +1 -0
  3. data/lib/storefront.rb +21 -0
  4. data/lib/storefront/dashboard.rb +184 -0
  5. data/lib/storefront/form.rb +65 -0
  6. data/lib/storefront/form/elements.rb +101 -0
  7. data/lib/storefront/form/errors.rb +57 -0
  8. data/lib/storefront/form/fields.rb +420 -0
  9. data/lib/storefront/form/hints.rb +18 -0
  10. data/lib/storefront/form/inputs.rb +254 -0
  11. data/lib/storefront/form/labels.rb +81 -0
  12. data/lib/storefront/form/model.rb +84 -0
  13. data/lib/storefront/helpers/attribute_helper.rb +60 -0
  14. data/lib/storefront/helpers/body_helper.rb +18 -0
  15. data/lib/storefront/helpers/browser_helper.rb +54 -0
  16. data/lib/storefront/helpers/cache_helper.rb +25 -0
  17. data/lib/storefront/helpers/collection_helper.rb +14 -0
  18. data/lib/storefront/helpers/component_helper.rb +35 -0
  19. data/lib/storefront/helpers/dashboard_helper.rb +37 -0
  20. data/lib/storefront/helpers/debug_helper.rb +11 -0
  21. data/lib/storefront/helpers/definition_list_helper.rb +29 -0
  22. data/lib/storefront/helpers/error_helper.rb +11 -0
  23. data/lib/storefront/helpers/flash_helper.rb +14 -0
  24. data/lib/storefront/helpers/form_helper.rb +8 -0
  25. data/lib/storefront/helpers/format_helper.rb +59 -0
  26. data/lib/storefront/helpers/head_helper.rb +229 -0
  27. data/lib/storefront/helpers/image_helper.rb +54 -0
  28. data/lib/storefront/helpers/list_helper.rb +47 -0
  29. data/lib/storefront/helpers/locale_helper.rb +175 -0
  30. data/lib/storefront/helpers/open_graph_helper.rb +5 -0
  31. data/lib/storefront/helpers/page_helper.rb +73 -0
  32. data/lib/storefront/helpers/presenter_helper.rb +5 -0
  33. data/lib/storefront/helpers/request_helper.rb +66 -0
  34. data/lib/storefront/helpers/semantic/location_helper.rb +18 -0
  35. data/lib/storefront/helpers/semantic/time_helper.rb +14 -0
  36. data/lib/storefront/helpers/sidebar_helper.rb +27 -0
  37. data/lib/storefront/helpers/system_helper.rb +18 -0
  38. data/lib/storefront/helpers/table_helper.rb +38 -0
  39. data/lib/storefront/helpers/time_helper.rb +20 -0
  40. data/lib/storefront/helpers/url_helper.rb +32 -0
  41. data/lib/storefront/helpers/user_helper.rb +15 -0
  42. data/lib/storefront/helpers/widget_helper.rb +10 -0
  43. data/lib/storefront/helpers/workflow_helper.rb +50 -0
  44. data/lib/storefront/microdata/address.rb +7 -0
  45. data/lib/storefront/microdata/event.rb +13 -0
  46. data/lib/storefront/microdata/geo.rb +7 -0
  47. data/lib/storefront/microdata/organization.rb +7 -0
  48. data/lib/storefront/microdata/person.rb +7 -0
  49. data/lib/storefront/microformat/event.rb +7 -0
  50. data/lib/storefront/microformat/person.rb +7 -0
  51. data/lib/storefront/railtie.rb +28 -0
  52. data/lib/storefront/table.rb +191 -0
  53. data/rails/init.rb +1 -0
  54. data/test/form_helper_test.rb +5 -0
  55. data/test/support/mock_controller.rb +15 -0
  56. data/test/support/mock_response.rb +14 -0
  57. data/test/support/models.rb +0 -0
  58. data/test/test_helper.rb +34 -0
  59. 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,7 @@
1
+ module Storefront
2
+ module Microdata
3
+ class Address
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Storefront
2
+ module Microdata
3
+ class Event
4
+ def initialize(options = {})
5
+
6
+ end
7
+
8
+ def root_attributes
9
+ {:itemscope => "http://data-vocabulary.org/Event"}
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module Storefront
2
+ module Microdata
3
+ class Geo
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Storefront
2
+ module Microdata
3
+ class Organization
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Storefront
2
+ module Microdata
3
+ class Person
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Storefront
2
+ module Microformat
3
+ class Event
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Storefront
2
+ module Microformat
3
+ class Person
4
+
5
+ end
6
+ end
7
+ 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