lux-fw 0.5.36 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/.version +1 -1
  3. data/bin/README.md +26 -13
  4. data/bin/cli/benchmark.rb +18 -0
  5. data/bin/cli/cerb.rb +90 -0
  6. data/bin/cli/config.rb +4 -11
  7. data/bin/cli/console.rb +72 -30
  8. data/bin/cli/eval.rb +5 -27
  9. data/bin/cli/generate.rb +9 -11
  10. data/bin/cli/get.rb +14 -6
  11. data/bin/cli/memory.rb +12 -0
  12. data/bin/cli/new.rb +2 -0
  13. data/bin/cli/secrets.rb +3 -31
  14. data/bin/cli/server.rb +28 -9
  15. data/bin/cli/stats.rb +26 -20
  16. data/bin/cli/template.rb +10 -0
  17. data/bin/generate_doc +168 -0
  18. data/bin/lux +73 -10
  19. data/lib/README.md +18 -8
  20. data/lib/common/crypt.rb +60 -9
  21. data/lib/common/string_base.rb +54 -15
  22. data/lib/common/struct_opts.rb +30 -0
  23. data/lib/common/time_difference.rb +75 -0
  24. data/lib/loader.rb +41 -0
  25. data/lib/lux/application/README.md +67 -105
  26. data/lib/lux/application/application.rb +87 -329
  27. data/lib/lux/application/lib/magic_routes.rb +22 -0
  28. data/lib/lux/application/lib/nav.rb +218 -99
  29. data/lib/lux/application/lib/render.rb +47 -67
  30. data/lib/lux/application/lib/routes.rb +242 -0
  31. data/lib/lux/application/lib/shared.rb +47 -0
  32. data/lib/lux/application/lux_adapter.rb +6 -0
  33. data/lib/lux/application/lux_config.rb +26 -0
  34. data/lib/lux/cache/Find Results +24 -0
  35. data/lib/lux/cache/README.md +28 -35
  36. data/lib/lux/cache/cache.rb +78 -26
  37. data/lib/lux/cache/lib/memcached_server.rb +36 -0
  38. data/lib/lux/cache/lib/memory_server.rb +44 -0
  39. data/lib/lux/cache/lib/null_server.rb +33 -0
  40. data/lib/lux/cache/lib/sqlite_server.rb +62 -0
  41. data/lib/lux/cache/lux_adapter.rb +19 -0
  42. data/lib/lux/config/config.rb +93 -144
  43. data/lib/lux/config/lux_adapter.rb +27 -0
  44. data/lib/lux/controller/README.md +67 -12
  45. data/lib/lux/controller/controller.rb +237 -187
  46. data/lib/lux/current/README.md +29 -10
  47. data/lib/lux/current/current.rb +166 -77
  48. data/lib/lux/current/lib/current.rb +6 -0
  49. data/lib/lux/current/lib/encrypt_params.rb +38 -36
  50. data/lib/lux/current/lib/session.rb +86 -65
  51. data/lib/lux/current/lux_adapter.rb +5 -0
  52. data/lib/lux/environment/README.md +24 -0
  53. data/lib/lux/environment/environment.rb +91 -0
  54. data/lib/lux/environment/lux_adapter.rb +13 -0
  55. data/lib/lux/error/README.md +18 -19
  56. data/lib/lux/error/error.rb +207 -152
  57. data/lib/lux/error/lux_adapter.rb +9 -0
  58. data/lib/lux/logger/README.md +45 -0
  59. data/lib/lux/logger/lux_adapter.rb +27 -0
  60. data/lib/lux/lux.rb +72 -129
  61. data/lib/lux/mailer/README.md +12 -5
  62. data/lib/lux/mailer/lux_config.rb +4 -0
  63. data/lib/lux/mailer/mailer.rb +81 -59
  64. data/lib/lux/plugin/README.md +19 -0
  65. data/lib/lux/plugin/lux_adapter.rb +8 -0
  66. data/lib/lux/plugin/plugin.rb +65 -0
  67. data/lib/lux/render/README.md +100 -0
  68. data/lib/lux/render/render.rb +12 -0
  69. data/lib/lux/response/README.md +57 -1
  70. data/lib/lux/response/lib/file.rb +87 -65
  71. data/lib/lux/response/lib/flash.rb +49 -34
  72. data/lib/lux/response/lib/header.rb +34 -33
  73. data/lib/lux/response/response.rb +252 -164
  74. data/lib/lux/template/helper.rb +130 -0
  75. data/lib/lux/template/inline_render_proxy.rb +31 -0
  76. data/lib/lux/template/lux_adapter.rb +5 -0
  77. data/lib/lux/template/template.rb +127 -0
  78. data/lib/lux-fw.rb +15 -33
  79. data/lib/overload/array.rb +33 -7
  80. data/lib/overload/blank.rb +8 -3
  81. data/lib/overload/boolean.rb +46 -0
  82. data/lib/overload/class.rb +28 -0
  83. data/lib/overload/dir.rb +117 -7
  84. data/lib/overload/file.rb +40 -5
  85. data/lib/overload/float.rb +38 -3
  86. data/lib/overload/hash.rb +81 -91
  87. data/lib/overload/integer.rb +15 -0
  88. data/lib/overload/json.rb +26 -0
  89. data/lib/overload/nil.rb +4 -8
  90. data/lib/overload/object.rb +91 -24
  91. data/lib/overload/pathname.rb +11 -0
  92. data/lib/overload/raise_variants.rb +26 -36
  93. data/lib/overload/string.rb +100 -27
  94. data/lib/overload/thread_simple.rb +100 -0
  95. data/lib/overload/time.rb +60 -38
  96. data/tasks/loader.rb +20 -7
  97. metadata +170 -169
  98. data/bin/.DS_Store +0 -0
  99. data/bin/build_gem +0 -77
  100. data/bin/cli/dbconsole.rb +0 -8
  101. data/bin/cli/routes.rb +0 -90
  102. data/lib/.DS_Store +0 -0
  103. data/lib/common/.DS_Store +0 -0
  104. data/lib/common/class_attributes.rb +0 -51
  105. data/lib/common/class_callbacks.rb +0 -47
  106. data/lib/common/free_struct.rb +0 -42
  107. data/lib/common/hash_with_indifferent_access.rb +0 -74
  108. data/lib/common/html_tag_builder.rb +0 -91
  109. data/lib/common/method_attr.rb +0 -69
  110. data/lib/common/url.rb +0 -191
  111. data/lib/lux/.DS_Store +0 -0
  112. data/lib/lux/README.md +0 -10
  113. data/lib/lux/cache/.DS_Store +0 -0
  114. data/lib/lux/cache/lib/memory.rb +0 -36
  115. data/lib/lux/cache/lib/null.rb +0 -21
  116. data/lib/lux/config/README.md +0 -63
  117. data/lib/lux/config/lib/plugin.rb +0 -65
  118. data/lib/lux/config/lib/secrets.rb +0 -48
  119. data/lib/lux/current/.DS_Store +0 -0
  120. data/lib/lux/delayed_job/.DS_Store +0 -0
  121. data/lib/lux/delayed_job/README.md +0 -3
  122. data/lib/lux/delayed_job/delayed_job.rb +0 -51
  123. data/lib/lux/delayed_job/lib/memory.rb +0 -16
  124. data/lib/lux/delayed_job/lib/nsq.rb +0 -3
  125. data/lib/lux/delayed_job/lib/postgre.rb +0 -6
  126. data/lib/lux/delayed_job/lib/redis.rb +0 -19
  127. data/lib/lux/event_bus/README.md +0 -36
  128. data/lib/lux/event_bus/event_bus.rb +0 -27
  129. data/lib/lux/view/README.md +0 -85
  130. data/lib/lux/view/cell.rb +0 -102
  131. data/lib/lux/view/helper.rb +0 -120
  132. data/lib/lux/view/lib/cell_helpers.rb +0 -29
  133. data/lib/lux/view/view.rb +0 -95
  134. data/lib/overload/it.rb +0 -29
  135. data/plugins/api/README.md +0 -49
  136. data/plugins/api/api.rb +0 -153
  137. data/plugins/api/lib/attr.rb +0 -31
  138. data/plugins/api/lib/dsl.rb +0 -52
  139. data/plugins/api/lib/error.rb +0 -3
  140. data/plugins/api/lib/model_api.rb +0 -203
  141. data/plugins/api/lib/response.rb +0 -85
  142. data/plugins/db/.DS_Store +0 -0
  143. data/plugins/db/README.md +0 -29
  144. data/plugins/db/auto_migrate/auto_migrate.rb +0 -268
  145. data/plugins/db/auto_migrate/db.rake +0 -15
  146. data/plugins/db/helpers/array_search.rb +0 -27
  147. data/plugins/db/helpers/before_save_filters.rb +0 -32
  148. data/plugins/db/helpers/composite_primary_keys.rb +0 -36
  149. data/plugins/db/helpers/core.rb +0 -94
  150. data/plugins/db/helpers/dataset_methods.rb +0 -138
  151. data/plugins/db/helpers/enums_plugin.rb +0 -52
  152. data/plugins/db/helpers/find_precache.rb +0 -31
  153. data/plugins/db/helpers/link_objects.rb +0 -84
  154. data/plugins/db/helpers/schema_checks.rb +0 -83
  155. data/plugins/db/helpers/typero_adapter.rb +0 -71
  156. data/plugins/db/logger/config.rb +0 -22
  157. data/plugins/db/logger/lux_response_adapter.rb +0 -10
  158. data/plugins/db/paginate/helper.rb +0 -32
  159. data/plugins/db/paginate/sequel_adapter.rb +0 -23
  160. data/plugins/exceptions/exceptions.rake +0 -43
  161. data/plugins/exceptions/simple_exception.rb +0 -64
  162. data/plugins/favicon/favicon.rb +0 -10
  163. data/plugins/html/README.md +0 -3
  164. data/plugins/html/html_form.rb +0 -118
  165. data/plugins/html/html_input.rb +0 -98
  166. data/plugins/html/html_menu.rb +0 -79
  167. data/plugins/html/input_types.rb +0 -346
  168. data/plugins/js_widgets/README.md +0 -5
  169. data/plugins/js_widgets/js/html_tag.coffee +0 -42
  170. data/plugins/js_widgets/js/widgets.coffee +0 -161
  171. data/plugins/js_widgets/js_widgets.rb +0 -15
  172. data/plugins/oauth/lib/facebook.rb +0 -35
  173. data/plugins/oauth/lib/github.rb +0 -38
  174. data/plugins/oauth/lib/google.rb +0 -41
  175. data/plugins/oauth/lib/linkedin.rb +0 -41
  176. data/plugins/oauth/lib/stackexchange.rb +0 -41
  177. data/plugins/oauth/lib/twitter.rb +0 -38
  178. data/plugins/oauth/oauth.rb +0 -42
  179. data/plugins/policy/policy.rb +0 -53
  180. data/tasks/nginx.rake +0 -23
  181. /data/lib/lux/{view/lib → mailer}/helper_modules.rb +0 -0
@@ -1,118 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # = form Lux.current.var.user do |f|
4
- # = f.hidden :company_id
5
- # = f.row :name
6
- # = f.row :counrty_id, :as=>:country
7
- # .custom= f.input :email
8
- # = f.submit 'Save'
9
-
10
- Lux.plugin 'api'
11
-
12
- ApplicationApi.before do
13
- name = '[protected]:'
14
- params.each do |k,v|
15
- params[k] = Crypt.decrypt(v.split(name, 2)[1]) if v.is_a?(String) && v.starts_with?(name)
16
- end
17
- end
18
-
19
- class HtmlForm
20
- def initialize target, opts={}
21
- opts[:method] = 'get' if opts.delete(:get)
22
- opts[:method] ||= 'get' unless @target
23
- opts[:method] ||= 'post'
24
- opts[:method] = opts[:method].upcase
25
-
26
- opts[:id] ||= 'form-%s' % Lux.current.uid
27
-
28
- @target = target
29
- @opts = opts
30
- @before = [] # add stuff to the begining of the form block
31
-
32
- if @target.respond_to?(:update)
33
- @object = @target
34
- @opts['data-model'] = @object.class.to_s.underscore.singularize
35
- end
36
-
37
- before
38
-
39
- @opts[:action] = @target if @target
40
- end
41
-
42
- # render full form, accepts block
43
- def render
44
- data = @before.join('')
45
- data += yield self
46
- data = form data
47
-
48
- @opts.tag(:form, data)
49
- end
50
-
51
- # run stuff after block initialize
52
- def before
53
- true
54
- end
55
-
56
- # hidden filed
57
- def hidden name, opts={}
58
- fname = @object.class.name.tableize.singularize rescue nil
59
-
60
- if name.respond_to?(:update)
61
- oname = name.class.name.tableize.singularize
62
- if @object && @object.respond_to?("#{oname}_id") # grp
63
- Lux::Current::EncryptParams.hidden_input "#{fname}[#{oname}_id]", name.id
64
- else
65
- [
66
- Lux::Current::EncryptParams.hidden_input("#{fname}[model_id]", name.id),
67
- Lux::Current::EncryptParams.hidden_input("#{fname}[model_type]", name.class.name),
68
- ].join('')
69
- end
70
- else
71
- opts[:value] ||= @object[name] if @object && name.is_a?(Symbol)
72
- name = '%s[%s]' % [fname, name] if fname && name.is_a?(Symbol)
73
-
74
- if opts[:value].present?
75
- Lux::Current::EncryptParams.hidden_input(name, opts[:value])
76
- else
77
- ''
78
- end
79
- end
80
- end
81
-
82
- # standard input linked to HtmlInput class
83
- def input name, opts={}
84
- @name = name
85
- opts[:id] ||= Lux.current.uid
86
- opts[:value] ||= Lux.current.request.params[name] if @opts[:method] == 'GET'
87
- input_object = HtmlInput.new(@object)
88
- data = input_object.render(name, opts)
89
- @type = input_object.type
90
- data
91
- end
92
-
93
- # submit button
94
- def submit name=nil
95
- name ||= 'Submit'
96
- %[<li><button type="submit">#{name}</button></li>]
97
- end
98
-
99
- # render simple row
100
- def row name, opts={}
101
- node = input(name, opts)
102
- label = %[<label for="#{opts[:id]}">#{opts[:label] || name.to_s.humanize}</label>]
103
- %[<li class="as-#{opts[:as]}">#{label}#{node}<span class="error"></span></li>]
104
- end
105
-
106
- private
107
-
108
- def form data
109
- @opts[:class] = 'ul-form'
110
- %[<ul>#{data}</ul>]
111
- end
112
-
113
- def encrypt data
114
- return unless data
115
- '[protected]:%s' % Crypt.encrypt(data)
116
- end
117
- end
118
-
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # input = HtmlInput.new(User.first)
4
- # input.render :email
5
-
6
- class HtmlInput
7
- attr_accessor :type
8
-
9
- def self.register name, &block
10
- define_method "as_#{name}", &block
11
- end
12
-
13
- ###
14
-
15
- def initialize(obj=nil, opts={})
16
- @object = obj
17
- @globals = opts.dup
18
- end
19
-
20
- # if type is written in parameter :as=> use this helper function
21
- def render(name, opts={})
22
- if name.is_hash?
23
- opts = name
24
- name = :null
25
- end
26
-
27
- opts = opts_prepare name, opts.dup
28
- @type = opts.delete(:as) || :text
29
- send("as_#{@type}") rescue Lux::Error.inline("as_#{@type} (HtmlInput)")
30
- end
31
-
32
- private
33
-
34
- # exports @name and @opts globals
35
- def opts_prepare name, opts={}
36
-
37
- opts[:as] ||= lambda do
38
- return :select if opts[:collection]
39
-
40
- data_type = @object[name].class.name rescue 'String'
41
-
42
- if ['TrueClass','FalseClass'].index(data_type)
43
- :checkbox
44
- else
45
- :string
46
- end
47
- end.call
48
-
49
- # experimental, figure out collection unless defined
50
- if name =~ /_id$/ && opts[:as] == :select && !opts[:collection]
51
- class_name = name.to_s.split('_id')[0].capitalize
52
- opts[:collection] = eval "#{class_name}.order('name').all"
53
- end
54
-
55
- opts[:as] ||= :select if opts[:collection]
56
- opts[:id] ||= Lux.current.uid
57
- opts[:value] ||= @object.send(name) if @object
58
- opts[:value] = opts[:default] if opts[:value].blank?
59
- opts[:name] = name.kind_of?(Symbol) && @object ? "#{@object.class.name.underscore}[#{name}]" : name
60
-
61
- # convert decimal numbers to float
62
- opts[:value] = opts[:value].to_f if opts[:value].class == BigDecimal
63
-
64
- @label = opts.delete :label
65
- @wrap = opts.delete(:wrap) || @globals[:wrap]
66
- @name = name
67
- @opts = opts
68
- end
69
-
70
- def prepare_collection data
71
- ret = []
72
-
73
- if data.is_hash?
74
- # { id: {name:'Foo'} } : { id: 'Foo' }
75
- for id, name in data
76
- name = name[:name] if name.is_hash?
77
- ret.push [id.to_s, name]
78
- end
79
- else
80
- for el in data
81
- if data[0].respond_to?(:select_name)
82
- ret.push [el.id.to_s, el.select_name]
83
- elsif data[0].respond_to?(:name)
84
- ret.push [el.id.to_s, el.name]
85
- elsif data[0].kind_of?(Array)
86
- ret.push [el[0].to_s, el[1]]
87
- elsif data.is_hash?
88
- ret.push el
89
- else
90
- ret.push [el.to_s, el]
91
- end
92
- end
93
- end
94
-
95
- ret
96
- end
97
-
98
- end
@@ -1,79 +0,0 @@
1
- # menu = HtmlMenu.new request.path
2
- # menu.add 'Home', '/'
3
- # menu.add 'People', '/people', lambda { |path| path.index('peor') }
4
- # menu.add 'Jobs', '/jobs', { icon: true }
5
- # menu.to_a
6
- # ---
7
- # [["Home", "/", {}, true], ["People", "/people", {}, false], ["Jobs", "/jobs", { icon: true }, false]]
8
-
9
- class HtmlMenu
10
- attr_accessor :path
11
- attr_accessor :data
12
-
13
- def initialize path
14
- @path = path.to_s
15
- @data = []
16
- end
17
-
18
- # item 'Links', '/link'
19
- # item('Links', '/link') { ... }
20
- def add name, path, opt1=nil, opt2=nil, &block
21
- test, opts = opt1.is_a?(Hash) ? [opt2, opt1] : [opt1, opt2 || {}]
22
-
23
- if @data.first
24
- active = nil
25
- active = false if test.class == FalseClass && !@data.first
26
-
27
- if !@is_activated && @data.first && path != @data.first[1]
28
- test ||= block || path
29
- active = item_active(test)
30
- @is_activated ||= active
31
- end
32
-
33
- @data.push [name, path, opts, active]
34
- else
35
- @data.push [name, path, opts, test.class == FalseClass ? false : nil]
36
- end
37
- end
38
-
39
- # is menu item active?
40
- def item_active data
41
- case data
42
- when Symbol
43
- @path.include?(data.to_s)
44
- when String
45
- @path.starts_with? data
46
- when Regexp
47
- @path =~ data
48
- when Proc
49
- !! data.call(@path)
50
- when Integer
51
- true
52
- when TrueClass
53
- true
54
- when FalseClass
55
- false
56
- else
57
- raise ArgumentError.new("Unhandled class #{data.class} for #{data}")
58
- end
59
- end
60
-
61
- # return result as a list
62
- def to_a
63
- @data[0][3] = true if ! @is_activated && @data[0][3].class != FalseClass
64
- @data
65
- end
66
-
67
- # return result as list of hashes
68
- def to_h
69
- to_a.map do |it|
70
- {
71
- name: it[0],
72
- path: it[1],
73
- opts: it[2],
74
- active: it[3],
75
- }
76
- end
77
- end
78
-
79
- end
@@ -1,346 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class HtmlInput
4
-
5
- # if you call .memo which is not existant, it translates to .as_memo with opts_prepare first
6
- # def method_missing(meth, *args, &block)
7
- # opts_prepare *args
8
- # send "as_#{meth}"
9
- # end
10
-
11
- #############################
12
- # custom fields definitions #
13
- #############################
14
-
15
- def as_string
16
- @opts[:type] = 'text'
17
- @opts[:autocomplete] ||= 'off'
18
- @opts.tag(:input)
19
- end
20
- alias :as_text :as_string
21
-
22
- def as_password
23
- @opts[:type] = 'password'
24
- @opts.tag(:input)
25
- end
26
-
27
- def as_hidden
28
- @opts[:type] = 'hidden'
29
- @opts.tag(:input)
30
- end
31
-
32
- def as_file
33
- @opts[:type] = 'file'
34
- @opts.tag(:input)
35
- end
36
-
37
- def as_textarea
38
- val = @opts.delete(:value) || ''
39
- val = val.join($/) if val.is_array?
40
- comp_style = val.split(/\n/).length + val.length/100
41
- comp_style = 6 if comp_style < 6
42
- comp_style = 15 if comp_style > 15
43
- @opts[:style] = "height:#{comp_style*20}px; #{@opts[:style]};"
44
- @opts.tag(:textarea, val)
45
- end
46
- alias :as_memo :as_textarea
47
-
48
- def as_checkbox
49
- id = Lux.current.uid
50
- hidden = { :name=>@opts.delete(:name), :type=>:hidden, :value=>@opts[:value] ? 1 : 0, :id=>id }
51
- @opts[:type] = :checkbox
52
- @opts[:onclick] = "document.getElementById('#{id}').value=this.checked ? 1 : 0; #{@opts[:onclick]}"
53
- @opts[:checked] = @opts.delete(:value) ? 1 : nil
54
- @opts.tag(:input)+hidden.tag(:input)
55
- end
56
-
57
- def as_checkboxes
58
- body = []
59
- collection = @opts.delete(:collection)
60
-
61
- @opts[:type] = :checkbox
62
-
63
- null = @opts.delete(:null)
64
- value = @opts.delete(:value).to_s
65
-
66
- body.push %[<label>#{opts.tag(:input)} #{null}</label>] if null
67
-
68
- prepare_collection(collection).each do |el|
69
- opts = @opts.dup
70
- opts[:value] = el[0]
71
- opts[:checked] = true if value == el[0].to_s
72
-
73
- body.push %[<label>#{opts.tag(:input)} #{el[1]}</label>]
74
- end
75
-
76
- '<div class="form-checkboxes">%s</div>' % body.join("\n")
77
- end
78
-
79
- def as_select
80
- body = []
81
- collection = @opts.delete(:collection)
82
-
83
- @opts[:class] ||= 'form-select'
84
-
85
- if nullval = @opts.delete(:null)
86
- body.push %[<option value="">#{nullval}</option>] if nullval
87
- end
88
-
89
- for el in prepare_collection(collection)
90
- body.push(%[<option value="#{el[0]}"#{@opts[:value].to_s == el[0].to_s ? ' selected=""' : nil}>#{el[1]}</option>])
91
- end
92
-
93
- body = body.join("\n")
94
- @opts.tag(:select, body)
95
- end
96
-
97
- def as_radio
98
- return as_radios if @opts[:collection]
99
-
100
- @opts[:type] = :radio
101
- @opts[:checked] = @opts[:value] == @object.send(@name) ? true : nil
102
- @opts.tag(:input)
103
- end
104
-
105
- def as_radios
106
- body = []
107
- collection = @opts.delete(:collection)
108
-
109
- @opts[:type] = :radio
110
-
111
- null = @opts.delete(:null)
112
- value = @opts.delete(:value).to_s
113
-
114
- body.push %[<label>#{opts.tag(:input)} #{null}</label>] if null
115
-
116
- prepare_collection(collection).each do |el|
117
- opts = @opts.dup
118
- opts[:value] = el[0]
119
- opts[:checked] = true if value == el[0].to_s
120
-
121
- body.push %[<label>#{opts.tag(:input)} #{el[1]}</label>]
122
- end
123
-
124
- '<div class="form-radios">%s</div>' % body.join("\n")
125
- end
126
-
127
- def as_tag
128
- @opts[:value] = @opts[:value].or([]).join(', ') if ['Array', 'Sequel::Postgres::PGArray'].index(@opts[:value].class.name)
129
- @opts[:id] ||= Lux.current.uid
130
- @opts[:type] = :text
131
- @opts[:onkeyup] = %[draw_tag('#{@opts[:id]}')]
132
- @opts[:autocomplete] ||= 'off'
133
- @opts[:style] = ['display: block; width: 100%;', @opts[:style]].join(';')
134
-
135
- ret = %[
136
- <script>
137
- window.draw_tag = window.draw_tag || function (id) {
138
- tags = $.map(String($('#'+id).val()).split(/\s*,\s*/), function(el) {
139
- val = el.replace(/\s+/,'-');
140
- return val ? '<span class="label label-default">'+val+'</span> ' : ''
141
- });
142
- $('#'+id+'_tags').html(tags)
143
- }</script>]
144
- ret += @opts.tag(:input)
145
- ret += %[<div id="#{@opts[:id]}_tags" style="margin-top:5px;"></div>]
146
- ret += %[<script>if (window.$) { draw_tag('#{@opts[:id]}'); } else { window.onload = function(){ draw_tag('#{@opts[:id]}'); } }</script>]
147
- ret
148
- end
149
-
150
- def as_date
151
- @opts[:type] = 'text'
152
- @opts[:style] = 'width: 120px; display: inline;'
153
- @opts[:value] = @opts[:value].strftime('%d.%m.%Y') rescue @opts[:value]
154
- @opts[:autocomplete] = :off
155
-
156
- ret = @opts.tag(:input)
157
- ret += '<span class="date-ago"> &bull; %s</span>' % Time.ago(Time.parse(@opts[:value])) if @opts[:value].present? && !@opts.delete(:no_ago)
158
- # ret += ' &bull; <small>%s</small>' % @opts[:hint]
159
- ret + %[<script>new Pikaday({ field: document.getElementById('#{@opts [:id]}'), format: "DD.MM.YYYY" }); </script>]
160
- end
161
-
162
- def as_datetime
163
- value = @opts[:value]
164
- id = @opts[:id]
165
-
166
- value_day = value ? value.strftime('%Y-%m-%d') : ''
167
- value_time = value ? value.strftime('%H:%M') : ''
168
- value_all = value ? value.strftime('%H:%M') : ''
169
-
170
- base = { class: 'form-control', onchange: "datetime_set('#{id}');", style: 'width: 160px; display: inline;' }
171
-
172
- input_day = base.merge({ type: :date, id: '%s_day' % id, value: value_day }).tag :input
173
- input_time = base.merge({ style: 'width: 110px; display: inline;', type: :time, id: '%s_time' % id, value: value_time }).tag :input
174
- input_all = base.merge({ style: 'width: 150px; display: inline;', type: :text, id: id, name: @opts[:name], onfocus: 'blur();' }).tag :input
175
- script = %[<script>window.datetime_set = function(id) { $('#'+id).val($('#'+id+'_day').val()+' '+$('#'+id+'_time').val()); }; datetime_set('#{id}');</script>]
176
- desc = value ? '&mdash;' + Time.ago(value) : ''
177
-
178
- [input_day, input_time, input_all, script, desc].join(' ')
179
- end
180
-
181
- def as_datebuttons
182
- @opts[:type] = 'text'
183
- @opts[:style] = 'width:100px; display:inline;'
184
- @opts[:id] = "date_#{Lux.current.uid}"
185
- id = "##{@opts[:id]}"
186
- ret = @opts.tag(:input)
187
- ret += %[ <button class="btn btn-default btn-sm" onclick="$('#{id}').val('#{DateTime.now.strftime('%Y-%m-%d')}'); return false;">Today</button>]
188
- for el in [1, 3, 7, 14, 30]
189
- date = DateTime.now+el.days
190
- name = el.to_s
191
- name += " (#{date.strftime('%a')})" if el < 7
192
- ret += %[ <button class="btn btn-default btn-sm" onclick="$('#{id}').val('#{(DateTime.now+el.days).strftime('%Y-%m-%d')}'); return false;">+#{name}</button>]
193
- end
194
- ret
195
- end
196
-
197
- def as_user
198
- button_text = if @opts[:value].to_i > 0
199
- usr = User.find(@opts[:value])
200
- "#{usr.name} (#{usr.email})"
201
- else
202
- 'Select user'
203
- end
204
-
205
- @opts[:style] = "width:auto;#{@opts[:style]};"
206
- @opts[:onclick] = %[Dialog.render(this,'Select user', '/part/users/single_user?product_id=#{@object.bucket_id}');return false;]
207
- @opts.tag :button, button_text
208
- end
209
-
210
- def as_photo
211
- @opts[:type] = 'hidden'
212
- if @opts[:value].present?
213
- img = Photo.find(@opts[:value])
214
- @image = %[ <img id="#{@opts[:id]}_image" style="height:34px; cursor:pointer;" src="#{img.thumbnail}" onclick="window.open('#{img.image.remote_url}')" /> <span class="btn btn-default btn-xs" onclick="$('##{@opts[:id]}').val('');$('##{@opts[:id]}_image').remove();$(this).remove();">&times;</span>]
215
- end
216
- picker = @opts.tag(:input)
217
- %[<span class="btn btn-default" onclick="Photo.pick('#{@opts[:id]}', function(id) { alert('Chosen: '+id) })">Select photo</span>#{picker}#{@image}]
218
- end
219
-
220
- def as_photos
221
- @opts[:type] = 'text'
222
- @opts[:style] = 'width:150px; display:inline;'
223
- @opts[:class] += ' mutiple'
224
- @images = []
225
- if @opts[:value].present?
226
- for el in @opts[:value].split(',').uniq
227
- img = Photo.find(el.to_i) rescue next
228
- @images.push %[ <img style="height:34px; cursor:pointer;" src="#{img.thumbnail}" onclick="window.open('#{img.image.remote_url}')" />]
229
- end
230
- end
231
- picker = @opts.tag(:input)
232
- %[<span class="btn btn-default" onclick="Photo.pick('#{@opts[:id]}', function(id) { alert('Chosen: '+id) })">Add photo</span> #{picker}<div class="images" style="padding-top:5px;">#{@images.join(' ')}</div>]
233
- end
234
-
235
- def as_admin_password
236
- @opts[:type] = 'text'
237
- @opts[:style] = 'display:none;'
238
- @opts[:value] = ''
239
- ret = @opts.tag(:input)
240
- %[<span class="btn btn-default" onclick="$(this).hide();$('##{@opts[:id]}').show().val('').attr('type','password').focus()">Set pass</span> #{ret}]
241
- end
242
-
243
- def as_color
244
- value = @opts[:value]
245
- @opts[:style] ||= 'width:150px; float: left; margin-right: 10px;'
246
- as_text + %[<span style="background-color: #{value.or('#fff')}; height:34px; width:150px; display: inline-block;"></span>]
247
- end
248
-
249
- def as_array_values
250
- name = @opts[:name]
251
- ret = []
252
- values = @opts[:value].kind_of?(String) ? @opts[:value].split(',') : @opts[:value]
253
- for el in @opts[:collection]
254
- ret.push %[<label style="position:relative; top:4px;">
255
- <input name="#{name}[#{el[1]}]" value="1" type="checkbox" #{values[el[1]].present? ? 'checked=""' : ''} style="position:relative;top:2px; left:2px;" />
256
- <span style="margin-right:10px;">#{el[0]}</span>
257
- </label>]
258
- end
259
- ret.join('')
260
- end
261
-
262
- def as_pass
263
- value = @opts[:value]
264
- id = @opts[:id]
265
- @opts[:value] = ''
266
- @opts[:style] = 'width:200px; display:inline;'
267
- ret = @opts.tag(:input)
268
- %[<span class="btn btn-default" onclick="$(this).hide(); $(this).next().show().focus();">#{value.present? ? 'Change' : 'Set'} password</span><span id="s-#{id}" style="display:none;">#{ret} or <a onclick="p=$(this).parent(); p.hide(); p.prev().show(); return false;" href="#">cancel</a></span>]
269
- end
270
-
271
- def as_image
272
- @opts[:type] = 'text'
273
- @opts[:style] = 'width:350px; float:left;'
274
- @opts[:autocomplete] ||= 'off'
275
-
276
- input = @opts.tag(:input)
277
- path_name = 'image_upload_dialog'
278
- input += %[<span class="btn btn-default" style="float:left; margin-left:5px;" onclick="Dialog.template('#{path_name}', function(url){ $('##{@opts[:id]}').val(url); Dialog.close(); })">upload</span>]
279
-
280
- if @opts[:value].present?
281
- input = %[<img onload="i = new Image(); i.src='#{@opts[:value]}'; $('#img_size_#{@opts[:id]}').html(i.width+' x '+i.height)" src="#{@opts[:value]}" onclick="window.open('#{@opts[:value]}')" style="width:100px; border:1px solid #ccc; float:left; margin-right:10px;" /> #{input}]
282
- input += %[<br /><br /><span id="img_size_#{@opts[:id]}">...</span>]
283
- end
284
-
285
- '<span style="clear: both; display: block;"></span>' + input
286
- end
287
-
288
- def as_geo
289
- @opts[:type] = 'text'
290
- @opts[:style] = 'width:200px; float:left;'
291
- ret = @opts.tag(:input)
292
- ret += %[ <a target="new" href="http://maps.google.com/maps?q=loc:#{@opts[:value]}" style="display:block; margin-top:7px;">&nbsp;Show on map</a>]
293
- end
294
-
295
- def as_html_trix
296
- %[
297
- <div class="hide-for-popup" style="width: 100%;">
298
- <textarea id="trix_#{@name}" name="#{@opts[:name]}" style="display:none;">#{@opts[:value]}</textarea>
299
- <trix-editor input="trix_#{@name}"></trix-editor>
300
- </div>
301
- ]
302
- end
303
-
304
- def as_button_select
305
- body = ['<div class="btn-group">']
306
- collection = @opts.delete(:collection)
307
- for el in prepare_collection(collection)
308
- opts = { class:'btn btn-sm' }
309
- ap "#{@opts[:name]} - #{@opts[:value]} == #{el[0]}"
310
- opts[:class] += ' btn-primary' if @opts[:value].to_s == el[0].to_s
311
- opts[:onclick] = "$(this).parent().find('.btn').removeClass('btn-primary'); $(this).addClass('btn-primary').blur(); $(this).addClass('btn-primary').blur();"
312
- opts[:onclick] += @opts[:onclick] ? "(#{@opts[:onclick].sub(/;\s*$/,'')})('#{el[0]}')" : "$('##{@opts[:id]}').val('#{el[0]}')"
313
- opts[:onclick] += '; return false;'
314
- body.push opts.tag(:button, el[1])
315
- end
316
- body.push '</div>'
317
- body.push @opts.pluck(:name, :id, :value).merge(type: :hidden).tag(:input)
318
- body.join('')
319
- end
320
-
321
- def as_address
322
- val = @opts[:value]
323
- @opts[:style] ||= 'height:55px; width:250px; float: left; margin-right:5px;'
324
- ret = as_textarea
325
- ret += %[<div><a class="btn btn-default btn-xs" onclick="window.open('https://www.google.hr/maps?q='+$('##{@opts[:id]}').val()); return false;">open in new window</a></div>] if val.to_s.length > 5
326
- ret
327
- end
328
-
329
- def as_images
330
- path_name = defined?(Storage) ? :storages : :images
331
-
332
- val = @opts[:value].to_s
333
- ret = as_memo
334
- ret += '<div style="margin-top: 7px;"></div>'
335
- ret += val.split("\n").map{ |url| %[<a href="#{url}" target="_new"><img src="#{url}" style="height:50px; margin-right:5px; border:1px solid #ccc;" /></a>] }.join(' ')
336
- ret += %[<span class="btn btn-default" style="float:left; margin-left:5px;" onclick='Dialog.template("#{path_name}/select", function(url){ $("##{@opts[:id]}")[0].value += "\\n"+url; Dialog.close(); })'>add image</span>]
337
- ret
338
- end
339
-
340
- def as_disabled
341
- @opts[:disabled] = true
342
- @opts.delete(:name)
343
- as_text
344
- end
345
-
346
- end
@@ -1,5 +0,0 @@
1
- ### Use as
2
-
3
- ```
4
- //= req plugin:js_widgets/*
5
- ```
@@ -1,42 +0,0 @@
1
- #$tag 'button.btn.btn-xs', button_name, class: 'btn-primary'
2
- @$tag = (name, args...) ->
3
- # evaluate function if data is function
4
- args = args.map (el) -> if typeof el == 'function' then el() else el
5
-
6
- # fill second value
7
- args[1] ||= if typeof args[0] == 'object' then '' else {}
8
-
9
- # swap args if first option is object
10
- [opts, data] = if typeof args[0] == 'object' then args else args.reverse()
11
- opts ||= {}
12
-
13
- # haml style id define
14
- name = name.replace /#([\w\-]+)/, (_, id) ->
15
- opts['id'] = id
16
- ''
17
-
18
- # haml style class add with a dot
19
- name_parts = name.split('.')
20
- name = name_parts.shift() || 'div'
21
-
22
- if name_parts[0]
23
- old_class = if opts['class'] then ' '+opts['class'] else ''
24
- opts['class'] = name_parts.join(' ') + old_class
25
-
26
- node = ['<'+name]
27
-
28
- for key in Object.keys(opts)
29
- val = opts[key]
30
-
31
- if typeof val == 'function'
32
- val = String(val).replace(/\s+/g,' ')
33
- val = """(#{val})();"""
34
-
35
- node.push ' '+key+'="'+val+'"'
36
-
37
- if ['input', 'img'].indexOf(name) > -1
38
- node.push ' />'
39
- else
40
- node.push '>'+data+'</'+name+'>'
41
-
42
- node.join('')