engine2 1.0.5 → 1.0.6

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 (86) hide show
  1. checksums.yaml +5 -5
  2. data/app/actions.coffee +93 -58
  3. data/app/app.css +12 -0
  4. data/app/engine2.coffee +42 -24
  5. data/conf/message.yaml +1 -0
  6. data/conf/message_pl.yaml +1 -0
  7. data/config.coffee +2 -2
  8. data/engine2.gemspec +1 -1
  9. data/lib/engine2/action.rb +130 -126
  10. data/lib/engine2/action/array.rb +4 -4
  11. data/lib/engine2/action/decode.rb +13 -9
  12. data/lib/engine2/action/infra.rb +3 -3
  13. data/lib/engine2/action/list.rb +17 -10
  14. data/lib/engine2/action_node.rb +1 -2
  15. data/lib/engine2/core.rb +35 -7
  16. data/lib/engine2/model.rb +64 -15
  17. data/lib/engine2/post_bootstrap.rb +1 -1
  18. data/lib/engine2/pre_bootstrap.rb +10 -0
  19. data/lib/engine2/scheme.rb +2 -2
  20. data/lib/engine2/templates.rb +8 -0
  21. data/lib/engine2/type_info.rb +37 -15
  22. data/lib/engine2/version.rb +1 -1
  23. data/package.json +8 -5
  24. data/views/fields/blob.slim +1 -1
  25. data/views/fields/bs_select.slim +2 -2
  26. data/views/fields/bsselect_picker.slim +4 -4
  27. data/views/fields/bsselect_picker_opt.slim +5 -5
  28. data/views/fields/checkbox.slim +4 -4
  29. data/views/fields/checkbox_buttons.slim +3 -3
  30. data/views/fields/checkbox_buttons_opt.slim +3 -3
  31. data/views/fields/currency.slim +2 -2
  32. data/views/fields/date.slim +4 -4
  33. data/views/fields/date_range.slim +9 -9
  34. data/views/fields/date_time.slim +9 -9
  35. data/views/fields/datetime.slim +8 -8
  36. data/views/fields/decimal.slim +1 -1
  37. data/views/fields/decimal_date.slim +3 -3
  38. data/views/fields/decimal_time.slim +3 -3
  39. data/views/fields/email.slim +3 -3
  40. data/views/fields/file_store.slim +4 -4
  41. data/views/fields/input_text.slim +4 -4
  42. data/views/fields/integer.slim +1 -1
  43. data/views/fields/list_bsmselect.slim +20 -0
  44. data/views/fields/list_bsselect.slim +5 -5
  45. data/views/fields/list_bsselect_opt.slim +6 -6
  46. data/views/fields/list_buttons.slim +1 -1
  47. data/views/fields/list_buttons_opt.slim +2 -2
  48. data/views/fields/list_select.slim +4 -4
  49. data/views/fields/list_select_opt.slim +5 -5
  50. data/views/fields/password.slim +4 -4
  51. data/views/fields/radio_checkbox.slim +3 -3
  52. data/views/fields/scaffold.slim +1 -1
  53. data/views/fields/scaffold_picker.slim +5 -5
  54. data/views/fields/select_picker.slim +3 -3
  55. data/views/fields/select_picker_opt.slim +4 -4
  56. data/views/fields/text_area.slim +3 -3
  57. data/views/fields/time.slim +5 -4
  58. data/views/fields/typeahead_picker.slim +5 -5
  59. data/views/scaffold/fields.slim +4 -4
  60. data/views/scaffold/form.slim +1 -1
  61. data/views/scaffold/form_collapse.slim +4 -3
  62. data/views/scaffold/form_tabs.slim +3 -2
  63. data/views/scaffold/search.slim +2 -2
  64. data/views/scaffold/search_collapse.slim +6 -5
  65. data/views/scaffold/search_tabs.slim +4 -3
  66. data/views/scaffold/view.slim +2 -2
  67. data/views/scaffold/view_collapse.slim +5 -4
  68. data/views/scaffold/view_tabs.slim +4 -3
  69. data/views/search_fields/bsmselect_picker.slim +4 -4
  70. data/views/search_fields/bsselect_picker.slim +4 -4
  71. data/views/search_fields/checkbox.slim +3 -3
  72. data/views/search_fields/checkbox2.slim +5 -5
  73. data/views/search_fields/checkbox_buttons.slim +3 -3
  74. data/views/search_fields/date_range.slim +8 -8
  75. data/views/search_fields/decimal_date_range.slim +5 -5
  76. data/views/search_fields/input_text.slim +2 -2
  77. data/views/search_fields/integer.slim +1 -1
  78. data/views/search_fields/integer_range.slim +2 -2
  79. data/views/search_fields/list_bsmselect.slim +4 -4
  80. data/views/search_fields/list_bsselect.slim +4 -4
  81. data/views/search_fields/list_buttons.slim +2 -2
  82. data/views/search_fields/list_select.slim +3 -3
  83. data/views/search_fields/scaffold_picker.slim +2 -2
  84. data/views/search_fields/select_picker.slim +3 -3
  85. data/views/search_fields/typeahead_picker.slim +4 -4
  86. metadata +6 -5
@@ -8,6 +8,7 @@
8
8
  :error: Error
9
9
  :no_entry: Entry doesnt exist
10
10
  :decode_selected: selected
11
+ :list_select_selected: Selected
11
12
 
12
13
  :name: Name
13
14
  :mime: Mime
@@ -8,6 +8,7 @@
8
8
  :error: Błąd
9
9
  :no_entry: Wpis nie istnieje
10
10
  :decode_selected: wybranych
11
+ :list_select_selected: Wybranych
11
12
 
12
13
  :name: Nazwa
13
14
  :mime: Mime
@@ -9,7 +9,7 @@ exports.config =
9
9
  "bootstrap-additions": ["dist/bootstrap-additions.css"]
10
10
  "angular-motion": ["dist/angular-motion.css"]
11
11
  "angular-ui-tree": ["dist/angular-ui-tree.css"]
12
- "font-awesome": ["css/font-awesome.css"]
12
+ "fork-awesome": ["css/fork-awesome.css"]
13
13
 
14
14
  modules:
15
15
  definition: 'commonjs'
@@ -64,7 +64,7 @@ exports.config =
64
64
 
65
65
  copycat:
66
66
  fonts: [
67
- "node_modules/font-awesome/fonts"
67
+ "node_modules/fork-awesome/fonts"
68
68
  "node_modules/bootstrap/fonts"
69
69
  ]
70
70
  verbose: true
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
17
  spec.require_paths = ["lib"]
18
18
 
19
- spec.add_dependency "sequel", '~> 4'
19
+ spec.add_dependency "sequel", '~> 5'
20
20
  if defined? JRUBY_VERSION
21
21
  spec.add_dependency 'jdbc-sqlite3', '~> 3.8'
22
22
  else
@@ -54,9 +54,9 @@ module Engine2
54
54
  def invoke! handler
55
55
  if rmp = @request_action_proc
56
56
  action = self.class.new(node, assets, self)
57
- action_result = action.instance_exec(handler, *action.request_action_proc_params(handler), &rmp)
57
+ result = action.instance_exec(handler, *action.request_action_proc_params(handler), &rmp)
58
58
  action.post_process
59
- response = @requestable ? (action_result || {}) : action.invoke(handler)
59
+ response = @requestable ? (result || {}) : action.invoke(handler)
60
60
  response[:meta] = action.meta
61
61
  response
62
62
  else
@@ -72,8 +72,8 @@ module Engine2
72
72
  @meta[:arguments] = args
73
73
  end
74
74
 
75
- def execute time
76
- @meta[:execute] = time
75
+ def execute command
76
+ (@meta[:execute] ||= []) << command
77
77
  end
78
78
 
79
79
  def dynamic?
@@ -189,11 +189,12 @@ module Engine2
189
189
  @ws_methods.each do |method, blk|
190
190
  ws.on(method) do |evt|
191
191
  begin
192
- if method == :message
193
- blk.(JSON.parse(evt.data, symbolize_names: true), ws, evt)
194
- else
195
- blk.(evt, ws, evt)
196
- end
192
+ data = method == :message ? JSON.parse(evt.data, symbolize_names: true) : evt
193
+ action = self.class.new(node, assets, self)
194
+ result = action.instance_exec(data, ws, evt, &blk)
195
+ result = {} unless result.is_a?(Hash)
196
+ result[:meta] = action.meta
197
+ ws.send! result unless action.meta.empty?
197
198
  rescue Exception => e
198
199
  ws.send! error: {exception: e, method: method}
199
200
  end
@@ -222,18 +223,18 @@ module Engine2
222
223
  end
223
224
 
224
225
  module ActionAPISupport
225
- def info field
226
- (@meta[:info] ||= {})[field.to_sym] ||= {}
226
+ def fields field
227
+ (@meta[:fields] ||= {})[field.to_sym] ||= {}
227
228
  end
228
229
 
229
230
  def config
230
231
  @meta[:config] ||= {}
231
232
  end
232
233
 
233
- def info! *fields, options
234
+ def fields! *fields, options
234
235
  raise E2Error.new("No fields given to info") if fields.empty?
235
236
  fields.each do |field|
236
- info(field).merge! options # rmerge ?
237
+ fields(field).merge! options # rmerge ?
237
238
  end
238
239
  end
239
240
 
@@ -243,24 +244,24 @@ module Engine2
243
244
 
244
245
  def decorate list
245
246
  list.each do |f|
246
- info(f)[:loc] ||= LOCS[f.to_sym]
247
+ fields(f)[:loc] ||= LOCS[f.to_sym]
247
248
  end
248
249
  end
249
250
 
250
251
  def render field, options
251
- info! field, render: options
252
+ fields! field, render: options
252
253
  end
253
254
 
254
255
  def hide_fields *flds
255
- info! *flds, hidden: true
256
+ fields! *flds, hidden: true
256
257
  end
257
258
 
258
259
  def show_fields *flds
259
- info! *flds, hidden: false
260
+ fields! *flds, hidden: false
260
261
  end
261
262
 
262
263
  def field_filter *flds, filter
263
- info! *flds, filter: filter
264
+ fields! *flds, filter: filter
264
265
  end
265
266
  end
266
267
 
@@ -321,23 +322,6 @@ module Engine2
321
322
  show_fields *assets[:model].primary_keys
322
323
  end
323
324
 
324
- def get_type_info name
325
- model = assets[:model]
326
- info = case name
327
- when Symbol
328
- model.type_info[name]
329
- when Sequel::SQL::QualifiedIdentifier
330
- assoc = model.many_to_one_associations[name.table] || model.many_to_many_associations[name.table]
331
- raise E2Error.new("Association #{name.table} not found for model #{model}") unless assoc
332
- assoc.associated_class.type_info[name.column]
333
- else
334
- raise E2Error.new("Unknown type info key: #{name} in model #{model}")
335
- end
336
-
337
- raise E2Error.new("Type info not found for '#{name}' in model '#{model}'") unless info
338
- info
339
- end
340
-
341
325
  # def parent_model_name
342
326
  # model = @assets[:model]
343
327
  # prnt = node.parent
@@ -431,13 +415,13 @@ module Engine2
431
415
  end
432
416
 
433
417
  def find_record handler, id
434
- get_query[assets[:model].primary_keys_hash_qualified(split_keys(id))]
418
+ get_query.load assets[:model].primary_keys_hash_qualified(split_keys(id))
435
419
  end
436
420
 
437
421
  def select *args, use_pk: true, &blk
438
422
  ds = assets[:model].select(*args, &blk)
439
423
  ds = ds.ensure_primary_key if use_pk
440
- ds.setup!(@meta[:fields] = [])
424
+ ds.setup_query(@meta[:field_list] = [])
441
425
  end
442
426
  end
443
427
 
@@ -448,15 +432,15 @@ module Engine2
448
432
  end
449
433
 
450
434
  def field_tabs hash
451
- @meta[:tabs] = hash.map{|k, v| {name: k, loc: LOCS[k], fields: v} }
435
+ @meta[:tab_list] = hash.keys
436
+ @meta[:tabs] = hash.reduce({}){|h, (k, v)| h[k] = {name: k, loc: LOCS[k], field_list: v}; h}
452
437
  end
453
438
 
454
- def lazy_tab tab_name
455
- tabs = @meta[:tabs]
456
- raise E2Error.new("No tabs defined") unless tabs
457
- tab = tabs.find{|t| t[:name] == tab_name}
458
- raise E2Error.new("No tab #{tab_name} defined") unless tab
459
- tab[:lazy] = true
439
+ def tab *tabs, options
440
+ raise E2Error.new("No tabs given to info") if tabs.empty?
441
+ tabs.each do |tab|
442
+ @meta[:tabs][tab].merge! options # rmerge ?
443
+ end
460
444
  end
461
445
  end
462
446
 
@@ -484,7 +468,7 @@ module Engine2
484
468
 
485
469
  def ng_info! name, *selector, expression
486
470
  # expression = "'#{expression}'" if expression.is_a? String
487
- "action.meta.info['#{name}'].#{selector.join('.')} = #{expression}"
471
+ "action.meta.fields['#{name}'].#{selector.join('.')} = #{expression}"
488
472
  end
489
473
 
490
474
  def ng_call name, *args
@@ -542,6 +526,17 @@ module Engine2
542
526
  end
543
527
  end
544
528
 
529
+ module ActionDraggableSupport
530
+ def draggable
531
+ @meta[:draggable] ||= {}
532
+ end
533
+
534
+ def post_run
535
+ super
536
+ draggable[:position_field] ||= 'position' if @meta[:draggable]
537
+ end
538
+ end
539
+
545
540
  class MenuAction < Action
546
541
  include ActionMenuSupport
547
542
  action_type :menu
@@ -583,8 +578,8 @@ module Engine2
583
578
  nd = node.define_node node_name, (blk.arity > 2 ? OnChangeGetAction : OnChangePostAction)
584
579
  nd.*{request &blk}
585
580
 
586
- info! field, remote_onchange: node_name
587
- info! field, remote_onchange_record: :true if blk.arity > 2
581
+ fields! field, remote_onchange: node_name
582
+ fields! field, remote_onchange_record: :true if blk.arity > 2
588
583
  end
589
584
 
590
585
  class OnChangeAction < Action
@@ -626,7 +621,7 @@ module Engine2
626
621
  end
627
622
 
628
623
  module ActionListSupport
629
- include ActionModelSupport, ActionAPISupport, ActionTabSupport, ActionPanelSupport, ActionMenuSupport, ActionOnChangeSupport
624
+ include ActionModelSupport, ActionAPISupport, ActionTabSupport, ActionPanelSupport, ActionMenuSupport, ActionOnChangeSupport, ActionDraggableSupport
630
625
  attr_reader :filters, :orders
631
626
 
632
627
  def pre_run
@@ -638,7 +633,7 @@ module Engine2
638
633
  loc! LOCS[:list_locs]
639
634
  menu :menu do
640
635
  properties break: 2, group_class: "btn-group-xs"
641
- option :search_toggle, icon: "search", show: "action.meta.search_fields", active: "action.ui_state.search_active", button_loc: false
636
+ option :search_toggle, icon: "search", show: "action.meta.search_field_list", active: "action.ui_state.search_active", button_loc: false
642
637
  # divider
643
638
  option :refresh, icon: "refresh", button_loc: false
644
639
  option :default_order, icon: "signal", button_loc: false
@@ -669,7 +664,7 @@ module Engine2
669
664
 
670
665
  def post_run
671
666
  unless panel[:class]
672
- panel_class case @meta[:fields].size
667
+ panel_class case @meta[:field_list].size
673
668
  when 1..3; ''
674
669
  when 4..6; 'modal-large'
675
670
  else; 'modal-huge'
@@ -687,21 +682,22 @@ module Engine2
687
682
  # end
688
683
 
689
684
  def post_process
690
- if fields = @meta[:search_fields]
691
- fields = fields - static.meta[:search_fields] if dynamic?
685
+ model = assets[:model]
686
+ if fields = @meta[:search_field_list]
687
+ fields = fields - static.meta[:search_field_list] if dynamic?
692
688
 
693
689
  decorate(fields)
694
690
  fields.each do |name|
695
- type_info = get_type_info(name)
691
+ type_info = model.find_type_info(name)
696
692
 
697
- # render = info[name][:render]
693
+ # render = fields[name][:render]
698
694
  # if not render
699
- # info[name][:render] = find_renderer(type_info)
695
+ # fields[name][:render] = find_renderer(type_info)
700
696
  # else
701
- # info[name][:render].merge!(find_renderer(type_info)){|key, v1, v2|v1}
697
+ # fields[name][:render].merge!(find_renderer(type_info)){|key, v1, v2|v1}
702
698
  # end
703
699
 
704
- info(name)[:render] ||= begin # set before :fields
700
+ fields(name)[:render] ||= begin # set before :field_list
705
701
  renderer = DefaultSearchRenderers[type_info[:type]] || DefaultSearchRenderers[type_info[:otype]]
706
702
  raise E2Error.new("No search renderer found for field '#{type_info[:name]}'") unless renderer
707
703
  renderer.(self, type_info)
@@ -712,12 +708,12 @@ module Engine2
712
708
  end
713
709
  end
714
710
 
715
- if fields = @meta[:fields]
716
- fields = fields - static.meta[:fields] if dynamic?
711
+ if fields = @meta[:field_list]
712
+ fields = fields - static.meta[:field_list] if dynamic?
717
713
 
718
714
  decorate(fields)
719
715
  fields.each do |name|
720
- type_info = get_type_info(name)
716
+ type_info = model.find_type_info(name)
721
717
  proc = ListRendererPostProcessors[type_info[:type]]
722
718
  proc.(self, name, type_info) if proc
723
719
  end
@@ -731,19 +727,20 @@ module Engine2
731
727
  end
732
728
 
733
729
  def sortable *flds
734
- flds = @meta[:fields] if flds.empty?
735
- info! *flds, sort: true
730
+ flds = @meta[:field_list] if flds.empty?
731
+ fields! *flds, sort: true
736
732
  end
737
733
 
738
734
  def search_live *flds
739
- flds = @meta[:search_fields] if flds.empty?
740
- info! *flds, search_live: true
735
+ flds = @meta[:search_field_list] if flds.empty?
736
+ fields! *flds, search_live: true
741
737
  end
742
738
 
743
739
  def searchable *flds
740
+ @meta.delete(:tab_list)
744
741
  @meta.delete(:tabs)
745
742
  search_template 'scaffold/search'
746
- @meta[:search_fields] = *flds
743
+ @meta[:search_field_list] = *flds
747
744
  end
748
745
 
749
746
  def searchable_tabs tabs
@@ -760,8 +757,8 @@ module Engine2
760
757
  end
761
758
 
762
759
  def filter_case_insensitive name
763
- raise E2Error.new("Field '#{name}' needs to be a string one") unless get_type_info(name)[:otype] == :string
764
- filter(name){|query, hash, handler| query.where(name.ilike("%#{hash[name]}%")) }
760
+ raise E2Error.new("Field '#{name}' needs to be a string one") unless assets[:model].find_type_info(name)[:otype] == :string
761
+ filter(name){|handler, query, hash| query.where(name.ilike("%#{hash[name]}%")) }
765
762
  end
766
763
 
767
764
  def order name, &blk
@@ -794,7 +791,7 @@ module Engine2
794
791
  def validate_and_approve handler, record, parent_id
795
792
  static.before_approve(handler, record)
796
793
  record.valid?
797
- validate_record(handler, record)
794
+ validate_record(handler, record, parent_id)
798
795
  if record.errors.empty?
799
796
  static.after_approve(handler, record)
800
797
  true
@@ -828,10 +825,10 @@ module Engine2
828
825
  (@validations ||= {})[name] = blk
829
826
  end
830
827
 
831
- def validate_record handler, record
828
+ def validate_record handler, record, parent_id
832
829
  @validations.each do |name, val|
833
830
  unless record.errors[name]
834
- result = val.(record, handler)
831
+ result = val.(handler, record, parent_id)
835
832
  record.errors.add(name, result) if result
836
833
  end
837
834
  end if @validations
@@ -844,7 +841,7 @@ module Engine2
844
841
 
845
842
  def post_run
846
843
  super
847
- validate_fields *node.parent.*.meta[:fields] unless validate_fields
844
+ validate_fields *node.parent.*.meta[:field_list] unless validate_fields
848
845
  end
849
846
  end
850
847
 
@@ -859,7 +856,7 @@ module Engine2
859
856
  end
860
857
 
861
858
  def validate_and_approve handler, record, parent_id, validate_only = self.class.validate_only
862
- if validate_only then
859
+ if validate_only
863
860
  super(handler, record, parent_id)
864
861
  else
865
862
  record.skip_save_refresh = true
@@ -868,7 +865,7 @@ module Engine2
868
865
  assoc = assets[:assoc]
869
866
  new_assoc = record.new? && assoc && assoc[:type]
870
867
 
871
- save = lambda do|c|
868
+ save = lambda do |c|
872
869
  if super(handler, record, parent_id)
873
870
  if new_assoc == :one_to_many
874
871
  handler.permit parent_id
@@ -965,16 +962,16 @@ module Engine2
965
962
  end
966
963
 
967
964
  def post_process
968
- if fields = @meta[:fields]
969
- fields = fields - static.meta[:fields] if dynamic?
965
+ if fields = @meta[:field_list]
966
+ model = assets[:model]
967
+ fields = fields - static.meta[:field_list] if dynamic?
970
968
 
971
969
  decorate(fields)
972
970
 
973
971
  fields.each do |name|
974
- # type_info = model.type_info.fetch(name)
975
- type_info = get_type_info(name)
972
+ type_info = model.find_type_info(name)
976
973
 
977
- info(name)[:render] ||= begin
974
+ fields(name)[:render] ||= begin
978
975
  renderer = DefaultFormRenderers[type_info[:type]] # .merge(default: true)
979
976
  raise E2Error.new("No form renderer found for field '#{type_info[:name]}' of type '#{type_info[:type]}'") unless renderer
980
977
  renderer.(self, type_info)
@@ -987,11 +984,11 @@ module Engine2
987
984
  assoc = assets[:assoc]
988
985
  if assoc && assoc[:type] == :one_to_many
989
986
  # fields.select{|f| assoc[:keys].include? f}.each do |key|
990
- # # hide_fields(key) if self[:info, key, :hidden] == nil
991
- # info! key, disabled: true
987
+ # # hide_fields(key) if self[:fields, key, :hidden] == nil
988
+ # fields! key, disabled: true
992
989
  # end
993
990
  assoc[:keys].each do |key|
994
- info! key, disabled: true if fields.include? key
991
+ fields! key, disabled: true if fields.include? key
995
992
  end
996
993
  end
997
994
  end
@@ -1009,7 +1006,7 @@ module Engine2
1009
1006
  end
1010
1007
 
1011
1008
  def hr_after field, message = '-'
1012
- info! field, hr: message
1009
+ fields! field, hr: message
1013
1010
  end
1014
1011
  end
1015
1012
 
@@ -1022,8 +1019,8 @@ module Engine2
1022
1019
 
1023
1020
  def pre_run
1024
1021
  super
1025
- panel_title LOCS[:create_title]
1026
- node.parent.*.menu(:menu).option_at 0, node.name, icon: "plus-sign", button_loc: false
1022
+ panel_title "#{LOCS[:create_title]} - #{LOCS[assets[:model].table_name]}"
1023
+ node.parent.*.menu(:menu).option_at 0, node.name, icon: "plus-sign", button_loc: false if node.parent.*.is_a?(ListAction)
1027
1024
 
1028
1025
  hide_pk unless assets[:model].natural_key
1029
1026
  end
@@ -1058,7 +1055,7 @@ module Engine2
1058
1055
 
1059
1056
  def pre_run
1060
1057
  super
1061
- panel_title LOCS[:modify_title]
1058
+ panel_title "#{LOCS[:modify_title]} - #{LOCS[assets[:model].table_name]}"
1062
1059
  node.parent.*.menu(:item_menu).option node.name, icon: "pencil", button_loc: false
1063
1060
  end
1064
1061
 
@@ -1084,7 +1081,7 @@ module Engine2
1084
1081
  def post_run
1085
1082
  super
1086
1083
  assets[:model].primary_keys.each do |key| # pre_run ?
1087
- info! key, disabled: true
1084
+ fields! key, disabled: true
1088
1085
  end
1089
1086
  end
1090
1087
  end
@@ -1099,7 +1096,7 @@ module Engine2
1099
1096
  def pre_run
1100
1097
  super
1101
1098
  panel_template 'scaffold/view'
1102
- panel_title LOCS[:view_title]
1099
+ panel_title "#{LOCS[:view_title]} - #{LOCS[assets[:model].table_name]}"
1103
1100
  panel[:backdrop] = true
1104
1101
 
1105
1102
  menu(:panel_menu).option :cancel, icon: "remove"
@@ -1126,12 +1123,13 @@ module Engine2
1126
1123
  end
1127
1124
 
1128
1125
  def post_process
1129
- if fields = @meta[:fields]
1130
- fields = fields - static.meta[:fields] if dynamic?
1126
+ if fields = @meta[:field_list]
1127
+ model = assets[:model]
1128
+ fields = fields - static.meta[:field_list] if dynamic?
1131
1129
 
1132
1130
  decorate(fields)
1133
1131
  fields.each do |name|
1134
- type_info = get_type_info(name)
1132
+ type_info = model.find_type_info(name)
1135
1133
  proc = ListRendererPostProcessors[type_info[:type]]
1136
1134
  proc.(self, name, type_info) if proc
1137
1135
  end
@@ -1174,87 +1172,92 @@ module Engine2
1174
1172
 
1175
1173
  (FormRendererPostProcessors ||= {}).merge!(
1176
1174
  boolean: lambda{|action, field, info|
1177
- action.info(field)[:render].merge! true_value: info[:true_value], false_value: info[:false_value]
1178
- action.info(field)[:dont_strip] = info[:dont_strip] if info[:dont_strip]
1175
+ action.fields(field)[:render].merge! true_value: info[:true_value], false_value: info[:false_value]
1176
+ action.fields(field)[:dont_strip] = info[:dont_strip] if info[:dont_strip]
1179
1177
  },
1180
1178
  date: lambda{|action, field, info|
1181
- action.info(field)[:render].merge! format: info[:format], model_format: info[:model_format]
1179
+ action.fields(field)[:render].merge! format: info[:format], model_format: info[:model_format]
1182
1180
  if date_to = info[:other_date]
1183
- action.info(field)[:render].merge! other_date: date_to #, format: info[:format], model_format: info[:model_format]
1181
+ action.fields(field)[:render].merge! other_date: date_to #, format: info[:format], model_format: info[:model_format]
1184
1182
  action.hide_fields date_to
1185
1183
  elsif time = info[:other_time]
1186
- action.info(field)[:render].merge! other_time: time
1184
+ action.fields(field)[:render].merge! other_time: time
1187
1185
  action.hide_fields time
1188
1186
  end
1189
1187
  },
1190
1188
  time: lambda{|action, field, info|
1191
- action.info(field)[:render].merge! format: info[:format], model_format: info[:model_format]
1189
+ render = action.fields(field)[:render]
1190
+ render[:type] ||= info[:otype] == :string ? :string : :number
1191
+ render.merge! format: info[:format], model_format: info[:model_format]
1192
1192
  },
1193
1193
  decimal_date: lambda{|action, field, info|
1194
1194
  FormRendererPostProcessors[:date].(action, field, info)
1195
- action.info! field, type: :decimal_date
1195
+ action.fields! field, type: :decimal_date
1196
1196
  },
1197
1197
  decimal_time: lambda{|action, field, info|
1198
1198
  FormRendererPostProcessors[:time].(action, field, info)
1199
- action.info! field, type: :decimal_time
1199
+ action.fields! field, type: :decimal_time
1200
1200
  },
1201
1201
  datetime: lambda{|action, field, info|
1202
- action.info(field)[:render].merge! date_format: info[:date_format], time_format: info[:time_format], date_model_format: info[:date_model_format], time_model_format: info[:time_model_format]
1202
+ action.fields(field)[:render].merge! date_format: info[:date_format], time_format: info[:time_format], date_model_format: info[:date_model_format], time_model_format: info[:time_model_format]
1203
1203
  },
1204
1204
  currency: lambda{|action, field, info|
1205
- action.info(field)[:render].merge! symbol: info[:symbol]
1205
+ action.fields(field)[:render].merge! symbol: info[:symbol]
1206
1206
  },
1207
1207
  # date_range: lambda{|action, field, info|
1208
- # action.info[field][:render].merge! other_date: info[:other_date], format: info[:format], model_format: info[:model_format]
1208
+ # action.fields[field][:render].merge! other_date: info[:other_date], format: info[:format], model_format: info[:model_format]
1209
1209
  # action.hide_fields info[:other_date]
1210
- # action.info[field][:decimal_date] = true if info[:validations][:decimal_date]
1210
+ # action.fields[field][:decimal_date] = true if info[:validations][:decimal_date]
1211
1211
  # },
1212
1212
  list_select: lambda{|action, field, info|
1213
- action.info(field)[:render].merge! list: info[:list]
1213
+ render = action.fields(field)[:render]
1214
+ render.merge! values: info[:values]
1215
+ render.merge! max_length: info[:max_length], max_length_html: info[:max_length_html], separator: info[:separator] if info[:multiselect]
1214
1216
  },
1215
1217
  many_to_one: lambda{|action, field, info|
1216
- field_info = action.info(field)
1218
+ field_info = action.fields(field)
1217
1219
  field_info[:assoc] = :"#{info[:assoc_name]}!"
1218
1220
  field_info[:fields] = info[:keys]
1219
1221
  field_info[:type] = info[:otype]
1220
1222
 
1221
1223
  (info[:keys] - [field]).each do |of|
1222
- f_info = action.info(of)
1224
+ f_info = action.fields(of)
1223
1225
  f_info[:hidden] = true
1224
1226
  f_info[:type] = action.assets[:model].type_info[of].fetch(:otype)
1225
1227
  end
1226
1228
  },
1227
1229
  file_store: lambda{|action, field, info|
1228
- action.info(field)[:render].merge! multiple: info[:multiple]
1230
+ action.fields(field)[:render].merge! multiple: info[:multiple]
1229
1231
  },
1230
1232
  star_to_many_field: lambda{|action, field, info|
1231
- field_info = action.info(field)
1233
+ field_info = action.fields(field)
1232
1234
  field_info[:assoc] = :"#{info[:assoc_name]}!"
1233
1235
  }
1234
1236
  )
1235
1237
 
1236
1238
  (ListRendererPostProcessors ||= {}).merge!(
1237
1239
  boolean: lambda{|action, field, info|
1238
- action.info! field, type: :boolean # move to action ?
1239
- action.info(field)[:render] ||= {}
1240
- action.info(field)[:render].merge! true_value: info[:true_value], false_value: info[:false_value]
1240
+ action.fields! field, type: :boolean # move to action ?
1241
+ action.fields(field)[:render] ||= {}
1242
+ action.fields(field)[:render].merge! true_value: info[:true_value], false_value: info[:false_value]
1241
1243
  },
1242
1244
  list_select: lambda{|action, field, info|
1243
- action.info! field, type: :list_select
1244
- action.info(field)[:render] ||= {}
1245
- action.info(field)[:render].merge! list: info[:list]
1245
+ action.fields! field, type: :list_select
1246
+ render = (action.fields(field)[:render] ||= {})
1247
+ render.merge! values: info[:values]
1248
+ render.merge! multiselect: true if info[:multiselect]
1246
1249
  },
1247
1250
  datetime: lambda{|action, field, info|
1248
- action.info! field, type: :datetime
1251
+ action.fields! field, type: :datetime
1249
1252
  },
1250
1253
  decimal_date: lambda{|action, field, info|
1251
- action.info! field, type: :decimal_date
1254
+ action.fields! field, type: :decimal_date
1252
1255
  },
1253
1256
  decimal_time: lambda{|action, field, info|
1254
- action.info! field, type: :decimal_time
1257
+ action.fields! field, type: :decimal_time
1255
1258
  },
1256
1259
  # date_range: lambda{|action, field, info|
1257
- # action.info[field][:type] = :decimal_date if info[:validations][:decimal_date] # ? :decimal_date : :date
1260
+ # action.fields[field][:type] = :decimal_date if info[:validations][:decimal_date] # ? :decimal_date : :date
1258
1261
  # }
1259
1262
  )
1260
1263
 
@@ -1269,21 +1272,21 @@ module Engine2
1269
1272
  keys = info[:keys].map{|k| model.table_name.q(k)}
1270
1273
  end
1271
1274
 
1272
- field_info = action.info(field)
1275
+ field_info = action.fields(field)
1273
1276
  field_info[:assoc] = :"#{info[:assoc_name]}!"
1274
1277
  field_info[:fields] = keys
1275
1278
  field_info[:type] = info[:otype]
1276
1279
 
1277
1280
  (keys - [field]).each do |of|
1278
- f_info = action.info(of)
1281
+ f_info = action.fields(of)
1279
1282
  raise E2Error.new("Missing searchable field: '#{of}' in model '#{action.assets[:model]}'") unless f_info
1280
1283
  f_info[:hidden_search] = true
1281
1284
  f_info[:type] = model.type_info[of].fetch(:otype)
1282
1285
  end
1283
1286
  },
1284
1287
  date: lambda{|action, field, info|
1285
- action.info(field)[:render] ||= {}
1286
- action.info(field)[:render].merge! format: info[:format], model_format: info[:model_format] # Model::DEFAULT_DATE_FORMAT
1288
+ action.fields(field)[:render] ||= {}
1289
+ action.fields(field)[:render].merge! format: info[:format], model_format: info[:model_format] # Model::DEFAULT_DATE_FORMAT
1287
1290
  },
1288
1291
  decimal_date: lambda{|action, field, info|
1289
1292
  SearchRendererPostProcessors[:date].(action, field, info)
@@ -1313,14 +1316,15 @@ module Engine2
1313
1316
  boolean: lambda{|action, info| Templates.checkbox_buttons(optional: !info[:required])},
1314
1317
  currency: lambda{|action, info| Templates.currency},
1315
1318
  list_select: lambda{|action, info|
1316
- length = info[:list].length
1317
- if length <= 3
1319
+ length = info[:values].length
1320
+ max_length = info[:values].map(&:last).max_by(&:length).length
1321
+ if info[:multiselect]
1322
+ Templates.list_bsmselect(max_length)
1323
+ elsif length <= 3
1318
1324
  Templates.list_buttons(optional: !info[:required])
1319
1325
  elsif length <= 15
1320
- max_length = info[:list].max_by{|a|a.last.length}.last.length
1321
1326
  Templates.list_bsselect(max_length, optional: !info[:required])
1322
1327
  else
1323
- max_length = info[:list].max_by{|a|a.last.length}.last.length
1324
1328
  Templates.list_select(max_length, optional: !info[:required])
1325
1329
  end
1326
1330
  },
@@ -1344,7 +1348,7 @@ module Engine2
1344
1348
  string: lambda{|action, info| SearchTemplates.input_text},
1345
1349
  boolean: lambda{|action, info| SearchTemplates.checkbox_buttons},
1346
1350
  list_select: lambda{|action, info|
1347
- length = info[:list].length
1351
+ length = info[:values].length
1348
1352
  if length <= 3
1349
1353
  SearchTemplates.list_buttons
1350
1354
  elsif length <= 15