engine2 1.0.4 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
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