lux-fw 0.1.17 → 0.1.35
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/bin/cli/am +38 -29
- data/bin/cli/assets +8 -4
- data/bin/cli/exceptions +6 -6
- data/bin/cli/generate +0 -0
- data/bin/cli/get +0 -0
- data/bin/cli/nginx +11 -5
- data/bin/cli/routes +0 -0
- data/bin/cli/systemd +36 -0
- data/bin/forever +0 -0
- data/bin/job_que +0 -0
- data/bin/lux +1 -0
- data/lib/common/base32.rb +0 -0
- data/lib/common/class_attributes.rb +13 -4
- data/lib/common/crypt.rb +6 -10
- data/lib/common/dynamic_class.rb +23 -0
- data/lib/common/generic_model.rb +0 -0
- data/lib/common/hash_with_indifferent_access.rb +352 -0
- data/lib/common/method_attr.rb +69 -0
- data/lib/lux/api/api.rb +26 -27
- data/lib/lux/api/lib/application_api.rb +26 -7
- data/lib/lux/api/lib/doc_builder.rb +18 -17
- data/lib/lux/api/lib/dsl.rb +23 -41
- data/lib/lux/api/lib/error.rb +3 -0
- data/lib/lux/api/lib/model_api.rb +22 -20
- data/lib/lux/api/lib/rescue.rb +5 -15
- data/lib/lux/api/lib/response.rb +46 -0
- data/lib/lux/cache/cache.rb +13 -6
- data/lib/lux/cell/cell.rb +3 -14
- data/lib/lux/config/config.rb +4 -3
- data/lib/lux/controller/controller.rb +3 -3
- data/lib/lux/controller/lib/nav.rb +6 -2
- data/lib/lux/error/error.rb +15 -14
- data/lib/lux/helper/helper.rb +5 -5
- data/lib/lux/helper/lib/html_tag.rb +67 -0
- data/lib/lux/html/lib/input_types.rb +26 -16
- data/lib/lux/lib/lux.rb +51 -0
- data/lib/lux/lux.rb +5 -52
- data/lib/lux/page/lib/response.rb +178 -0
- data/lib/lux/page/page.rb +72 -51
- data/lib/lux/rescue_from/rescue_from.rb +8 -6
- data/lib/lux/template/template.rb +1 -0
- data/lib/lux-fw.rb +2 -0
- data/lib/overload/array.rb +4 -0
- data/lib/overload/date.rb +2 -0
- data/lib/overload/hash.rb +19 -10
- data/lib/overload/it.rb +29 -0
- data/lib/overload/object.rb +3 -19
- data/lib/overload/r.rb +53 -0
- data/lib/overload/string.rb +5 -6
- data/lib/overload/string_inflections.rb +4 -3
- data/lib/plugins/assets/assets_plug.rb +9 -4
- data/lib/plugins/assets/helper_module_adapter.rb +4 -2
- data/lib/plugins/db_helpers/link_plugin.rb +2 -2
- data/lib/plugins/db_logger/init.rb +1 -1
- data/lib/vendor/mini_assets/lib/asset/css.rb +19 -0
- data/lib/vendor/mini_assets/lib/asset/js.rb +17 -0
- data/lib/vendor/mini_assets/lib/asset.rb +71 -0
- data/lib/vendor/mini_assets/lib/base/javascript.rb +13 -0
- data/lib/vendor/mini_assets/lib/base/stylesheet.rb +5 -0
- data/lib/vendor/mini_assets/lib/base.rb +69 -0
- data/lib/vendor/mini_assets/lib/manifest.rb +18 -0
- data/lib/vendor/mini_assets/lib/opts.rb +16 -0
- data/lib/vendor/mini_assets/mini_assets.rb +74 -0
- metadata +23 -10
- data/lib/common/class_method_params.rb +0 -94
- data/lib/overload/hash_wia.rb +0 -282
- data/lib/overload/inflections.rb +0 -199
- data/lib/vendor/mini_assets/mini_asset/base.rb +0 -167
- data/lib/vendor/mini_assets/mini_asset/css.rb +0 -38
- data/lib/vendor/mini_assets/mini_asset/js.rb +0 -38
- data/lib/vendor/mini_assets/mini_asset.rb +0 -31
data/lib/lux/api/lib/dsl.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
class Lux::Api
|
2
|
-
|
3
2
|
# name 'Show user data'
|
4
3
|
# param :email, type: :email, req: false
|
5
4
|
# param :pass
|
@@ -8,56 +7,41 @@ class Lux::Api
|
|
8
7
|
# @user.slice(:id, :name, :avatar, :email)
|
9
8
|
# end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def param(field, type=String, opts={})
|
24
|
-
opts = type.is_a?(Hash) ? type : opts.merge(type: type)
|
25
|
-
opts[:name] = field
|
26
|
-
opts[:req] = opts[:req].class.name == 'FalseClass' ? false : true
|
27
|
-
opts[:type] ||= String
|
28
|
-
|
29
|
-
ClassMethodParams.add_param self, :param, opts
|
30
|
-
end
|
10
|
+
# helper for standard definition of parametars
|
11
|
+
# param :o_id
|
12
|
+
# param :o_id, Integer
|
13
|
+
# param :o_id, Integer, req: false
|
14
|
+
# param :o_id, req: false
|
15
|
+
method_attr :param do |field, type=String, opts={}|
|
16
|
+
opts = type.is_a?(Hash) ? type : opts.merge(type: type)
|
17
|
+
opts[:name] = field
|
18
|
+
opts[:req] = true if opts[:req].nil?
|
19
|
+
opts[:type] ||= String
|
20
|
+
opts
|
21
|
+
end
|
31
22
|
|
32
|
-
|
33
|
-
|
34
|
-
ClassMethodParams.add_param self, :name, name
|
35
|
-
end
|
23
|
+
# helper for standard definition of name
|
24
|
+
method_attr :name
|
36
25
|
|
37
|
-
|
38
|
-
|
39
|
-
ClassMethodParams.add_param self, :description, name
|
40
|
-
end
|
41
|
-
end
|
26
|
+
# helper for standard definition of description
|
27
|
+
method_attr :data
|
42
28
|
|
43
29
|
###
|
44
30
|
|
45
31
|
def check_params_and_mock_instance_variables action
|
46
|
-
|
47
|
-
|
48
|
-
if opts && opts[:param]
|
49
|
-
local = opts[:param].inject({}) { |h, el| o=el.dup; h[o.delete(:name)] = o; h }
|
32
|
+
@method_attr = self.class.method_attr[action] || {}
|
50
33
|
|
51
|
-
|
34
|
+
# params check if framework default
|
35
|
+
if @method_attr[:param]
|
36
|
+
local = @method_attr[:param].inject({}) { |h, el| o=el.dup; h[o.delete(:name)] = o; h }
|
37
|
+
rules = Typero.new local
|
52
38
|
errors = rules.validate(@params)
|
53
39
|
|
54
40
|
if errors.keys.length > 0
|
55
41
|
raise ArgumentError.new(errors.values.to_sentence) unless Lux.page
|
56
42
|
|
57
|
-
Lux.page.status
|
58
|
-
|
59
|
-
@response[:errors] = errors
|
60
|
-
return false
|
43
|
+
Lux.page.status 400
|
44
|
+
return response.error errors.values.to_sentence
|
61
45
|
end
|
62
46
|
|
63
47
|
# define local prefixed @_ variables
|
@@ -66,8 +50,6 @@ class Lux::Api
|
|
66
50
|
eval "@_#{key.downcase.gsub(/[^\w]/,'_')} = value" if key.length < 15 && value.present? && key =~ /^[\w]+$/
|
67
51
|
end
|
68
52
|
end
|
69
|
-
|
70
|
-
true
|
71
53
|
end
|
72
54
|
|
73
55
|
end
|
@@ -56,12 +56,12 @@ class ModelApi < ApplicationApi
|
|
56
56
|
return if report_errros_if_any @object
|
57
57
|
|
58
58
|
if @object.id
|
59
|
-
|
59
|
+
message '%s created' % @class_name.capitalize
|
60
60
|
else
|
61
61
|
error 'object not created, error unknown'
|
62
62
|
end
|
63
63
|
|
64
|
-
|
64
|
+
response.meta :path, @object.path if @object.respond_to?(:path)
|
65
65
|
|
66
66
|
@object.attributes
|
67
67
|
end
|
@@ -76,8 +76,8 @@ class ModelApi < ApplicationApi
|
|
76
76
|
can? :update, @object
|
77
77
|
@object.save if @object.valid?
|
78
78
|
report_errros_if_any @object
|
79
|
-
|
80
|
-
|
79
|
+
response.message '%s updated' % @class_name
|
80
|
+
response.meta :path, @object.path if @object.respond_to?(:path)
|
81
81
|
@object.attributes
|
82
82
|
end
|
83
83
|
|
@@ -88,15 +88,19 @@ class ModelApi < ApplicationApi
|
|
88
88
|
|
89
89
|
if @object.respond_to?(:is_active)
|
90
90
|
@object.update is_active: false
|
91
|
-
|
91
|
+
|
92
|
+
message 'Object deleted (exists in trashcan)'
|
92
93
|
elsif @object.respond_to?(:active)
|
93
94
|
@object.update active: false
|
94
|
-
|
95
|
+
|
96
|
+
message 'Object deleted (exists in trashcan)'
|
95
97
|
else
|
96
98
|
@object.destroy
|
97
|
-
|
99
|
+
message '%s deleted' % @object.class.name
|
98
100
|
end
|
101
|
+
|
99
102
|
report_errros_if_any @object
|
103
|
+
|
100
104
|
@object.attributes
|
101
105
|
end
|
102
106
|
|
@@ -112,26 +116,24 @@ class ModelApi < ApplicationApi
|
|
112
116
|
error "No is_active, can't undelete"
|
113
117
|
end
|
114
118
|
|
115
|
-
|
119
|
+
response.message = 'Object raised from the dead.'
|
116
120
|
end
|
117
121
|
|
118
|
-
def report_errros_if_any
|
119
|
-
@response[:object] = obj.class.to_s.tableize.singularize
|
120
|
-
@response[:objects] = obj.class.to_s.tableize
|
121
|
-
|
122
|
+
def report_errros_if_any obj
|
122
123
|
if obj.errors.count > 0
|
123
|
-
|
124
|
-
@response[:errors] = {}
|
125
|
-
for k,v in obj.errors
|
124
|
+
for k, v in obj.errors
|
126
125
|
desc = v.join(', ')
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
126
|
+
|
127
|
+
response.error k, desc
|
128
|
+
response.error desc
|
129
|
+
# desc = "#{k} #{desc}" if desc.starts_with?('is ')
|
131
130
|
end
|
132
|
-
|
131
|
+
|
132
|
+
Lux.page.status 400
|
133
|
+
|
133
134
|
return true
|
134
135
|
end
|
136
|
+
|
135
137
|
false
|
136
138
|
end
|
137
139
|
|
data/lib/lux/api/lib/rescue.rb
CHANGED
@@ -1,18 +1,8 @@
|
|
1
|
-
Lux::Api.
|
1
|
+
Lux::Api.rescue_from(:default) do |msg|
|
2
|
+
response.error msg
|
2
3
|
|
3
|
-
|
4
|
-
Lux.
|
5
|
-
|
6
|
-
data = { error:msg }
|
7
|
-
|
8
|
-
if Lux.dev? && $!.class != StandardError
|
9
|
-
data[:backtrace] = $!.backtrace.reject{ |el| el.index('/gems/') }.map{ |el| el.sub(Lux.root.to_s, '') }
|
10
|
-
ap data[:backtrace]
|
11
|
-
end
|
12
|
-
|
13
|
-
ApplicationApi.new.decorate_response!(data)
|
14
|
-
|
15
|
-
Lux.page.body data
|
4
|
+
if Lux.dev? && $!.class != Lux::Api::Error
|
5
|
+
data[:backtrace] = $!.backtrace.reject{ |el| el.index('/gems/') }.map{ |el| el.sub(Lux.root.to_s, '') }
|
6
|
+
ap data[:backtrace]
|
16
7
|
end
|
17
|
-
|
18
8
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Lux::Api::Response
|
2
|
+
attr_accessor :data
|
3
|
+
attr_accessor :message
|
4
|
+
|
5
|
+
def meta key, value
|
6
|
+
@meta ||= {}
|
7
|
+
@meta[key.to_s] = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def error key, data=nil
|
11
|
+
if data
|
12
|
+
@error_hash ||= {}
|
13
|
+
@error_hash[key.to_s] = data
|
14
|
+
data
|
15
|
+
else
|
16
|
+
@errors ||= []
|
17
|
+
@errors.push key unless @errors.include?(key)
|
18
|
+
key
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def message what
|
23
|
+
@message = what
|
24
|
+
end
|
25
|
+
|
26
|
+
def errors?
|
27
|
+
(@error_hash || @errors) ? true : false
|
28
|
+
end
|
29
|
+
|
30
|
+
def render
|
31
|
+
output = {}
|
32
|
+
|
33
|
+
output[:data] = @data if @data.present?
|
34
|
+
output[:meta] = @meta if @meta.present?
|
35
|
+
output[:message] = @message if @message.present?
|
36
|
+
|
37
|
+
if errors?
|
38
|
+
output[:error] ||= {}
|
39
|
+
output[:error][:messages] = @errors if @errors
|
40
|
+
output[:error][:hash] = @error_hash if @error_hash
|
41
|
+
end
|
42
|
+
|
43
|
+
output
|
44
|
+
end
|
45
|
+
alias :to_hash :render
|
46
|
+
end
|
data/lib/lux/cache/cache.rb
CHANGED
@@ -35,14 +35,21 @@ module Lux::Cache
|
|
35
35
|
@@server.delete(key)
|
36
36
|
end
|
37
37
|
|
38
|
-
def fetch key,
|
39
|
-
|
40
|
-
|
38
|
+
def fetch key, opts={}
|
39
|
+
opts = { ttl: opts } unless opts.is_a?(Hash)
|
40
|
+
opts = opts.to_opts!(:ttl, :log, :force)
|
41
|
+
|
42
|
+
opts.ttl = opts.ttl.to_i if opts.ttl
|
43
|
+
opts.log ||= true if opts.log.nil?
|
44
|
+
opts.force ||= true if opts.force.nil?
|
45
|
+
|
46
|
+
@@server.delete key if Lux.page && opts.force && Lux.page.no_cache?
|
47
|
+
|
48
|
+
Lux.log " Cache.fetch.get #{key} (ttl: #{opts.ttl.or(:nil)})".green if opts.log
|
41
49
|
|
42
|
-
|
43
|
-
data = @@server.fetch key, ttl do
|
50
|
+
data = @@server.fetch key, opts.ttl do
|
44
51
|
data = yield
|
45
|
-
Lux.log " Cache.fetch.SET #{key} len:#{data.to_s.length}" if log
|
52
|
+
Lux.log " Cache.fetch.SET #{key} len:#{data.to_s.length}" if opts.log
|
46
53
|
data
|
47
54
|
end
|
48
55
|
|
data/lib/lux/cell/cell.rb
CHANGED
@@ -61,6 +61,8 @@ class Lux::Cell
|
|
61
61
|
|
62
62
|
### INSTANCE METHODS
|
63
63
|
|
64
|
+
attr_reader :cell_action
|
65
|
+
|
64
66
|
def initialize
|
65
67
|
# before and after should be exected only once
|
66
68
|
@executed_filters = {}
|
@@ -91,7 +93,7 @@ class Lux::Cell
|
|
91
93
|
|
92
94
|
method_name = method_name.to_s.gsub('-', '_').gsub(/[^\w]/, '')
|
93
95
|
|
94
|
-
Lux.log " #{self.class.to_s}(:#{method_name})".
|
96
|
+
Lux.log " #{self.class.to_s}(:#{method_name})".light_blue
|
95
97
|
Lux.page.files_in_use.push "app/cells/#{self.class.to_s.underscore}.rb"
|
96
98
|
|
97
99
|
@cell_action = method_name
|
@@ -137,19 +139,6 @@ class Lux::Cell
|
|
137
139
|
|
138
140
|
opts[:template] = name if name
|
139
141
|
|
140
|
-
# etag and cache string are same things, one is client based, other one is server based
|
141
|
-
if opts[:cache]
|
142
|
-
opts[:cache] = Lux.cache.generate_key(opts[:cache] )
|
143
|
-
opts[:etag] ||= opts[:cache]
|
144
|
-
end
|
145
|
-
|
146
|
-
return if opts[:etag] && Lux.page.etag(opts[:etag])
|
147
|
-
|
148
|
-
if opts[:cache]
|
149
|
-
data = Lux.cache.get(opts[:cache])
|
150
|
-
return Lux.page.body(data) if data
|
151
|
-
end
|
152
|
-
|
153
142
|
render_resolve_body(opts)
|
154
143
|
Lux.cache.set(opts[:cache], Lux.page.body) if opts[:cache]
|
155
144
|
end
|
data/lib/lux/config/config.rb
CHANGED
@@ -74,11 +74,12 @@ module Lux::Config
|
|
74
74
|
speed = ((Time.now - load_start)*1000).round.to_s.sub(/(\d)(\d{3})$/,'\1s \2')+'ms'
|
75
75
|
ram = `ps -o rss -p #{$$}`.chomp.split("\n").last.to_i / 1000
|
76
76
|
opts = []
|
77
|
-
opts.push Lux.verbose? ? 'verbose'.yellow : '
|
78
|
-
opts.push Lux.config(:auto_code_reload) ? 'code-reload'.yellow : 'no-code-reload'.green
|
77
|
+
opts.push Lux.verbose? ? 'verbose'.yellow : 'no-verbose'.green
|
78
|
+
opts.push Lux.config(:auto_code_reload) ? 'auto-code-reload'.yellow : 'no-code-reload'.green
|
79
79
|
|
80
|
-
"* #{'Lux'.
|
80
|
+
"* #{'Lux'.white} loaded #{Lux.env('RACK_ENV').green} (#{opts.join(', ')}) mode in #{speed.to_s.white}, uses #{ram.to_s.white} MB RAM with total of #{Gem.loaded_specs.keys.length.to_s.white} gems in spec"
|
81
81
|
end
|
82
|
+
|
82
83
|
end
|
83
84
|
|
84
85
|
class Object
|
@@ -66,7 +66,7 @@ class Lux::Controller
|
|
66
66
|
|
67
67
|
def rescued_main
|
68
68
|
if respond_to?(:main)
|
69
|
-
@@rescue_from_ivar.call { main }
|
69
|
+
@@rescue_from_ivar.call(self) { main }
|
70
70
|
else
|
71
71
|
Lux.error %[No instance method "main" in Lux::Controller defiend]
|
72
72
|
end
|
@@ -81,7 +81,7 @@ class Lux::Controller
|
|
81
81
|
when nil
|
82
82
|
'/'.ljust(20).green
|
83
83
|
else
|
84
|
-
@route.to_s.ljust(20).
|
84
|
+
@route.to_s.ljust(20).light_blue
|
85
85
|
end
|
86
86
|
|
87
87
|
route_target = case @route_target
|
@@ -169,7 +169,7 @@ class Lux::Controller
|
|
169
169
|
|
170
170
|
object, action = object if object.is_a? Array
|
171
171
|
|
172
|
-
Lux.log ' %s %s # %s' % [object.to_s.
|
172
|
+
Lux.log ' %s %s # %s' % [object.to_s.light_blue, nav.path, @route_object]
|
173
173
|
|
174
174
|
if action
|
175
175
|
object.action action
|
@@ -7,7 +7,7 @@ class Lux::Controller::Nav
|
|
7
7
|
# acepts path as a string
|
8
8
|
def initialize request
|
9
9
|
@path = request.path.split('/').slice(1, 100) || []
|
10
|
-
|
10
|
+
shift_to_root if @path.first
|
11
11
|
|
12
12
|
@subdomain = request.host.split('.')
|
13
13
|
@domain = @subdomain.pop(2).join('.')
|
@@ -22,7 +22,7 @@ class Lux::Controller::Nav
|
|
22
22
|
|
23
23
|
def shift_to_root
|
24
24
|
@root.tap do
|
25
|
-
@root = @path.shift
|
25
|
+
@root = @path.shift.to_s.gsub('-', '_')
|
26
26
|
build_full
|
27
27
|
end
|
28
28
|
end
|
@@ -48,6 +48,10 @@ class Lux::Controller::Nav
|
|
48
48
|
@path.first
|
49
49
|
end
|
50
50
|
|
51
|
+
def first= data
|
52
|
+
@path[0] = data
|
53
|
+
end
|
54
|
+
|
51
55
|
def second
|
52
56
|
@path[1]
|
53
57
|
end
|
data/lib/lux/error/error.rb
CHANGED
@@ -16,14 +16,13 @@ NotFoundError ||= Class.new(StandardError)
|
|
16
16
|
RateLimitError ||= Class.new(StandardError)
|
17
17
|
|
18
18
|
module Lux::Error
|
19
|
-
OUT_OF_PROCESS_ERROR_PATH = Lux.root.join('tmp/request-error.txt')
|
20
|
-
|
21
19
|
extend self
|
22
20
|
|
23
21
|
def try(name)
|
24
22
|
begin
|
25
23
|
yield
|
26
24
|
rescue
|
25
|
+
Lux.page.status 500
|
27
26
|
log($!)
|
28
27
|
inline('%s (%s)' % [name, $!.class])
|
29
28
|
end
|
@@ -41,9 +40,20 @@ module Lux::Error
|
|
41
40
|
|
42
41
|
def inline(name=nil, o=nil)
|
43
42
|
o ||= $!
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
|
44
|
+
dmp = [[], []]
|
45
|
+
|
46
|
+
o.backtrace.each do |line|
|
47
|
+
line = line.sub(Lux.root.to_s, '.')
|
48
|
+
dmp[line.include?('/app/') ? 0 : 1].push line
|
49
|
+
end
|
50
|
+
|
51
|
+
dmp[0] = dmp[0].map { |_| _ = _.split(':', 3); '<b>%s</b> - %s - %s' % _ }
|
52
|
+
|
53
|
+
name ||= 'Undefined name'
|
54
|
+
msg = $!.to_s.gsub('","',%[",\n "]).gsub('<','<')
|
55
|
+
|
56
|
+
%[<pre style="color:red; background:#eee; padding:10px; font-family:'Lucida Console'; line-height:15pt; font-size:11pt;"><b style="font-size:110%;">#{name}</b>\n\n<b>#{msg}</b>\n\n#{dmp[0].join("\n")}\n\n#{dmp[1].join("\n")}</pre>]
|
47
57
|
end
|
48
58
|
|
49
59
|
def log(exception)
|
@@ -63,13 +73,4 @@ module Lux::Error
|
|
63
73
|
|
64
74
|
File.write("#{folder}/#{key}.txt", data)
|
65
75
|
end
|
66
|
-
|
67
|
-
|
68
|
-
# if some other process as asset complation raises error
|
69
|
-
# use this method to show errors
|
70
|
-
def log_out_of_process_error(data)
|
71
|
-
return unless Lux.config(:show_server_errors)
|
72
|
-
File.write OUT_OF_PROCESS_ERROR_PATH, data
|
73
|
-
end
|
74
|
-
|
75
76
|
end
|
data/lib/lux/helper/helper.rb
CHANGED
@@ -99,11 +99,11 @@ class Lux::Helper
|
|
99
99
|
end
|
100
100
|
|
101
101
|
# tag :div, { 'class'=>'iform' } do
|
102
|
-
def tag name, opts={}, data=nil
|
103
|
-
|
104
|
-
|
105
|
-
opts
|
102
|
+
def tag name=nil, opts={}, data=nil
|
103
|
+
return Lux::Helper::HtmlTag unless name
|
104
|
+
|
105
|
+
data = yield(opts) if block_given?
|
106
|
+
Lux::Helper::HtmlTag.tag name, opts, data
|
106
107
|
end
|
107
108
|
|
108
109
|
end
|
109
|
-
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# tag.ul do |n|
|
2
|
+
# 1.upto(3) do |num|
|
3
|
+
# n.li do |n|
|
4
|
+
# n.i '.arrow'
|
5
|
+
# n.span num
|
6
|
+
# end
|
7
|
+
# end
|
8
|
+
# end
|
9
|
+
|
10
|
+
class Lux::Helper::HtmlTag
|
11
|
+
class << self
|
12
|
+
# tag.div -> tag.tag :div
|
13
|
+
def method_missing tag_name, *args, &block
|
14
|
+
tag tag_name, args[0], args[1], &block
|
15
|
+
end
|
16
|
+
|
17
|
+
# tag :div, { 'class'=>'iform' } do
|
18
|
+
def tag name=nil, opts={}, data=nil
|
19
|
+
# covert tag.a '.foo.bar' to class names
|
20
|
+
if opts.class == String && opts[0,1] == '.'
|
21
|
+
opts = { class: opts.sub('.', '').gsub('.', ' ') }
|
22
|
+
end
|
23
|
+
|
24
|
+
# fix data and opts unless opts is Hash
|
25
|
+
data, opts = opts, {} unless opts.class == Hash
|
26
|
+
|
27
|
+
if block_given?
|
28
|
+
inline = new
|
29
|
+
data = yield(inline, opts)
|
30
|
+
|
31
|
+
# if data is pushed to passed node, use that data
|
32
|
+
data = inline.data if inline.data.first
|
33
|
+
end
|
34
|
+
|
35
|
+
data = data.join('') if data.is_a?(Array)
|
36
|
+
|
37
|
+
build opts, name, data
|
38
|
+
end
|
39
|
+
|
40
|
+
# build html node
|
41
|
+
def build attrs, node=nil, text=nil
|
42
|
+
opts = ''
|
43
|
+
attrs.each do |k,v|
|
44
|
+
opts += ' '+k.to_s.gsub(/_/,'-')+'="'+v.to_s.gsub(/"/,'"')+'"' if v.present?
|
45
|
+
end
|
46
|
+
|
47
|
+
return opts unless node
|
48
|
+
|
49
|
+
text = yield opts if block_given?
|
50
|
+
text ||= '' unless ['input', 'img', 'meta', 'link', 'hr', 'br'].include?(node.to_s)
|
51
|
+
text ? %{<#{node}#{opts}>#{text}</#{node}>} : %{<#{node}#{opts} />}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
###
|
56
|
+
|
57
|
+
attr_reader :data
|
58
|
+
|
59
|
+
def initialize
|
60
|
+
@data = []
|
61
|
+
end
|
62
|
+
|
63
|
+
# forward to class
|
64
|
+
def method_missing tag_name, *args, &block
|
65
|
+
@data.push self.class.tag(tag_name, args[0], args[1], &block)
|
66
|
+
end
|
67
|
+
end
|
@@ -62,12 +62,15 @@ class Lux::Html::Input
|
|
62
62
|
def as_select
|
63
63
|
body = []
|
64
64
|
collection = @opts.delete(:collection)
|
65
|
+
|
65
66
|
if nullval = @opts.delete(:null)
|
66
67
|
body.push %[<option value="">#{nullval}</option>] if nullval
|
67
68
|
end
|
69
|
+
|
68
70
|
for el in prepare_collection(collection)
|
69
71
|
body.push(%[<option value="#{el[0]}"#{@opts[:value].to_s == el[0].to_s ? ' selected=""' : nil}>#{el[1]}</option>])
|
70
72
|
end
|
73
|
+
|
71
74
|
body = body.join("\n")
|
72
75
|
@opts.tag(:select, body)
|
73
76
|
end
|
@@ -94,25 +97,32 @@ class Lux::Html::Input
|
|
94
97
|
end
|
95
98
|
|
96
99
|
def as_date
|
97
|
-
@opts[:type]
|
98
|
-
@opts[:style]
|
99
|
-
|
100
|
-
@opts[:
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
ret + %[<script>new Pikaday({ field: document.getElementById('#{@opts [:id]}'), format: "YYYY-MM-DD" }); </script>]
|
100
|
+
@opts[:type] = :date
|
101
|
+
@opts[:style] = 'width: 160px; display: inline;'
|
102
|
+
|
103
|
+
value = @opts[:value] || nil
|
104
|
+
desc = value ? '—' + Time.ago(value) : ''
|
105
|
+
|
106
|
+
[@opts.tag(:input), desc].join(' ')
|
105
107
|
end
|
106
108
|
|
107
109
|
def as_datetime
|
108
|
-
@opts[:
|
109
|
-
@opts[:
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
110
|
+
value = @opts[:value]
|
111
|
+
id = @opts[:id]
|
112
|
+
|
113
|
+
value_day = value ? value.strftime('%Y-%m-%d') : ''
|
114
|
+
value_time = value ? value.strftime('%H:%M') : ''
|
115
|
+
value_all = value ? value.strftime('%H:%M') : ''
|
116
|
+
|
117
|
+
base = { class: 'form-control', onchange: "datetime_set('#{id}');", style: 'width: 160px; display: inline;' }
|
118
|
+
|
119
|
+
input_day = base.merge({ type: :date, id: '%s_day' % id, value: value_day }).tag :input
|
120
|
+
input_time = base.merge({ style: 'width: 110px; display: inline;', type: :time, id: '%s_time' % id, value: value_time }).tag :input
|
121
|
+
input_all = base.merge({ style: 'width: 150px; display: inline;', type: :text, id: id, name: @opts[:name], onfocus: 'blur();' }).tag :input
|
122
|
+
script = %[<script>window.datetime_set = function(id) { $('#'+id).val($('#'+id+'_day').val()+' '+$('#'+id+'_time').val()); }; datetime_set('#{id}');</script>]
|
123
|
+
desc = value ? '—' + Time.ago(value) : ''
|
124
|
+
|
125
|
+
[input_day, input_time, input_all, script, desc].join(' ')
|
116
126
|
end
|
117
127
|
|
118
128
|
def as_datebuttons
|
data/lib/lux/lib/lux.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# handy :)
|
2
|
+
# renders full pages and exposes page object (req, res) in yiled
|
3
|
+
# for easy and powerful testing
|
4
|
+
# Hash :qs, Hash :post, String :method, Hash :cookies, Hash :session
|
5
|
+
# https://github.com/rack/rack/blob/master/test/spec_request.rb
|
6
|
+
def Lux(path, in_opts={}, &block)
|
7
|
+
allowed_opts = [:qs, :post, :method, :session, :cookies]
|
8
|
+
in_opts.keys.each { |k| die "#{k} is not allowed as opts param. allowed are #{allowed_opts}" unless allowed_opts.index(k) }
|
9
|
+
|
10
|
+
opts = {}
|
11
|
+
|
12
|
+
if in_opts[:post]
|
13
|
+
opts[:query_string] = in_opts[:post]
|
14
|
+
opts[:request_method] = :post
|
15
|
+
else
|
16
|
+
opts[:query_string] = in_opts[:qs] || {}
|
17
|
+
opts[:request_method] ||= in_opts[:method] || :get
|
18
|
+
end
|
19
|
+
opts[:request_method] = opts[:request_method].to_s.upcase
|
20
|
+
opts[:query_string] = opts[:query_string].to_query if opts[:query_string].class.to_s == 'Hash'
|
21
|
+
|
22
|
+
if path[0,4] == 'http'
|
23
|
+
parsed = URI.parse(path)
|
24
|
+
opts[:server_name] = parsed.host
|
25
|
+
opts[:server_port] = parsed.port
|
26
|
+
path = '/'+path.split('/', 4).last
|
27
|
+
end
|
28
|
+
|
29
|
+
env = Rack::MockRequest.env_for(path)
|
30
|
+
env[:input] = opts[:post] if opts[:post]
|
31
|
+
for k,v in opts
|
32
|
+
env[k.to_s.upcase] = v
|
33
|
+
end
|
34
|
+
|
35
|
+
page = nil
|
36
|
+
time_ms = Lux.speed { page = Lux::Page.prepare(env) }
|
37
|
+
page.session = in_opts[:session] if in_opts[:session]
|
38
|
+
|
39
|
+
return page.instance_exec &block if block_given?
|
40
|
+
|
41
|
+
response = page.render
|
42
|
+
body = response[2].join('')
|
43
|
+
body = JSON.parse body if response[1]['content-type'].index('/json')
|
44
|
+
|
45
|
+
{
|
46
|
+
time: time_ms,
|
47
|
+
status: response[0],
|
48
|
+
headers: response[1],
|
49
|
+
body: body
|
50
|
+
}.h
|
51
|
+
end
|