storefront 0.2.0

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