engine2 1.0.8 → 1.0.9

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -3
  3. data/app/actions.coffee +87 -50
  4. data/app/app.css +2 -1
  5. data/app/engine2.coffee +37 -19
  6. data/app/modal.coffee +8 -3
  7. data/bower.json +3 -2
  8. data/conf/message.yaml +3 -0
  9. data/conf/message_pl.yaml +5 -2
  10. data/config.coffee +16 -15
  11. data/engine2.gemspec +1 -1
  12. data/lib/engine2/action.rb +51 -23
  13. data/lib/engine2/action/array.rb +94 -1
  14. data/lib/engine2/action/decode.rb +29 -3
  15. data/lib/engine2/action/delete.rb +1 -2
  16. data/lib/engine2/action/infra.rb +5 -4
  17. data/lib/engine2/action/list.rb +70 -25
  18. data/lib/engine2/action/save.rb +0 -2
  19. data/lib/engine2/action_node.rb +2 -4
  20. data/lib/engine2/core.rb +30 -21
  21. data/lib/engine2/handler.rb +5 -5
  22. data/lib/engine2/model.rb +18 -9
  23. data/lib/engine2/models/Files.rb +2 -0
  24. data/lib/engine2/scheme.rb +1 -6
  25. data/lib/engine2/templates.rb +32 -6
  26. data/lib/engine2/type_info.rb +9 -5
  27. data/lib/engine2/version.rb +1 -1
  28. data/package.json +9 -8
  29. data/views/fields/checkbox_button.slim +6 -0
  30. data/views/fields/checkbox_buttons.slim +1 -1
  31. data/views/fields/list_mbuttons.slim +9 -0
  32. data/views/fields/list_mbuttons_opt.slim +11 -0
  33. data/views/fields/list_mselect.slim +12 -0
  34. data/views/fields/scaffold.slim +1 -1
  35. data/views/fields/typeahead_picker.slim +8 -5
  36. data/views/infra/inspect.slim +19 -16
  37. data/views/scaffold/fields.slim +3 -1
  38. data/views/scaffold/search.slim +2 -2
  39. data/views/scaffold/search_collapse.slim +2 -2
  40. data/views/scaffold/search_tabs.slim +2 -2
  41. data/views/search_fields/date.slim +20 -0
  42. data/views/search_fields/list_mbuttons.slim +12 -0
  43. data/views/search_fields/typeahead_picker.slim +4 -3
  44. metadata +11 -5
@@ -97,11 +97,16 @@ angular.module('Engine2')
97
97
  modal.show()
98
98
  modal
99
99
 
100
- error: (title, msg, html) ->
101
- body = if html then msg else "<div class='alert alert-danger'>#{msg}</div>"
102
- clazz = if html then "modal-huge" else "modal-large"
100
+ show_modal: (title, msg, options = {html: false, alert_class: 'alert-danger', modal_class: 'modal-large'}) ->
101
+ body = if options.html then msg else "<div class='alert alert-#{options.alert_class}'>#{msg}</div>"
102
+ clazz = if options.html then "modal-huge" else options.modal_class
103
103
  @show meta: panel: (panel_template: "close_m", template_string: body, title: title, class: clazz, footer: true) # message: msg,
104
104
 
105
+
106
+ info: (title, msg, options = {alert_class: 'info', modal_class: 'modal-large'}) -> @show_modal(title, msg, options)
107
+ warning: (title, msg, options = {alert_class: 'warning', modal_class: 'modal-large'}) -> @show_modal(title, msg, options)
108
+ error: (title, msg, options = {alert_class: 'danger', modal_class: 'modal-huge'}) -> @show_modal(title, msg, options)
109
+
105
110
  confirm: (title, msg, action) ->
106
111
  body = "<div class='alert alert-warning'>#{msg}</div>"
107
112
  clazz = "modal-large"
data/bower.json CHANGED
@@ -2,9 +2,10 @@
2
2
  "name": "engine2",
3
3
  "version": "1.0.0",
4
4
  "dependencies": {
5
- "angular-strap": "^2.3.10",
5
+ "angular-strap": "^2.3.12",
6
6
  "angular": "^1.5.8",
7
- "angular-websocket": "^2.0.0"
7
+ "angular-websocket": "^2.0.0",
8
+ "angular-toastr": "^2.1.1"
8
9
  },
9
10
  "overrides": {
10
11
  "angular": {
@@ -10,11 +10,14 @@
10
10
  :decode_selected: selected
11
11
  :list_select_selected: Selected
12
12
 
13
+ :E2Files: Files
14
+ :files: File
13
15
  :name: Name
14
16
  :mime: Mime
15
17
  :owner: Owner
16
18
  :model: Model
17
19
  :field: Field
20
+ :uploaded: Uploaded
18
21
  :updated: Updated
19
22
 
20
23
  :ok: Ok
@@ -10,11 +10,14 @@
10
10
  :decode_selected: wybranych
11
11
  :list_select_selected: Wybranych
12
12
 
13
+ :E2Files: Pliki
14
+ :files: Plik
13
15
  :name: Nazwa
14
16
  :mime: Mime
15
17
  :owner: Właściciel
16
18
  :model: Model
17
19
  :field: Pole
20
+ :uploaded: Wysłany
18
21
  :updated: Aktualizowany
19
22
 
20
23
  :ok: Ok
@@ -31,12 +34,12 @@
31
34
  :select_toggle: Zaznacz
32
35
  :confirm_delete: Usuń
33
36
  :confirm_delete_title: <span class='glyphicon glyphicon-trash'></span> Potwierdzenie
34
- :confirm_bulk_delete: Usuń zaznacznone
37
+ :confirm_bulk_delete: Usuń zaznaczone
35
38
  :delete_restricted: Blokujące relacje
36
39
  :confirm_bulk_delete_title: <span class='glyphicon glyphicon-trash'></span> Potwierdzenie
37
40
  :confirm_unlink: Odłącz
38
41
  :confirm_unlink_title: <span class='glyphicon glyphicon-minus'></span> Potwierdzenie
39
- :confirm_bulk_unlink: Odłącz zaznacznone
42
+ :confirm_bulk_unlink: Odłącz zaznaczone
40
43
  :confirm_bulk_unlink_title: <span class='glyphicon glyphicon-minus'></span> Potwierdzenie
41
44
  :debug_info: Debug info
42
45
  :show_meta: Metainfo
@@ -24,8 +24,8 @@ exports.config =
24
24
  files:
25
25
  javascripts:
26
26
  joinTo:
27
- 'engine2vendor.js': /^node_modules|bower_components/
28
- 'engine2.js': /^app/
27
+ 'assets/engine2vendor.js': /^node_modules|bower_components/
28
+ 'assets/engine2.js': /^app/
29
29
  order:
30
30
  before: [
31
31
  "app/engine2.coffee"
@@ -33,35 +33,36 @@ exports.config =
33
33
 
34
34
  stylesheets:
35
35
  joinTo:
36
- 'engine2vendor.css': /^node_modules/
37
- 'engine2.css': /^app/
38
- order:
39
- before: [
40
- /bootstrap.css$/
41
- ]
36
+ 'assets/engine2vendor.css': /^(?:node_modules||bower_components)\/(?!(bootstrap\/))/
37
+ 'assets/bootstrap.css': /^node_modules\/(bootstrap\/)/
38
+ 'assets/engine2.css': /^app/
39
+ # order:
40
+ # before: [
41
+ # /bootstrap\.css$/
42
+ # ]
42
43
 
43
44
  plugins:
44
45
  on: ["ng-annotate-brunch"]
45
46
 
46
47
  uglify:
47
- mangle: false
48
+ mangle: true
48
49
  compress:
49
50
  global_defs:
50
51
  DEBUG: false
51
52
 
52
53
  replacement:
53
54
  replacements: [
54
- files: [/vendor.js$/]
55
+ files: [/vendor\.js$/]
55
56
  match: (
56
57
  fix = "$modal.$element = compileData.link(modalScope, function(clonedElement, scope) {});"
57
58
  find: fix.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1")
58
59
  replace: "#{fix}$modal.$backdrop = backdropElement;"
59
- ),
60
- files: [/vendor\.css$/]
61
- match: (
62
- find: "../fonts"
63
- replace: "fonts"
64
60
  )
61
+ # files: [/\.css$/]
62
+ # match: (
63
+ # find: "../fonts"
64
+ # replace: "fonts"
65
+ # )
65
66
  ]
66
67
 
67
68
  copycat:
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency 'faye-websocket', '~> 0.10'
28
28
 
29
29
  spec.add_development_dependency "bundler", "~> 2.00"
30
- spec.add_development_dependency "rake", "~> 12"
30
+ spec.add_development_dependency "rake", "~> 13"
31
31
  end
@@ -69,7 +69,7 @@ module Engine2
69
69
  action = self.class.new(node, assets, self)
70
70
  result = action.instance_exec(handler, *action.request_action_proc_params(handler), &rmp)
71
71
  action.post_process
72
- response = @requestable ? (result || {}) : action.invoke(handler)
72
+ response = @requestable ? (result.is_a?(Hash) ? result : {}) : action.invoke(handler)
73
73
  response[:meta] = action.meta
74
74
  response
75
75
  else
@@ -82,7 +82,7 @@ module Engine2
82
82
  end
83
83
 
84
84
  def arguments args
85
- @meta[:arguments] = args
85
+ (@meta[:arguments] ||= {}).merge! args
86
86
  end
87
87
 
88
88
  def execute command
@@ -235,7 +235,8 @@ module Engine2
235
235
  class RootAction < Action
236
236
  def initialize *args
237
237
  super
238
- @meta.merge! environment: Handler::environment, application: Engine2::SETTINGS[:name], key_separator: Engine2::SETTINGS[:key_separator], ws_methods: ActionWebSocketSupport::WS_METHODS
238
+ @meta.merge! environment: Handler::environment, application: Engine2::SETTINGS[:name], uuid: SecureRandom.uuid,
239
+ key_separator: Engine2::SETTINGS[:key_separator], ws_methods: ActionWebSocketSupport::WS_METHODS
239
240
  end
240
241
  end
241
242
 
@@ -459,7 +460,7 @@ module Engine2
459
460
 
460
461
  module ActionAngularSupport
461
462
  def ng_execute expr
462
- (@meta[:execute] ||= "") << expr + ";"
463
+ (@meta[:execute] ||= String.new) << expr + ";"
463
464
  end
464
465
 
465
466
  def ng_record! name, value
@@ -586,13 +587,12 @@ module Engine2
586
587
  end
587
588
 
588
589
  module ActionOnChangeSupport
589
- def on_change field, &blk
590
+ def on_change field, trigger_on_start = false, &blk
590
591
  node_name = :"#{field}_on_change"
591
- nd = node.define_node node_name, (blk.arity > 2 ? OnChangeGetAction : OnChangePostAction)
592
+ nd = node.define_node node_name, (blk.arity <= 2 ? OnChangeGetAction : OnChangePostAction)
592
593
  nd.*{request &blk}
593
594
 
594
- fields! field, remote_onchange: node_name
595
- fields! field, remote_onchange_record: :true if blk.arity > 2
595
+ fields! field, remote_onchange: {action: node_name, record: blk.arity > 2, trigger_on_start: trigger_on_start}
596
596
  end
597
597
 
598
598
  class OnChangeAction < Action
@@ -608,9 +608,9 @@ module Engine2
608
608
  end
609
609
  end
610
610
 
611
- def invoke handler
612
- {}
613
- end
611
+ # def invoke handler
612
+ # {}
613
+ # end
614
614
  end
615
615
 
616
616
  class OnChangeGetAction < OnChangeAction
@@ -635,17 +635,17 @@ module Engine2
635
635
 
636
636
  module ActionListSupport
637
637
  include ActionModelSupport, ActionAPISupport, ActionTabSupport, ActionPanelSupport, ActionMenuSupport, ActionOnChangeSupport, ActionDraggableSupport
638
- attr_reader :filters, :orders
638
+ attr_reader :filters, :orders, :default_order_field
639
639
 
640
640
  def pre_run
641
641
  super
642
642
  config.merge!(per_page: 10, use_count: false, selectable: true) # search_active: false,
643
643
 
644
644
  panel_template 'scaffold/list'
645
- panel_title "#{:list.icon} #{LOCS[assets[:model].name.to_sym]}"
645
+ panel_title "#{assets[:model].model_icon.icon} #{LOCS[assets[:model].model_route]}"
646
646
  loc! LOCS[:list_locs]
647
647
  menu :menu do
648
- properties break: 2, group_class: "btn-group-xs"
648
+ properties break: 2, group_class: "btn-group-sm"
649
649
  option :search_toggle, icon: "search", show: "action.meta.search_field_list", active: "action.ui_state.search_active", button_loc: false
650
650
  # divider
651
651
  option :refresh, icon: "refresh", button_loc: false
@@ -657,7 +657,7 @@ module Engine2
657
657
  end
658
658
 
659
659
  menu :item_menu do
660
- properties break: 1, group_class: "btn-group-xs"
660
+ properties break: 1, group_class: "btn-group-sm"
661
661
  end
662
662
 
663
663
  @meta[:state] = [:query, :ui_state]
@@ -676,6 +676,8 @@ module Engine2
676
676
  end
677
677
 
678
678
  def post_run
679
+ super
680
+
679
681
  unless panel[:class]
680
682
  panel_class case @meta[:field_list].size
681
683
  when 1..3; ''
@@ -684,7 +686,6 @@ module Engine2
684
686
  end
685
687
  end
686
688
 
687
- super
688
689
  @meta[:primary_fields] = assets[:model].primary_keys
689
690
  end
690
691
 
@@ -744,8 +745,15 @@ module Engine2
744
745
  fields! *flds, sort: true
745
746
  end
746
747
 
748
+ def default_order order
749
+ @default_order_field = order
750
+ end
751
+
747
752
  def search_live *flds
748
- flds = @meta[:search_field_list] if flds.empty?
753
+ if flds.empty?
754
+ flds = @meta[:search_field_list]
755
+ @meta[:disable_search_button] = true
756
+ end
749
757
  fields! *flds, search_live: true
750
758
  end
751
759
 
@@ -770,8 +778,12 @@ module Engine2
770
778
  end
771
779
 
772
780
  def filter_case_insensitive name
773
- raise E2Error.new("Field '#{name}' needs to be a string one") unless assets[:model].find_type_info(name)[:otype] == :string
774
- filter(name){|handler, query, hash| query.where(name.ilike("%#{hash[name]}%")) }
781
+ model = assets[:model]
782
+ raise E2Error.new("Field '#{name}' needs to be a string") unless model.find_type_info(name)[:otype] == :string
783
+ filter name do |handler, query, hash|
784
+ value = hash[name]
785
+ value ? query.where(model.table_name.q(name).ilike("%#{value}%")) : query
786
+ end
775
787
  end
776
788
 
777
789
  def order name, &blk
@@ -817,7 +829,10 @@ module Engine2
817
829
  model = assets[:model]
818
830
  handler.permit json_rec.is_a?(Hash)
819
831
  val_fields = (dynamic? ? static.validate_fields : @validate_fields) || model.type_info.keys
820
- handler.permit (json_rec.keys - val_fields).empty?
832
+ left_fields = (json_rec.keys - val_fields)
833
+
834
+ puts "Left: #{left_fields.inspect}" unless left_fields.empty?
835
+ handler.permit left_fields.empty?
821
836
 
822
837
  record = model.call(json_rec)
823
838
  record.validate_fields = val_fields
@@ -1025,6 +1040,14 @@ module Engine2
1025
1040
  def hr_after field, message = '-'
1026
1041
  fields! field, hr: message
1027
1042
  end
1043
+
1044
+ def create?
1045
+ @action_type == :create
1046
+ end
1047
+
1048
+ def modify?
1049
+ @action_type == :modify
1050
+ end
1028
1051
  end
1029
1052
 
1030
1053
  module ActionCreateSupport
@@ -1037,7 +1060,7 @@ module Engine2
1037
1060
  def pre_run
1038
1061
  super
1039
1062
  panel_title "#{LOCS[:create_title]} - #{LOCS[assets[:model].table_name]}"
1040
- node.parent.*.menu(:menu).option_at 0, node.name, icon: "plus-sign", button_loc: false if node.parent.*.is_a?(ListAction)
1063
+ node.parent.*.menu(:menu).option_at 0, node.name, icon: "plus-sign", button_loc: false if node.parent.*.is_a?(ActionListSupport)
1041
1064
 
1042
1065
  hide_pk unless assets[:model].natural_key
1043
1066
  end
@@ -1305,6 +1328,10 @@ module Engine2
1305
1328
  action.fields(field)[:render] ||= {}
1306
1329
  action.fields(field)[:render].merge! format: info[:format], model_format: info[:model_format] # Model::DEFAULT_DATE_FORMAT
1307
1330
  },
1331
+ datetime: lambda{|action, field, info|
1332
+ action.fields(field)[:render] ||= {}
1333
+ action.fields(field)[:render].merge! format: info[:date_format], model_format: info[:date_model_format] # Model::DEFAULT_DATE_FORMAT
1334
+ },
1308
1335
  decimal_date: lambda{|action, field, info|
1309
1336
  SearchRendererPostProcessors[:date].(action, field, info)
1310
1337
  }
@@ -1330,11 +1357,11 @@ module Engine2
1330
1357
  email: lambda{|action, info| Templates.email(info[:length])},
1331
1358
  password: lambda{|action, info| Templates.password(info[:length])},
1332
1359
  # date_range: lambda{|action, info| Templates.date_range},
1333
- boolean: lambda{|action, info| Templates.checkbox_buttons(optional: !info[:required])},
1360
+ boolean: lambda{|action, info| Templates.checkbox_button},
1334
1361
  currency: lambda{|action, info| Templates.currency},
1335
1362
  list_select: lambda{|action, info|
1336
1363
  length = info[:values].length
1337
- max_length = info[:values].map(&:last).max_by(&:length).length
1364
+ max_length = length > 0 ? info[:values].map(&:last).max_by(&:length).length : 0
1338
1365
  if info[:multiselect]
1339
1366
  Templates.list_bsmselect(max_length)
1340
1367
  elsif length <= 3
@@ -1360,6 +1387,7 @@ module Engine2
1360
1387
 
1361
1388
  (DefaultSearchRenderers ||= {}).merge!(
1362
1389
  date: lambda{|action, info| SearchTemplates.date_range},
1390
+ datetime: lambda{|action, info| SearchTemplates.date_range},
1363
1391
  decimal_date: lambda{|action, info| SearchTemplates.date_range},
1364
1392
  integer: lambda{|action, info| SearchTemplates.integer_range},
1365
1393
  string: lambda{|action, info| SearchTemplates.input_text},
@@ -93,4 +93,97 @@ module Engine2
93
93
  entries
94
94
  end
95
95
  end
96
- end
96
+
97
+ class ArrayViewAction < Action
98
+ include ActionViewSupport
99
+
100
+ def find_record handler, id
101
+ node.parent.*.data_source(handler)[id.to_i]
102
+ end
103
+ end
104
+
105
+ class ArrayFormAction < Action
106
+ end
107
+
108
+ class ArrayCreateAction < ArrayFormAction
109
+ include ActionCreateSupport
110
+ end
111
+
112
+ class ArrayModifyAction < ArrayFormAction
113
+ include ActionModifySupport
114
+
115
+ def find_record handler, id
116
+ node.parent.*.data_source(handler)[id.to_i]
117
+ end
118
+ end
119
+
120
+ class ArrayDeleteAction < Action
121
+ include ActionDeleteSupport
122
+
123
+ def invoke handler
124
+ handler.permit id = handler.params[:id]
125
+ node.parent.parent.*.data_source(handler).delete_at(id.to_i)
126
+ end
127
+ end
128
+
129
+ class ArraySaveAction < Action
130
+ include ActionApproveSupport
131
+ end
132
+
133
+ class ArrayInsertAction < ArraySaveAction
134
+ include ActionInsertSupport
135
+ action_type :approve
136
+
137
+ def after_approve handler, record
138
+ # handler.permit id = record[:id]
139
+ # ds = node.parent.parent.*.data_source(handler)
140
+ end
141
+ end
142
+
143
+ class ArrayUpdateAction < ArraySaveAction
144
+ include ActionUpdateSupport
145
+ action_type :approve
146
+
147
+ def after_approve handler, record
148
+ handler.permit id = record[:id]
149
+ node.parent.parent.*.data_source(handler)[id].merge!(record.values)
150
+ end
151
+ end
152
+
153
+ class Schemes
154
+ ARRAY_CRUD ||= {array_create: true, array_view: true, array_modify: true, array_delete: true}.freeze
155
+ ARRAY_VIEW ||= {array_view: true}
156
+ end
157
+
158
+ SCHEMES.instance_eval do
159
+ define_scheme :array_view do |name = :view|
160
+ define_node name, ArrayViewAction
161
+ end
162
+
163
+ define_scheme :array_modify do |name = :modify|
164
+ define_node name, ArrayModifyAction do
165
+ define_node :approve, ArrayUpdateAction
166
+ end
167
+ end
168
+
169
+ define_scheme :array_create do |name = :create|
170
+ define_node name, ArrayCreateAction do
171
+ define_node :approve, ArrayInsertAction
172
+ end
173
+ end
174
+
175
+ define_scheme :array_delete do
176
+ run_scheme :confirm, :delete, ArrayDeleteAction,
177
+ message: LOCS[:delete_question], title: LOCS[:confirm_delete_title]
178
+ end
179
+
180
+ define_scheme :array do |name, model, options|
181
+ options ||= Schemes::ARRAY_CRUD
182
+ define_node name, ArrayListAction, model: model do
183
+ options.each{|k, v| run_scheme(k) if v}
184
+
185
+ define_node_bundle :form, :create, :modify if options[:array_create] && options[:array_modify]
186
+ end
187
+ end
188
+ end
189
+ end