engine2 1.0.4 → 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 (131) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +0 -0
  3. data/Rakefile +4 -4
  4. data/app/{engine2actions.coffee → actions.coffee} +341 -215
  5. data/app/app.coffee +0 -0
  6. data/app/app.css +17 -0
  7. data/app/engine2.coffee +158 -208
  8. data/app/modal.coffee +138 -0
  9. data/bower.json +4 -2
  10. data/conf/message.yaml +5 -0
  11. data/conf/message_pl.yaml +7 -2
  12. data/config.coffee +24 -12
  13. data/engine2.gemspec +8 -8
  14. data/lib/engine2.rb +12 -10
  15. data/lib/engine2/action.rb +1338 -133
  16. data/lib/engine2/action/array.rb +189 -0
  17. data/lib/engine2/{meta/decode_meta.rb → action/decode.rb} +52 -21
  18. data/lib/engine2/action/delete.rb +64 -0
  19. data/lib/engine2/action/form.rb +16 -0
  20. data/lib/engine2/{meta/infra_meta.rb → action/infra.rb} +123 -89
  21. data/lib/engine2/action/link.rb +117 -0
  22. data/lib/engine2/action/list.rb +333 -0
  23. data/lib/engine2/action/save.rb +28 -0
  24. data/lib/engine2/action/view.rb +8 -0
  25. data/lib/engine2/action_node.rb +221 -0
  26. data/lib/engine2/core.rb +175 -87
  27. data/lib/engine2/handler.rb +14 -13
  28. data/lib/engine2/model.rb +85 -43
  29. data/lib/engine2/models/Files.rb +4 -1
  30. data/lib/engine2/models/UserInfo.rb +6 -3
  31. data/lib/engine2/post_bootstrap.rb +4 -3
  32. data/lib/engine2/pre_bootstrap.rb +10 -6
  33. data/lib/engine2/scheme.rb +107 -65
  34. data/lib/engine2/templates.rb +41 -6
  35. data/lib/engine2/type_info.rb +51 -23
  36. data/lib/engine2/version.rb +2 -1
  37. data/package.json +22 -16
  38. data/public/favicon.ico +0 -0
  39. data/public/img/ajax-loader-dark.gif +0 -0
  40. data/public/img/ajax-loader.gif +0 -0
  41. data/views/fields/blob.slim +1 -1
  42. data/views/fields/bs_select.slim +2 -2
  43. data/views/fields/bsselect_picker.slim +4 -4
  44. data/views/fields/bsselect_picker_opt.slim +5 -5
  45. data/views/fields/checkbox.slim +4 -4
  46. data/views/fields/checkbox_button.slim +6 -0
  47. data/views/fields/checkbox_buttons.slim +3 -3
  48. data/views/fields/checkbox_buttons_opt.slim +3 -3
  49. data/views/fields/currency.slim +2 -2
  50. data/views/fields/date.slim +4 -4
  51. data/views/fields/date_range.slim +9 -9
  52. data/views/fields/date_time.slim +9 -9
  53. data/views/fields/datetime.slim +8 -8
  54. data/views/fields/decimal.slim +1 -1
  55. data/views/fields/decimal_date.slim +3 -3
  56. data/views/fields/decimal_time.slim +3 -3
  57. data/views/fields/email.slim +3 -3
  58. data/views/fields/file_store.slim +11 -11
  59. data/views/fields/input_text.slim +4 -4
  60. data/views/fields/integer.slim +1 -1
  61. data/views/fields/list_bsmselect.slim +20 -0
  62. data/views/fields/list_bsselect.slim +5 -5
  63. data/views/fields/list_bsselect_opt.slim +6 -6
  64. data/views/fields/list_buttons.slim +1 -1
  65. data/views/fields/list_buttons_opt.slim +2 -2
  66. data/views/fields/list_mbuttons.slim +9 -0
  67. data/views/fields/list_mbuttons_opt.slim +11 -0
  68. data/views/fields/list_mselect.slim +12 -0
  69. data/views/fields/list_select.slim +4 -4
  70. data/views/fields/list_select_opt.slim +5 -5
  71. data/views/fields/password.slim +4 -4
  72. data/views/fields/radio_checkbox.slim +3 -3
  73. data/views/fields/scaffold.slim +2 -2
  74. data/views/fields/scaffold_picker.slim +5 -5
  75. data/views/fields/select_picker.slim +3 -3
  76. data/views/fields/select_picker_opt.slim +4 -4
  77. data/views/fields/text_area.slim +4 -3
  78. data/views/fields/time.slim +5 -4
  79. data/views/fields/typeahead_picker.slim +12 -9
  80. data/views/index.slim +3 -3
  81. data/views/infra/index.slim +0 -0
  82. data/views/infra/inspect.slim +41 -10
  83. data/views/modals/close_m.slim +0 -0
  84. data/views/modals/confirm_m.slim +0 -0
  85. data/views/modals/empty_m.slim +0 -0
  86. data/views/modals/menu_m.slim +1 -1
  87. data/views/modals/yes_no_m.slim +0 -0
  88. data/views/panels/menu_m.slim +1 -1
  89. data/views/scaffold/confirm.slim +0 -0
  90. data/views/scaffold/fields.slim +6 -4
  91. data/views/scaffold/form.slim +1 -1
  92. data/views/scaffold/form_collapse.slim +4 -3
  93. data/views/scaffold/form_tabs.slim +3 -2
  94. data/views/scaffold/list.slim +0 -0
  95. data/views/scaffold/message.slim +0 -0
  96. data/views/scaffold/search.slim +4 -4
  97. data/views/scaffold/search_collapse.slim +8 -7
  98. data/views/scaffold/search_tabs.slim +6 -5
  99. data/views/scaffold/view.slim +2 -2
  100. data/views/scaffold/view_collapse.slim +5 -4
  101. data/views/scaffold/view_tabs.slim +4 -3
  102. data/views/search_fields/bsmselect_picker.slim +4 -4
  103. data/views/search_fields/bsselect_picker.slim +4 -4
  104. data/views/search_fields/checkbox.slim +3 -3
  105. data/views/search_fields/checkbox2.slim +5 -5
  106. data/views/search_fields/checkbox_buttons.slim +3 -3
  107. data/views/search_fields/date.slim +20 -0
  108. data/views/search_fields/date_range.slim +8 -8
  109. data/views/search_fields/decimal_date_range.slim +5 -5
  110. data/views/search_fields/input_text.slim +2 -2
  111. data/views/search_fields/integer.slim +1 -1
  112. data/views/search_fields/integer_range.slim +2 -2
  113. data/views/search_fields/list_bsmselect.slim +4 -4
  114. data/views/search_fields/list_bsselect.slim +4 -4
  115. data/views/search_fields/list_buttons.slim +2 -2
  116. data/views/search_fields/list_mbuttons.slim +12 -0
  117. data/views/search_fields/list_select.slim +3 -3
  118. data/views/search_fields/scaffold_picker.slim +2 -2
  119. data/views/search_fields/select_picker.slim +3 -3
  120. data/views/search_fields/typeahead_picker.slim +8 -7
  121. metadata +53 -48
  122. data/lib/engine2/meta.rb +0 -1216
  123. data/lib/engine2/meta/array_meta.rb +0 -82
  124. data/lib/engine2/meta/delete_meta.rb +0 -60
  125. data/lib/engine2/meta/form_meta.rb +0 -15
  126. data/lib/engine2/meta/link_meta.rb +0 -134
  127. data/lib/engine2/meta/list_meta.rb +0 -281
  128. data/lib/engine2/meta/save_meta.rb +0 -50
  129. data/lib/engine2/meta/view_meta.rb +0 -7
  130. data/public/__sinatra__/404.png +0 -0
  131. data/public/__sinatra__/500.png +0 -0
@@ -0,0 +1,189 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Engine2
5
+ class ArrayListAction < Action
6
+ action_type :list
7
+ include ActionListSupport
8
+
9
+ (DefaultFilters ||= {}).merge!(
10
+ exact: lambda{|entries, name, value, type_info, hash|
11
+ entries.select{|e|e[name] == value}
12
+ },
13
+ string: lambda{|entries, name, value, type_info, hash|
14
+ if type_info[:type] == :list_select
15
+ if type_info[:multiselect]
16
+ entries.select{|e|value.include?(e[name].to_s)}
17
+ else
18
+ entries.select{|e|e[name].to_s == value}
19
+ end
20
+ else
21
+ entries.select{|e|e[name].to_s[value]}
22
+ end
23
+
24
+ },
25
+ boolean: lambda{|*args| DefaultFilters[:exact].(*args)},
26
+ integer: lambda{|entries, name, value, type_info, hash|
27
+ if value.is_a? Hash
28
+ from, to = value[:from], value[:to]
29
+ if from && to
30
+ entries.select{|e|e[name] >= from.to_i && e[name] <= to.to_i}
31
+ else
32
+ entries.select{|e| from ? e[name] >= from.to_i : e[name] <= to.to_i}
33
+ end
34
+ elsif value.is_a? Integer
35
+ entries.select{|e|e[name] == value.to_i}
36
+ else
37
+ nil
38
+ end
39
+ }
40
+ )
41
+
42
+ def data_source handler
43
+ []
44
+ end
45
+
46
+ def page_frame handler, entries
47
+ entries
48
+ end
49
+
50
+ def invoke handler
51
+ params = handler.params
52
+ # if params[:initial] || params[:refresh]
53
+ entries = data_source(handler)
54
+
55
+ per_page = lookup(:config, :per_page)
56
+ page = params[:page].to_i
57
+ handler.permit page >= 0 && page < 1000
58
+
59
+ if order_str = params[:order]
60
+ order = order_str.to_sym
61
+ handler.permit lookup(:fields, order, :sort)
62
+ entries = entries.sort_by{|e|e[order].to_s}
63
+ entries = entries.reverse if params[:asc] == "true"
64
+ end
65
+
66
+ if search = params[:search]
67
+ entries = list_search(entries, handler, search)
68
+ end
69
+
70
+ {entries: page_frame(handler, entries[page, per_page]), count: entries.size}
71
+ end
72
+
73
+ def list_search entries, handler, search
74
+ hash = JSON.parse(search, symbolize_names: true) rescue handler.halt_forbidden
75
+ model = assets[:model]
76
+ sfields = lookup(:search_field_list)
77
+ handler.permit sfields
78
+ hash.each_pair do |name, value|
79
+ handler.permit sfields.include?(name)
80
+
81
+ type_info = model.find_type_info(name)
82
+ entries = if filter = (@filters && @filters[name]) || (dynamic? && (static.filters && static.filters[name]))
83
+ filter.(handler, entries, hash)
84
+ elsif filter = DefaultFilters[type_info[:otype]]
85
+ filter.(entries, name, value, type_info, hash)
86
+ else
87
+ raise E2Error.new("Filter not found for field '#{name}' in model '#{model}'") unless filter
88
+ end
89
+
90
+ handler.permit entries
91
+ end
92
+
93
+ entries
94
+ end
95
+ 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
@@ -1,8 +1,9 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Engine2
4
- class DecodeMeta < Meta
5
- include MetaAPISupport, MetaModelSupport, MetaQuerySupport
5
+ class DecodeAction < Action
6
+ include ActionAPISupport, ActionModelSupport, ActionQuerySupport
6
7
 
7
8
  def decode *fields, &blk
8
9
  query select(*fields), &blk
@@ -18,8 +19,8 @@ module Engine2
18
19
  end
19
20
 
20
21
  def post_process
21
- if fields = @meta[:fields]
22
- fields = fields - static.get[:fields] if dynamic?
22
+ if fields = @meta[:field_list]
23
+ fields = fields - static.meta[:field_list] if dynamic?
23
24
  # no decorate here
24
25
  fields.each do |name|
25
26
  type_info = assets[:model].type_info[name] # foreign keys ?
@@ -42,7 +43,7 @@ module Engine2
42
43
  end
43
44
 
44
45
  def post_run
45
- query select(*assets[:model].primary_keys) unless @query
46
+ decode(*assets[:model].primary_keys) unless @query
46
47
  @meta[:separator] = '/' unless @meta[:separator]
47
48
  super
48
49
  @meta[:primary_fields] = assets[:model].primary_keys
@@ -50,48 +51,78 @@ module Engine2
50
51
 
51
52
  end
52
53
 
53
- class DecodeListMeta < DecodeMeta
54
- meta_type :decode_list
54
+ class DecodeListAction < DecodeAction
55
+ action_type :decode_list
55
56
 
56
57
  def invoke handler
57
- {entries: get_query.limit(200).all}
58
+ {entries: get_query.limit(200).load_all}
59
+ end
60
+
61
+ def order *fields
62
+ @query = get_query.order *fields
58
63
  end
59
64
  end
60
65
 
61
- class TypeAheadMeta < DecodeMeta
62
- meta_type :typeahead
66
+ class TypeAheadAction < DecodeAction
67
+ action_type :typeahead
63
68
 
64
69
  def pre_run
65
70
  super
66
- limit 10
71
+ @limit = 10
67
72
  end
68
73
 
69
74
  def limit lmt
70
- @meta[:limit] = lmt
75
+ @limit = lmt
76
+ end
77
+
78
+ def get_limit
79
+ @limit
80
+ end
81
+
82
+ def get_case_insensitive
83
+ @case_insensitive
84
+ end
85
+
86
+ def case_insensitive
87
+ @case_insensitive = true
88
+ end
89
+
90
+ def order *fields
91
+ @query = get_query.order *fields
71
92
  end
72
93
 
73
94
  def invoke handler
95
+ model = assets[:model]
74
96
  if query = handler.params[:query]
75
- condition = (@meta[:decode_fields] || @meta[:fields]).map{|f|f.like("%#{query}%")}.inject{|q, f| q | f}
76
- {entries: get_query.where(condition).limit(@meta[:limit]).all}
97
+ fields = @meta[:decode_fields] || static.meta[:decode_fields]
98
+
99
+ entries = if query.to_s.empty?
100
+ get_query
101
+ else
102
+ table_name = model.table_name
103
+ condition = fields.map{|f|table_name.q(f).like("%#{query}%", case_insensitive: @case_insensitive || static.get_case_insensitive)}.reduce{|q, f| q | f}
104
+ get_query.where(condition)
105
+ end.limit(@limit || static.get_limit).load_all
106
+
107
+ {entries: entries}
77
108
  else
78
109
  handler.permit id = handler.params[:id]
79
- record = get_query[Hash[assets[:model].primary_keys.zip(split_keys(id))]]
110
+ record = get_query.unordered.load Hash[model.primary_keys_qualified.zip(split_keys(id))]
80
111
  # handler.halt_not_found(LOCS[:no_entry]) unless record
81
112
  {entry: record}
82
113
  end
83
114
  end
84
115
  end
85
116
 
86
- class DecodeEntryMeta < DecodeMeta
87
- meta_type :decode_entry
117
+ class DecodeEntryAction < DecodeAction
118
+ action_type :decode_entry
88
119
 
89
120
  def invoke handler
90
121
  {entries: invoke_decode(handler, handler.param_to_json(:ids))}
91
122
  end
92
123
 
93
124
  def invoke_decode handler, ids
94
- records = get_query.where(ids.map{|keys| Hash[assets[:model].primary_keys.zip(keys)]}.inject{|q, c| q | c}).all
125
+ records = get_query.where(ids.map{|keys| Hash[assets[:model].primary_keys.zip(keys)]}.reduce{|q, c| q | c}).load_all
95
126
  # handler.halt_not_found(LOCS[:no_entry]) if records.empty?
96
127
  records
97
128
  end
@@ -101,9 +132,9 @@ module Engine2
101
132
  if assoc = assets[:assoc]
102
133
  decode = assoc[:model].type_info[assoc[:keys].first][:decode]
103
134
 
104
- if decode[:search][:multiple] && action.parent.parent.*.is_a?(ListMeta)
105
- action.list.*.menu(:panel_menu).option :choose, icon: :ok #, disabled: "action.selected_size() == 0"
106
- action.list.*.menu(:panel_menu).option :cancel, icon: "remove"
135
+ if decode[:search][:multiple] && node.parent.parent.*.is_a?(ListAction)
136
+ node.list.*.menu(:panel_menu).option :choose, icon: :ok #, disabled: "action.selected_size() == 0"
137
+ node.list.*.menu(:panel_menu).option :cancel, icon: "remove"
107
138
  end
108
139
  end
109
140
  end
@@ -0,0 +1,64 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Engine2
5
+ class DeleteActionBase < Action
6
+ def invoke_delete_db handler, ids, from_assoc = nil
7
+ model = assets[:model]
8
+ model.db.transaction do
9
+ ids.each do |id|
10
+ keys = split_keys(id)
11
+
12
+ model.association_reflections.each do |name, assoc|
13
+ ds = case assoc[:type]
14
+ when :one_to_one
15
+ when :one_to_many
16
+ model.db[assoc.associated_class.table_name].where(Hash[assoc[:keys].zip(keys)])
17
+ when :many_to_many
18
+ model.db[assoc[:join_table]].where(Hash[assoc[:left_keys].zip(keys)])
19
+ when :many_to_one
20
+ nil
21
+ else
22
+ unsupported_association assoc[:type]
23
+ end
24
+
25
+ if assoc[:delete] == :cascade || from_assoc == assoc.associated_class.table_name
26
+ ds.delete
27
+ else
28
+ raise Sequel::DestroyFailed.new("#{LOCS[:delete_restricted]}: #{name}") unless ds.empty?
29
+ end if ds
30
+ end
31
+
32
+ rec = model.call(Hash[model.primary_keys.zip(keys)])
33
+ rec.destroy(transaction: false)
34
+ # model.where(model.primary_keys_hash(keys)).delete # model.dataset[model.primary_key => id].delete
35
+ end
36
+ end
37
+
38
+ rescue Sequel::NoExistingObject
39
+ handler.halt_not_found LOCS[:no_entry]
40
+ rescue Sequel::DestroyFailed => failure
41
+ handler.halt_forbidden failure.error.to_s
42
+ {}
43
+ end
44
+ end
45
+
46
+ class DeleteAction < DeleteActionBase
47
+ include ActionDeleteSupport
48
+
49
+ def invoke handler
50
+ handler.permit id = handler.params[:id]
51
+ invoke_delete_db(handler, [id])
52
+ end
53
+ end
54
+
55
+ class BulkDeleteAction < DeleteActionBase
56
+ include ActionBulkDeleteSupport
57
+
58
+ def invoke handler
59
+ ids = handler.param_to_json(:ids)
60
+ handler.permit ids.is_a?(Array)
61
+ invoke_delete_db(handler, ids)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,16 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Engine2
5
+ class FormAction < Action
6
+ include ActionQuerySupport
7
+ end
8
+
9
+ class CreateAction < FormAction
10
+ include ActionCreateSupport
11
+ end
12
+
13
+ class ModifyAction < FormAction
14
+ include ActionModifySupport
15
+ end
16
+ end
@@ -1,61 +1,43 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Engine2
4
- SCHEMES::define_scheme :infra! do |user_info_model = UserInfo|
5
- define_action :infra! do
6
- self.* do
7
- extend MetaPanelSupport, MetaMenuSupport, MetaAPISupport
8
- panel_panel_template false
9
- panel_template 'infra/index'
10
- loc! logged_on: LOCS[:logged_on]
11
- menu :menu do
12
- properties group_class: "btn-group-sm"
13
- option :inspect_modal, icon: :wrench, button_loc: false # , show: "action.logged_on"
14
-
15
- option :logout_form, icon: :"log-out" # , show: "action.logged_on"
16
- option :login_form, icon: :"log-in", disabled: 'action.action_pending()' # , show: "!action.logged_on"
17
- end
18
-
19
- @meta_type = :infra
20
-
21
- define_invoke do |handler|
22
- user = handler.user
23
- {user: user ? user.to_hash : nil}
24
- end
25
- end
5
+ SCHEMES::define_scheme :login! do |user_info_model = UserInfo|
6
+ define_node :login_form, LoginFormAction, model: user_info_model do
7
+ access!{|h|!h.logged_in?}
8
+ define_node :login, LoginAction
9
+ end
10
+ end
26
11
 
27
- define_action :login_form, LoginFormMeta, model: user_info_model do
28
- access!{|h|!h.logged_in?}
29
- define_action :login, LoginMeta
30
- end
12
+ SCHEMES::define_scheme :logout! do
13
+ define_node :logout_form, LogoutFormAction do
14
+ access! &:logged_in?
15
+ define_node :logout, LogoutAction
16
+ end
17
+ end
31
18
 
32
- define_action :logout_form, LogoutFormMeta do
33
- access! &:logged_in?
34
- define_action :logout, LogoutMeta
35
- end
19
+ SCHEMES::define_scheme :infra! do |user_info_model = UserInfo|
20
+ run_scheme :login!, user_info_model
21
+ define_node :infra!, InfraAction do
22
+ run_scheme :login!, user_info_model
23
+ run_scheme :logout!
36
24
 
37
- define_action :inspect_modal do
25
+ define_node :inspect_modal, InspectModalAction do
38
26
  access! &:logged_in?
39
- # access!{|h|h.user[:name] == 'admin'}
40
- self.* do
41
- extend MetaPanelSupport, MetaMenuSupport
42
- modal_action
43
- panel_template 'infra/inspect'
44
- panel_title "#{:wrench.icon} Inspect"
45
- panel_class "modal-huge"
46
- panel[:backdrop] = true
47
- menu(:panel_menu).option :cancel, icon: "remove"
48
- end
49
- define_action :inspect do
27
+ define_node :"inspect_#{SETTINGS[:name]}", WebSocketAction.inherit do
50
28
  self.* do
51
- @meta_type = :inspect
29
+ @action_type = :inspect
30
+
31
+ ws_message do |msg, ws|
32
+ ws.send! number: msg[:number].to_i + 1
33
+ end
52
34
  end
53
35
 
54
- define_action_invoke :models do |handler|
36
+ define_invoke :models do |handler|
55
37
  {models: Sequel::DATABASES.map{|db| {name: db.uri, models: db.models.keys} }}
56
38
  end
57
39
 
58
- define_action_invoke :model_info do |handler|
40
+ define_invoke :model_info do |handler|
59
41
  db_name = handler.params[:db]
60
42
  handler.permit db = Sequel::DATABASES.find{|d|d.uri == db_name || (d.uri && d.uri.start_with?(db_name))}
61
43
  handler.permit model = db.models[handler.params[:model].to_sym]
@@ -71,18 +53,22 @@ module Engine2
71
53
  }
72
54
  }
73
55
  end
56
+
57
+ define_invoke :environment do |handler|
58
+ {environment: handler.env}
59
+ end
74
60
  end
75
61
  end
76
62
  end
77
63
  end
78
64
 
79
65
  SCHEMES::define_scheme :menu! do
80
- define_action :menu!, MenuMeta do
66
+ define_node :menu!, MenuAction do
81
67
  end
82
68
  end
83
69
 
84
- class FileStoreMeta < Meta
85
- meta_type :file_store
70
+ class FileStoreAction < Action
71
+ action_type :file_store
86
72
 
87
73
  attr_accessor :model, :field
88
74
 
@@ -93,7 +79,7 @@ module Engine2
93
79
  end
94
80
 
95
81
 
96
- module BlobSupportMeta
82
+ module BlobSupportAction
97
83
  def serve_blob handler, entry, inf
98
84
  handler.permit entry
99
85
  handler.attachment entry[inf[:name_field]]
@@ -102,8 +88,8 @@ module Engine2
102
88
  end
103
89
  end
104
90
 
105
- class DownloadFileStoreMeta < Meta
106
- meta_type :download
91
+ class DownloadFileStoreAction < Action
92
+ action_type :download
107
93
 
108
94
  def invoke handler
109
95
  handler.permit id = handler.params[:id]
@@ -111,28 +97,29 @@ module Engine2
111
97
  handler.permit entry
112
98
  handler.attachment entry[:name]
113
99
  handler.content_type (entry[:mime].to_s.empty? ? "application/octet-stream" : entry[:mime])
114
- info = action.parent.*.model.type_info[action.parent.*.field]
100
+ info = node.parent.*.model.type_info[node.parent.*.field]
115
101
  open("#{info[:store][:files]}/#{entry[:name]}_#{id}", 'rb'){|f|f.read}
116
102
  end
117
103
  end
118
104
 
119
- class UploadFileStoreMeta < Meta
105
+ class UploadFileStoreAction < Action
120
106
  http_method :post
121
- meta_type :upload
107
+ action_type :upload
122
108
 
123
109
  def invoke handler
124
110
  file = handler.params[:file]
125
111
  temp = file[:tempfile]
126
112
  temp.close
127
113
  rackname = File.basename(temp.path)
128
- info = action.parent.*.model.type_info[action.parent.*.field]
129
- File.rename(temp.path, "#{info[:store][:upload]}/#{rackname}")
114
+ info = node.parent.*.model.type_info[node.parent.*.field]
115
+ FileUtils.cp(temp.path, "#{info[:store][:upload]}/#{rackname}") # File.rename(temp.path, "#{info[:store][:upload]}/#{rackname}")
116
+ FileUtils.rm(temp.path)
130
117
  {rackname: rackname}
131
118
  end
132
119
  end
133
120
 
134
- class BlobStoreMeta < Meta
135
- meta_type :blob_store
121
+ class BlobStoreAction < Action
122
+ action_type :blob_store
136
123
 
137
124
  attr_accessor :model, :field
138
125
 
@@ -145,13 +132,13 @@ module Engine2
145
132
  end
146
133
  end
147
134
 
148
- class DownloadBlobStoreMeta < Meta
149
- include BlobSupportMeta
150
- meta_type :download_blob
135
+ class DownloadBlobStoreAction < Action
136
+ include BlobSupportAction
137
+ action_type :download_blob
151
138
 
152
139
  def invoke handler
153
- model = action.parent.*.model
154
- inf = model.type_info[action.parent.*.field]
140
+ model = node.parent.*.model
141
+ inf = model.type_info[node.parent.*.field]
155
142
  handler.permit id = handler.params[:id]
156
143
 
157
144
  entry = model.naked.select(inf[:bytes_field], inf[:name_field], inf[:mime_field]).where(model.primary_keys_hash(split_keys(id))).first
@@ -159,23 +146,23 @@ module Engine2
159
146
  end
160
147
  end
161
148
 
162
- class UploadBlobStoreMeta < Meta
149
+ class UploadBlobStoreAction < Action
163
150
  http_method :post
164
- meta_type :upload_blob
151
+ action_type :upload_blob
165
152
 
166
153
  def invoke handler
167
154
  file = handler.params[:file]
168
155
  temp = file[:tempfile]
169
156
  temp.close
170
157
  rackname = File.basename(temp.path)
171
- info = action.parent.*.model.type_info[action.parent.*.field]
158
+ info = node.parent.*.model.type_info[node.parent.*.field]
172
159
  File.rename(temp.path, "#{info[:store][:upload]}/#{rackname}")
173
160
  {rackname: rackname}
174
161
  end
175
162
  end
176
163
 
177
- class ForeignBlobStoreMeta < Meta
178
- meta_type :blob_store
164
+ class ForeignBlobStoreAction < Action
165
+ action_type :blob_store
179
166
 
180
167
  attr_accessor :model, :field
181
168
 
@@ -195,13 +182,13 @@ module Engine2
195
182
  end
196
183
  end
197
184
 
198
- class DownloadForeignBlobStoreMeta < Meta
199
- include BlobSupportMeta
200
- meta_type :download_blob
185
+ class DownloadForeignBlobStoreAction < Action
186
+ include BlobSupportAction
187
+ action_type :download_blob
201
188
 
202
189
  def invoke handler
203
- model = action.parent.*.model
204
- inf = model.type_info[action.parent.*.field]
190
+ model = node.parent.*.model
191
+ inf = model.type_info[node.parent.*.field]
205
192
  assoc = model.association_reflections[inf[:assoc_name]]
206
193
  blob_model = assoc.associated_class
207
194
  handler.permit id = handler.params[:id]
@@ -213,9 +200,9 @@ module Engine2
213
200
  end
214
201
  end
215
202
 
216
- # class UploadForeignBlobStoreMeta < Meta
203
+ # class UploadForeignBlobStoreAction < Action
217
204
  # http_method :post
218
- # meta_type :upload_blob
205
+ # action_type :upload_blob
219
206
 
220
207
  # def invoke handler
221
208
  # file = handler.params[:file]
@@ -227,17 +214,63 @@ module Engine2
227
214
  # end
228
215
  # end
229
216
 
230
- class LoginFormMeta < Meta
231
- include MetaFormSupport
232
- meta_type :login_form
217
+ class InfraAction < Action
218
+ include ActionPanelSupport, ActionMenuSupport, ActionAPISupport
219
+ action_type :infra
220
+
221
+ def pre_run
222
+ super
223
+ panel_panel_template false
224
+ panel_template 'infra/index'
225
+ loc! logged_on: LOCS[:logged_on]
226
+ menu :menu do
227
+ properties group_class: "btn-group-sm"
228
+ option :inspect_modal, icon: :wrench, button_loc: false # , show: "action.logged_on"
229
+ end
230
+ end
231
+
232
+ def invoke handler
233
+ user = handler.user
234
+ {user: user ? user.to_hash : nil}
235
+ end
236
+
237
+ def login_meta menu_properties = {show: 'false'}, &blk
238
+ node.login_form.* &blk
239
+ menu(:menu).modify_option :login_form, menu_properties
240
+ node.parent.login_form.* &blk
241
+ end
242
+ end
243
+
244
+ class InspectModalAction < Action
245
+ include ActionPanelSupport, ActionMenuSupport
246
+ action_type :inline
247
+
248
+ def pre_run
249
+ super
250
+ modal_action
251
+ panel_template 'infra/inspect'
252
+ panel_title "#{:wrench.icon} Inspect"
253
+ panel_class "modal-huge"
254
+ panel[:backdrop] = true
255
+ menu(:panel_menu).option :close, icon: "remove"
256
+ end
257
+ end
258
+
259
+ class LoginFormAction < Action
260
+ include ActionFormSupport
261
+ action_type :login_form
233
262
 
234
263
  def pre_run
235
264
  super
236
265
  panel_class 'modal-default'
237
266
  panel_title LOCS[:login_title]
238
- info! :name, loc: LOCS[:user_name]
267
+ fields! :name, loc: LOCS[:user_name]
239
268
  menu(:panel_menu).modify_option :approve, name: :login, icon: :"log-in"
240
- @meta[:fields] = [:name, :password]
269
+ @meta[:field_list] = [:name, :password]
270
+ parent_action = node.parent.*
271
+ if parent_action.is_a? ActionMenuSupport
272
+ parent_action.menu(:menu).option :login_form, icon: :"log-in", disabled: "action.action_pending()"
273
+ end
241
274
  end
242
275
 
243
276
  def invoke handler
@@ -245,11 +278,11 @@ module Engine2
245
278
  end
246
279
  end
247
280
 
248
- class LoginMeta < Meta
249
- include MetaApproveSupport
250
- meta_type :login
281
+ class LoginAction < Action
282
+ include ActionApproveSupport
283
+ action_type :login
251
284
 
252
- def validate_record handler, record
285
+ def validate_record handler, record, parent_id
253
286
  super
254
287
  record.values[:password] = nil
255
288
  end
@@ -263,15 +296,16 @@ module Engine2
263
296
  end
264
297
  end
265
298
 
266
- class LogoutFormMeta < Meta
267
- include MetaPanelSupport, MetaMenuSupport
268
- meta_type :logout_form
299
+ class LogoutFormAction < Action
300
+ include ActionPanelSupport, ActionMenuSupport
301
+ action_type :logout_form
269
302
  def pre_run
270
303
  super
271
304
  panel_template 'scaffold/message'
272
305
  panel_title LOCS[:logout_title]
273
306
  panel_class 'modal-default'
274
307
  @meta[:message] = LOCS[:logout_message]
308
+ node.parent.*.menu(:menu).option :logout_form, icon: :"log-out" # , show: "action.logged_on"
275
309
  menu :panel_menu do
276
310
  option :logout, icon: "ok", loc: LOCS[:ok]
277
311
  option :cancel, icon: "remove"
@@ -279,8 +313,8 @@ module Engine2
279
313
  end
280
314
  end
281
315
 
282
- class LogoutMeta < Meta
283
- meta_type :logout
316
+ class LogoutAction < Action
317
+ action_type :logout
284
318
 
285
319
  def invoke handler
286
320
  handler.session.clear