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
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Engine2
4
5
  class Handler < Sinatra::Base
@@ -66,20 +67,20 @@ module Engine2
66
67
  def serve_api_resource verb, path
67
68
  path = path.split('/') # -1 ?
68
69
  is_meta = path.pop if path.last == 'meta'
69
- action = ROOT
70
+ node = ROOT
70
71
  path.each do |pat|
71
- action = action[pat.to_sym]
72
- halt_not_found unless action
73
- halt_unauthorized unless action.check_access!(self)
72
+ node = node[pat.to_sym]
73
+ halt_not_found unless node
74
+ halt_unauthorized unless node.check_access!(self)
74
75
  end
75
76
 
76
- meta = action.*
77
+ action = node.*
77
78
  response = if is_meta
78
- params[:access] ? action.access_info(self) : {meta: meta.get, actions: action.actions_info(self)}
79
+ params[:access] ? node.access_info(self) : {meta: action.meta, actions: node.nodes_info(self)}
79
80
  else
80
- if meta.http_method == verb && meta.invokable
81
+ if action.http_method == verb && action.invokable
81
82
  begin
82
- meta.invoke!(self)
83
+ action.invoke!(self)
83
84
  rescue => error
84
85
  attachment nil, nil
85
86
  # content_type :json
@@ -118,16 +119,16 @@ module Engine2
118
119
  slim name.to_sym
119
120
  end
120
121
 
121
- set :slim, pretty: true, sort_attrs: false
122
- set :views, ["views", "#{PATH}/views"]
123
- set :public_folder, "#{PATH}/public"
124
- set :sessions, expire_after: 3600 # , :httponly => true, :secure => production?
122
+ set :slim, pretty: !production?, sort_attrs: false
123
+ unless production? # use Engine2::SETTINGS[:reloading] ?
124
+ set :sessions, expire_after: 3600
125
+ # set :session_store, Rack::Session::Pool
126
+ end
125
127
 
126
128
  helpers do
127
129
  def find_template(views, name, engine, &block)
128
130
  views.each{|v| super(v, name, engine, &block)}
129
131
  end
130
132
  end
131
-
132
133
  end
133
134
  end
@@ -1,10 +1,11 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Engine2
4
5
  module Model
5
6
  attr_reader :dummies
6
7
  attr_reader :many_to_one_associations, :one_to_many_associations, :many_to_many_associations #, :one_to_one_associations
7
- attr_reader :before_save_processors, :after_save_processors, :before_destroy_processors, :after_destroy_processors
8
+ attr_reader :after_load_processors, :before_save_processors, :after_save_processors, :before_destroy_processors, :after_destroy_processors
8
9
  attr_reader :validation_in_transaction
9
10
 
10
11
  def self.extended cls
@@ -18,12 +19,15 @@ module Engine2
18
19
  @many_to_many_associations = association_reflections.select{|n, a| a[:type] == :many_to_many}
19
20
  # @one_to_one_associations = association_reflections.select{|n, a| a[:type] == :one_to_one}
20
21
  @validation_in_transaction = nil
22
+ @after_load_processors = nil
21
23
  @before_save_processors = nil
22
24
  @after_save_processors = nil
23
25
  @around_save_processors = nil
24
26
  @before_destroy_processors = nil
25
27
  @after_destroy_processors = nil
26
28
  @type_info_synchronized = nil
29
+ @model_icon = :"list"
30
+ @model_route = cls.name.to_sym
27
31
  end
28
32
  cls.setup_schema
29
33
  end
@@ -52,12 +56,12 @@ module Engine2
52
56
  when :integer
53
57
  integer_field name
54
58
  when :string
55
- if db_info[:db_type] == 'text'
56
- string_field name, 10
59
+ string_field name, case db_info[:db_type]
60
+ when 'text', 'character varying'
61
+ 100
57
62
  else
58
- string_field name, Integer(db_info[:column_size] || db_info[:db_type][/\((\d+)\)/, 1])
63
+ Integer(db_info[:column_size] || db_info[:db_type][/\((\d+)\)/, 1])
59
64
  end
60
-
61
65
  when :time
62
66
  time_field name, LOCS[:default_time_format], LOCS[:default_time_model_format]
63
67
  when :date
@@ -74,6 +78,8 @@ module Engine2
74
78
  decimal_field name, size, scale
75
79
  when :blob
76
80
  blob_field name, 100000
81
+ when :boolean
82
+ boolean_field name
77
83
  when nil
78
84
  # ignore nil type
79
85
  else
@@ -106,9 +112,27 @@ module Engine2
106
112
  end
107
113
  end
108
114
 
115
+ def find_type_info name
116
+ model = self
117
+ info = case name
118
+ when Symbol
119
+ model.type_info[name]
120
+ when Sequel::SQL::QualifiedIdentifier
121
+ assoc = model.many_to_one_associations[name.table] || model.many_to_many_associations[name.table]
122
+ raise E2Error.new("Association #{name.table} not found for model #{model}") unless assoc
123
+ assoc.associated_class.type_info[name.column]
124
+ else
125
+ raise E2Error.new("Unknown type info key: #{name} in model #{model}")
126
+ end
127
+
128
+ raise E2Error.new("Type info not found for '#{name}' in model '#{model}'") unless info
129
+ info
130
+ end
131
+
109
132
  def synchronize_type_info
110
133
  resolve_dependencies
111
134
  verify_associations
135
+ @after_load_processors = install_processors(AfterLoadProcessors)
112
136
  @before_save_processors = install_processors(BeforeSaveProcessors)
113
137
  @after_save_processors = install_processors(AfterSaveProcessors)
114
138
  @around_save_processors = {}
@@ -117,18 +141,6 @@ module Engine2
117
141
  @type_info_synchronized = true
118
142
  end
119
143
 
120
- def verify_associations
121
- one_to_many_associations.each do |name, assoc|
122
- other = assoc.associated_class
123
- other_type_info = other.type_info
124
- if other_keys = assoc[:keys]
125
- other_keys.each do |key|
126
- raise E2Error.new("No key '#{key}' found in model '#{other}' being related from #{self}") unless other_type_info[key]
127
- end
128
- end
129
- end
130
- end
131
-
132
144
  def resolve_dependencies
133
145
  resolved = {}
134
146
  @type_info.each_pair do |name, info|
@@ -150,14 +162,33 @@ module Engine2
150
162
  resolved[name] = @type_info[name]
151
163
  end
152
164
 
165
+ def verify_associations
166
+ one_to_many_associations.each do |name, assoc|
167
+ other = assoc.associated_class
168
+ other_type_info = other.type_info
169
+ if other_keys = assoc[:keys]
170
+ other_keys.each do |key|
171
+ raise E2Error.new("No key '#{key}' found in model '#{other}' being related from #{self}") unless other_type_info[key]
172
+ end
173
+ end
174
+ end
175
+ end
176
+
153
177
  attr_reader :scheme_name, :scheme_args
154
178
 
155
179
  def scheme s_name = :default, opts = nil, &blk
156
180
  @scheme_name = s_name
157
- @scheme_args = [name.to_sym, self, opts]
158
- SCHEMES::define_scheme name.to_sym, &blk
181
+ @scheme_args = [model_route, self, opts]
182
+ SCHEMES::define_scheme model_route, &blk
183
+ end
184
+
185
+ def model_icon icn = nil
186
+ icn ? @model_icon = icn : @model_icon
159
187
  end
160
188
 
189
+ def model_route rt = nil
190
+ rt ? @model_route = rt : @model_route
191
+ end
161
192
  end
162
193
 
163
194
  # def define_dummy_model
@@ -269,7 +300,14 @@ module Engine2
269
300
  },
270
301
  list_select: lambda{|record, field, info|
271
302
  value = record.values[field]
272
- LOCS[:invalid_list_value] unless info[:list].any?{|a|a.first == value}
303
+ values = info[:values].map(&:first)
304
+
305
+ result = if info[:multiselect]
306
+ value.is_a?(Array) && (values - value).length == values.length - value.length
307
+ else
308
+ values.include?(value)
309
+ end
310
+ LOCS[:invalid_list_value] unless result
273
311
  },
274
312
  decimal: lambda{|record, field, info|
275
313
  value = record.values[field]
@@ -284,7 +322,7 @@ module Engine2
284
322
  with_errors = with.map{|w|record.errors[w]}
285
323
  if with_errors.compact.empty?
286
324
  all_fields = [field] + with
287
- query = record.model.dataset.where(*all_fields.map{|f|{f => record[f]}})
325
+ query = all_fields.reduce(record.model.dataset){|ds, f|ds.where f => record[f]}
288
326
  query = query.exclude(record.model.primary_keys_hash(record.primary_key_values)) unless record.new?
289
327
  unless query.empty?
290
328
  msg = LOCS[:required_unique_value]
@@ -297,6 +335,20 @@ module Engine2
297
335
  }
298
336
  )
299
337
 
338
+ (AfterLoadProcessors ||= {}).merge!(
339
+ list_select: lambda{|record, field, info|
340
+ value = record[field]
341
+ record[field] = case info[:otype]
342
+ when :string
343
+ value.split(info[:separator])
344
+ when :integer
345
+ arr = []
346
+ value.bit_length.times{|i| arr << (1 << i) unless value[i].zero?}
347
+ arr
348
+ end if value && info[:multiselect]
349
+ }
350
+ )
351
+
300
352
  (BeforeSaveProcessors ||= {}).merge!(
301
353
  blob_store: lambda{|record, field, info|
302
354
  if value = record.values[field] # attachment info
@@ -323,33 +375,23 @@ module Engine2
323
375
  end
324
376
  File.delete("#{upload}/#{value[:rackname]}")
325
377
  end
378
+ },
379
+ list_select: lambda{|record, field, info|
380
+ value = record.values[field]
381
+ record[field] = case info[:otype]
382
+ when :string
383
+ value.join(info[:separator])
384
+ when :integer
385
+ value.reduce(0, :|)
386
+ end if value && info[:multiselect] && !info[:dummy]
326
387
  }
327
388
  )
328
389
 
329
390
  (AfterSaveProcessors ||= {}).merge!(
330
- star_to_many_field: lambda{|record, field, info|
331
- value = record.values[field]
332
- if value && value.is_a?(Hash)
333
- assoc = record.model.association_reflections[info[:assoc_name]]
334
- other_model = assoc.associated_class
335
- unlinked = value[:unlinked]
336
- linked = value[:linked]
337
- parent_key = record.primary_key_values
338
- case assoc[:type]
339
- when :one_to_many
340
- StarToManyUnlinkMetaBase.one_to_many_unlink_db(other_model, assoc, unlinked) if unlinked
341
- StarToManyLinkMeta.one_to_many_link_db(other_model, assoc, parent_key, linked) if linked
342
- when :many_to_many
343
- StarToManyUnlinkMetaBase.many_to_many_unlink_db(other_model, assoc, parent_key, unlinked) if unlinked
344
- StarToManyLinkMeta.many_to_many_link_db(other_model, assoc, parent_key, linked) if linked
345
- else unsupported_association
346
- end
347
- end
348
- },
349
391
  file_store: lambda{|m, v, info|
350
392
  value = m.values[v]
351
393
  files = E2Files.db[:files]
352
- owner = m.primary_key_values.join('|')
394
+ owner = Sequel::join_keys(m.primary_key_values)
353
395
  upload = info[:store][:upload]
354
396
  files_dir = info[:store][:files]
355
397
  value.each do |entry|
@@ -375,7 +417,7 @@ module Engine2
375
417
  # record.model.where(id).update(info[:field] => Sequel.blob(open("#{upload}/#{value[:rackname]}", "rb"){|f|f.read}))
376
418
  File.delete("#{upload}/#{value[:rackname]}")
377
419
  end
378
- }
420
+ },
379
421
  )
380
422
 
381
423
  (BeforeDestroyProcessors ||= {}).merge!(
@@ -393,7 +435,7 @@ module Engine2
393
435
  file_store: lambda{|m, v, info|
394
436
  files = E2Files.db[:files]
395
437
  files_dir = info[:store][:files]
396
- owner = m.primary_key_values.join('|')
438
+ owner = Sequel::join_keys(m.primary_key_values)
397
439
  files.select(:id, :name).where(owner: owner, model: m.model.name, field: v.to_s).all.each do |entry|
398
440
  File.delete("#{files_dir}/#{entry[:name]}_#{entry[:id]}")
399
441
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Engine2
4
5
  E2DB.create_table :files do
@@ -13,6 +14,8 @@ module Engine2
13
14
 
14
15
  class E2Files < Sequel::Model(E2DB[:files])
15
16
  extend Engine2::Model
17
+ model_icon :'file'
18
+ model_route :E2Files
16
19
 
17
20
  type_info do
18
21
  # list_select :model, Hash[@model.db.models.keys.map{|m| [m, m]}]
@@ -28,7 +31,7 @@ module Engine2
28
31
  search_live
29
32
 
30
33
  on_change :model do |req, value|
31
- # action.parent.*.assets[:model].select(:field).where(model: value).all.map{|rec|f = rec.values[:field]; [f, f]}
34
+ # node.parent.*.assets[:model].select(:field).where(model: value).all.map{|rec|f = rec.values[:field]; [f, f]}
32
35
  # render :field, list: {a: 1, b: 2}.to_a
33
36
  end
34
37
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Engine2
4
5
  class UserInfo < Sequel::Model(DUMMYDB)
@@ -6,15 +7,17 @@ module Engine2
6
7
  extend MemoryModel
7
8
 
8
9
  type_info do
9
- string_field :name, 10
10
+ string_field :name, 100
10
11
  required :name, LOCS[:user_required]
11
- string_field :password, 20
12
+ string_field :password, 100
12
13
  required :password, LOCS[:password_required]
13
14
  password :password
14
15
  end
15
16
 
16
17
  def to_hash
17
- {name: @values[:name]}
18
+ hash = @values.dup
19
+ hash.delete(:password)
20
+ hash
18
21
  end
19
22
  end
20
23
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Sequel
4
5
  module SequelFixes
@@ -8,7 +9,7 @@ module Sequel
8
9
  when Sequel::SQL::QualifiedIdentifier
9
10
  sel.column
10
11
  when Sequel::SQL::AliasedExpression
11
- Sequel::SQL::Identifier.new sel.aliaz
12
+ Sequel::SQL::Identifier.new sel.alias
12
13
  else
13
14
  sel # symbol ?
14
15
  end
@@ -31,10 +32,10 @@ module Sequel
31
32
  columns = SequelFixes.fix_aliased_expression(clone(:append_sql=>'', :placeholder_literal_null=>true))
32
33
  dsa1 = dataset_alias(1)
33
34
  rn = row_number_column
34
- sql = @opts[:append_sql] || ''
35
+ sql = @opts[:append_sql] || String.new
35
36
  subselect_sql_append(sql, unlimited.
36
37
  unordered.
37
- select_append{ROW_NUMBER{}.over(:order=>order).as(rn)}.
38
+ select_append{:ROW_NUMBER.sql_function.over(:order=>order).as(rn)}.
38
39
  from_self(:alias=>dsa1).
39
40
  select(*columns).
40
41
  limit(@opts[:limit]).
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Sequel
4
5
  class JDBC::Database
@@ -23,13 +24,16 @@ module Sequel
23
24
  rs.getInt(1)
24
25
  end
25
26
  end
27
+
28
+ def valid_connection_sql
29
+ 'select 1 from sysibm.sysdummy1'
30
+ end
26
31
  end if defined?(JDBC::AS400)
27
32
 
28
- module SchemaCaching
29
- def load_schema_cache(file)
30
- @schemas = Marshal.load(File.read(file, mode: 'rb'))
31
- nil
32
- end
33
- end
33
+ class JDBC::AS400::Dataset
34
+ def supports_where_true?
35
+ false
36
+ end
37
+ end if defined?(JDBC::AS400)
34
38
 
35
39
  end if defined? JRUBY_VERSION
@@ -1,10 +1,14 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Engine2
4
5
  class Schemes
5
6
  CRUD ||= {create: true, view: true, modify: true, delete: true}.freeze # bulk_delete: true
6
7
  VIEW ||= {view: true}.freeze
7
8
  LINK ||= {star_to_many_link: true, view: true, star_to_many_unlink: true}.freeze # star_to_many_bulk_unlink: true
9
+ STMF_CRUD ||= {star_to_many_field_create: true, star_to_many_field_view: true, star_to_many_field_modify: true, star_to_many_field_delete: true}.freeze
10
+ STMF_VIEW ||= {star_to_many_field_view: true}.freeze
11
+ STMF_LINK ||= {star_to_many_field_view: true, star_to_many_field_link: true ,star_to_many_field_unlink: true, star_to_many_field_link_list: true}.freeze
8
12
 
9
13
  attr_reader :builtin, :user
10
14
  def initialize
@@ -29,50 +33,52 @@ module Engine2
29
33
  SCHEMES.builtin.clear
30
34
  SCHEMES.instance_eval do
31
35
 
36
+ define_scheme :confirm do |name, action, options|
37
+ define_node :"confirm_#{name}", ConfirmAction do
38
+ self.*.panel_title options[:title]
39
+ self.*.message options[:message]
40
+ define_node name, action
41
+ end
42
+ end
43
+
32
44
  define_scheme :view do |name = :view|
33
- define_action name, ViewMeta
45
+ define_node name, ViewAction
34
46
  end
35
47
 
36
48
  define_scheme :create do |name = :create|
37
- define_action name, CreateMeta do
38
- define_action :approve, InsertMeta
49
+ define_node name, CreateAction do
50
+ define_node :approve, InsertAction
39
51
  end
40
52
  end
41
53
 
42
54
  define_scheme :modify do |name = :modify|
43
- define_action name, ModifyMeta do
44
- define_action :approve, UpdateMeta
55
+ define_node name, ModifyAction do
56
+ define_node :approve, UpdateAction
45
57
  end
46
58
  end
47
59
 
48
60
  define_scheme :delete do
49
- define_action :confirm_delete, ConfirmMeta do
50
- self.*.message LOCS[:delete_question]
51
- self.*.panel_title LOCS[:confirm_delete_title]
52
- define_action :delete, DeleteMeta
53
- end
61
+ run_scheme :confirm, :delete, DeleteAction,
62
+ message: LOCS[:delete_question], title: LOCS[:confirm_delete_title]
54
63
  end
55
64
 
56
65
  define_scheme :bulk_delete do
57
- define_action :confirm_bulk_delete, ConfirmMeta do
58
- self.*.message LOCS[:delete_question]
59
- self.*.panel_title LOCS[:confirm_bulk_delete_title]
60
- define_action :bulk_delete, BulkDeleteMeta
61
- end
66
+ run_scheme :confirm, :bulk_delete, BulkDeleteAction,
67
+ message: LOCS[:delete_question], title: LOCS[:confirm_bulk_delete_title]
62
68
  end
63
69
 
64
70
  define_scheme :default do |name, model, options|
65
71
  options ||= Schemes::CRUD
66
- define_action name, ListMeta, model: model do
72
+ define_node name, ListAction, model: model do
67
73
  options.each{|k, v| run_scheme(k) if v}
68
74
 
69
- define_action_bundle :form, :create, :modify if options[:create] && options[:modify]
70
- # define_action_bundle :decode, :decode_entry, :decode_list, :typahead
75
+ define_node_bundle :form, :create, :modify if options[:create] && options[:modify]
76
+ # define_node_bundle :decode, :decode_entry, :decode_list, :typahead
71
77
 
72
78
  # if ?
73
- define_action :decode_entry, DecodeEntryMeta
74
- define_action :decode_list, DecodeListMeta
75
- define_action :typeahead, TypeAheadMeta
79
+ define_node :decode_entry, DecodeEntryAction
80
+ define_node :decode_list, DecodeListAction
81
+ define_node :typeahead, TypeAheadAction
76
82
  end
77
83
  end
78
84
 
@@ -80,7 +86,7 @@ module Engine2
80
86
  # Many to One
81
87
  #
82
88
  define_scheme :many_to_one do
83
- define_action :list, ManyToOneListMeta do
89
+ define_node :list, ManyToOneListAction do
84
90
  run_scheme :view
85
91
  end
86
92
  end
@@ -89,18 +95,18 @@ module Engine2
89
95
  assoc = model.association_reflections[assoc_name]
90
96
  ::Kernel::raise E2Error.new("Association '#{assoc_name}' not found for model '#{model}'") unless assoc
91
97
 
92
- if self.*.assets[:model] != model && self.*.is_a?(ListMeta)
98
+ if self.*.assets[:model] != model && self.*.is_a?(ListAction)
93
99
  # verify relations ?
94
100
  mdl = assoc[:model]
95
101
  info = mdl.type_info[assoc[:keys].first]
96
102
  options = info[:decode][:search]
97
103
  end
98
104
 
99
- define_action :"#{assoc_name}!" do
105
+ define_node :"#{assoc_name}!" do
100
106
  # iterate over options like in :default ?
101
- define_action :list, DecodeListMeta, assoc: assoc if options[:list]
102
- define_action :typeahead, TypeAheadMeta, assoc: assoc if options[:typeahead]
103
- define_action :decode, DecodeEntryMeta, assoc: assoc do
107
+ define_node :list, DecodeListAction, assoc: assoc if options[:list]
108
+ define_node :typeahead, TypeAheadAction, assoc: assoc if options[:typeahead]
109
+ define_node :decode, DecodeEntryAction, assoc: assoc do
104
110
  run_scheme :many_to_one
105
111
  end if options[:scaffold]
106
112
  end
@@ -110,34 +116,28 @@ module Engine2
110
116
  # * to Many
111
117
  #
112
118
  define_scheme :star_to_many_unlink do
113
- define_action :confirm_unlink, ConfirmMeta do
114
- self.*.message LOCS[:unlink_question]
115
- self.*.panel_title LOCS[:confirm_unlink_title]
116
- define_action :unlink, StarToManyUnlinkMeta
117
- end
119
+ run_scheme :confirm, :unlink, StarToManyUnlinkAction,
120
+ message: LOCS[:unlink_question], title: LOCS[:confirm_unlink_title]
118
121
  end
119
122
 
120
123
  define_scheme :star_to_many_bulk_unlink do
121
- define_action :confirm_bulk_unlink, ConfirmMeta do
122
- self.*.message LOCS[:unlink_question]
123
- self.*.panel_title LOCS[:confirm_bulk_unlink_title]
124
- define_action :bulk_unlink, StarToManyBulkUnlinkMeta
125
- end
124
+ run_scheme :confirm, :bulk_unlink, StarToManyBulkUnlinkAction,
125
+ message: LOCS[:unlink_question], title: LOCS[:confirm_bulk_unlink_title]
126
126
  end
127
127
 
128
128
  define_scheme :star_to_many_link do
129
- define_action :link_list, StarToManyLinkListMeta do
129
+ define_node :link_list, StarToManyLinkListAction do
130
130
  run_scheme :view
131
- define_action :link, StarToManyLinkMeta
131
+ define_node :link, StarToManyLinkAction
132
132
  end
133
133
  end
134
134
 
135
- define_scheme :star_to_many do |act, assoc, model|
135
+ define_scheme :star_to_many do |assoc_name, assoc, model|
136
+ action.menu(:item_menu).option assoc_name, icon: Kernel::const_get(assoc[:class_name]).model_icon # , click: "action.show_assoc($index, \"#{assoc_name}!\")"
136
137
  options = assoc[:options] || Schemes::LINK
137
- define_action act, StarToManyListMeta, model: model, assoc: assoc do
138
+ define_node assoc_name, StarToManyListAction, model: model, assoc: assoc do
138
139
  options.each{|k, v| run_scheme(k) if v}
139
-
140
- define_action_bundle :form, :create, :modify if options[:create] && options[:modify]
140
+ define_node_bundle :form, :create, :modify if options[:create] && options[:modify]
141
141
  end
142
142
  end
143
143
 
@@ -145,11 +145,11 @@ module Engine2
145
145
  # arbitrary files per form
146
146
  #
147
147
  define_scheme :file_store do |model, field|
148
- define_action :"#{field}_file_store!", FileStoreMeta do
148
+ define_node :"#{field}_file_store!", FileStoreAction do
149
149
  self.*.model = model
150
150
  self.*.field = field
151
- define_action :download, DownloadFileStoreMeta
152
- define_action :upload, UploadFileStoreMeta
151
+ define_node :download, DownloadFileStoreAction
152
+ define_node :upload, UploadFileStoreAction
153
153
  end
154
154
  end
155
155
 
@@ -157,11 +157,11 @@ module Engine2
157
157
  # blob field in source table
158
158
  #
159
159
  define_scheme :blob_store do |model, field|
160
- define_action :"#{field}_blob_store!", BlobStoreMeta do
160
+ define_node :"#{field}_blob_store!", BlobStoreAction do
161
161
  self.*.model = model
162
- self.*.field = field # model.type_info[field][:field]
163
- define_action :download, DownloadBlobStoreMeta
164
- define_action :upload, UploadBlobStoreMeta
162
+ self.*.field = field
163
+ define_node :download, DownloadBlobStoreAction
164
+ define_node :upload, UploadBlobStoreAction
165
165
  end
166
166
  end
167
167
 
@@ -169,29 +169,71 @@ module Engine2
169
169
  # blob field in foreign (one to one) table
170
170
  #
171
171
  define_scheme :foreign_blob_store do |model, field|
172
- define_action :"#{field}_blob_store!", ForeignBlobStoreMeta do
172
+ define_node :"#{field}_blob_store!", ForeignBlobStoreAction do
173
173
  self.*.model = model
174
- self.*.field = field # model.type_info[field][:field]
175
- define_action :download, DownloadForeignBlobStoreMeta
176
- define_action :upload, UploadBlobStoreMeta
174
+ self.*.field = field
175
+ define_node :download, DownloadForeignBlobStoreAction
176
+ define_node :upload, UploadBlobStoreAction
177
177
  end
178
178
  end
179
179
 
180
- define_scheme :star_to_many_field do |assoc, field|
181
- define_action :"#{field}!", StarToManyFieldMeta, assoc: assoc do
182
- run_scheme :view
183
- define_action :confirm_unlink, ConfirmMeta do
184
- self.*.message LOCS[:unlink_question]
185
- define_action :unlink, StarToManyFieldUnlinkMeta
186
- end
187
- define_action :link_list, StarToManyFieldLinkListMeta do
188
- run_scheme :view
180
+ define_scheme :star_to_many_field_view do
181
+ define_node :view, ViewAction do
182
+ action{@action_type = :star_to_many_field_view}
183
+ end
184
+ end
185
+
186
+ define_scheme :star_to_many_field_link do
187
+ define_node :link, StarToManyLinkAction
188
+ end
189
+
190
+ define_scheme :star_to_many_field_unlink do
191
+ define_node :confirm_unlink, ConfirmAction do
192
+ self.*.message LOCS[:unlink_question]
193
+ define_node :unlink, StarToManyUnlinkAction do
194
+ action{@action_type = :star_to_many_field_unlink}
189
195
  end
190
196
  end
191
197
  end
192
198
 
193
- define_scheme :array do |name, model|
194
- define_action name, ArrayListMeta, model: model do
199
+ define_scheme :star_to_many_field_link_list do
200
+ define_node :link_list, StarToManyFieldLinkListAction do
201
+ run_scheme :view
202
+ end
203
+ end
204
+
205
+ #
206
+ # *_to_many_field
207
+ #
208
+ define_scheme :star_to_many_field do |assoc, field|
209
+ schemes = assoc[:model].type_info.fetch(field)[:schemes]
210
+ define_node :"#{field}!", StarToManyFieldAction, assoc: assoc do
211
+ schemes.each{|k, v| run_scheme(k) if v}
212
+
213
+ define_node_bundle :form, :star_to_many_field_create, :star_to_many_field_modify if schemes[:star_to_many_field_create] && schemes[:star_to_many_field_modify]
214
+ end
215
+ end
216
+
217
+ define_scheme :star_to_many_field_create do
218
+ define_node :create, CreateAction do
219
+ define_node :approve, StarToManyFieldInsertAction
220
+ end
221
+ end
222
+
223
+ define_scheme :star_to_many_field_modify do
224
+ define_node :modify, ModifyAction do
225
+ action{@action_type = :star_to_many_field_modify}
226
+ define_node :approve, StarToManyFieldUpdateAction
227
+ end
228
+ end
229
+
230
+ define_scheme :star_to_many_field_delete do
231
+ define_node :confirm_delete, ConfirmAction do
232
+ self.*.message LOCS[:delete_question]
233
+ self.*.panel_title LOCS[:confirm_delete_title]
234
+ define_node :delete, DeleteAction do
235
+ action{@action_type = :star_to_many_field_delete}
236
+ end
195
237
  end
196
238
  end
197
239
  end