engine2 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -117
  3. data/{views → app}/app.coffee +0 -0
  4. data/{public/css → app}/app.css +203 -196
  5. data/{views → app}/engine2.coffee +111 -60
  6. data/{views → app}/engine2actions.coffee +47 -28
  7. data/bower.json +13 -0
  8. data/conf/message.yaml +2 -1
  9. data/conf/message_pl.yaml +2 -1
  10. data/config.coffee +62 -0
  11. data/engine2.gemspec +2 -5
  12. data/lib/engine2.rb +1 -1
  13. data/lib/engine2/action.rb +9 -24
  14. data/lib/engine2/core.rb +9 -8
  15. data/lib/engine2/handler.rb +1 -5
  16. data/lib/engine2/meta.rb +61 -24
  17. data/lib/engine2/meta/array_meta.rb +82 -0
  18. data/lib/engine2/meta/decode_meta.rb +1 -1
  19. data/lib/engine2/meta/infra_meta.rb +21 -26
  20. data/lib/engine2/meta/list_meta.rb +2 -3
  21. data/lib/engine2/model.rb +5 -5
  22. data/lib/engine2/pre_bootstrap.rb +9 -1
  23. data/lib/engine2/scheme.rb +4 -0
  24. data/lib/engine2/type_info.rb +8 -1
  25. data/lib/engine2/version.rb +1 -1
  26. data/package.json +38 -0
  27. data/public/img/ajax-loader.gif +0 -0
  28. data/views/fields/blob.slim +4 -5
  29. data/views/fields/bs_select.slim +2 -2
  30. data/views/fields/bsselect_picker.slim +1 -2
  31. data/views/fields/bsselect_picker_opt.slim +1 -2
  32. data/views/fields/checkbox.slim +1 -1
  33. data/views/fields/checkbox_buttons.slim +1 -1
  34. data/views/fields/checkbox_buttons_opt.slim +1 -1
  35. data/views/fields/currency.slim +2 -2
  36. data/views/fields/date.slim +0 -1
  37. data/views/fields/date_range.slim +0 -1
  38. data/views/fields/date_time.slim +0 -1
  39. data/views/fields/datetime.slim +0 -2
  40. data/views/fields/decimal.slim +0 -1
  41. data/views/fields/decimal_date.slim +0 -1
  42. data/views/fields/decimal_time.slim +0 -1
  43. data/views/fields/email.slim +1 -2
  44. data/views/fields/file_store.slim +1 -1
  45. data/views/fields/input_text.slim +1 -2
  46. data/views/fields/integer.slim +1 -1
  47. data/views/fields/list_bsselect.slim +1 -2
  48. data/views/fields/list_bsselect_opt.slim +2 -3
  49. data/views/fields/list_buttons.slim +1 -1
  50. data/views/fields/list_buttons_opt.slim +1 -1
  51. data/views/fields/list_select.slim +1 -2
  52. data/views/fields/list_select_opt.slim +2 -3
  53. data/views/fields/password.slim +1 -2
  54. data/views/fields/radio_checkbox.slim +1 -1
  55. data/views/fields/scaffold.slim +1 -1
  56. data/views/fields/scaffold_picker.slim +1 -2
  57. data/views/fields/select_picker.slim +1 -2
  58. data/views/fields/select_picker_opt.slim +1 -2
  59. data/views/fields/text_area.slim +0 -1
  60. data/views/fields/time.slim +0 -1
  61. data/views/fields/typeahead_picker.slim +1 -2
  62. data/views/index.slim +4 -8
  63. data/views/scaffold/fields.slim +4 -4
  64. data/views/scaffold/form.slim +1 -7
  65. data/views/scaffold/form_collapse.slim +19 -0
  66. data/views/scaffold/form_tabs.slim +9 -0
  67. data/views/scaffold/list.slim +1 -12
  68. data/views/scaffold/search.slim +2 -9
  69. data/views/scaffold/search_collapse.slim +26 -0
  70. data/views/scaffold/search_tabs.slim +15 -0
  71. data/views/scaffold/view.slim +5 -15
  72. data/views/scaffold/view_collapse.slim +22 -0
  73. data/views/scaffold/view_tabs.slim +11 -0
  74. data/views/search_fields/bsmselect_picker.slim +1 -2
  75. data/views/search_fields/bsselect_picker.slim +1 -2
  76. data/views/search_fields/checkbox.slim +3 -3
  77. data/views/search_fields/checkbox2.slim +5 -5
  78. data/views/search_fields/checkbox_buttons.slim +2 -2
  79. data/views/search_fields/date_range.slim +0 -2
  80. data/views/search_fields/decimal_date_range.slim +5 -5
  81. data/views/search_fields/input_text.slim +2 -2
  82. data/views/search_fields/integer.slim +1 -1
  83. data/views/search_fields/integer_range.slim +2 -2
  84. data/views/search_fields/list_bsmselect.slim +1 -1
  85. data/views/search_fields/list_bsselect.slim +0 -1
  86. data/views/search_fields/list_buttons.slim +2 -2
  87. data/views/search_fields/list_select.slim +1 -2
  88. data/views/search_fields/scaffold_picker.slim +1 -2
  89. data/views/search_fields/select_picker.slim +1 -2
  90. data/views/search_fields/typeahead_picker.slim +1 -2
  91. metadata +29 -103
  92. data/public/assets/javascripts.js +0 -13
  93. data/public/assets/styles.css +0 -4
  94. data/public/css/angular-motion.css +0 -1022
  95. data/public/css/angular-ui-tree.min.css +0 -1
  96. data/public/css/bootstrap-additions.css +0 -1560
  97. data/public/css/bootstrap.min.css +0 -11
  98. data/public/css/font-awesome.min.css +0 -4
  99. data/public/fonts/FontAwesome.otf +0 -0
  100. data/public/fonts/fontawesome-webfont.eot +0 -0
  101. data/public/fonts/fontawesome-webfont.svg +0 -655
  102. data/public/fonts/fontawesome-webfont.ttf +0 -0
  103. data/public/fonts/fontawesome-webfont.woff +0 -0
  104. data/public/fonts/fontawesome-webfont.woff2 +0 -0
  105. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  106. data/public/fonts/glyphicons-halflings-regular.svg +0 -288
  107. data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  108. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  109. data/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  110. data/public/images/file.png +0 -0
  111. data/public/images/folder-closed.png +0 -0
  112. data/public/images/folder.png +0 -0
  113. data/public/images/node-closed-2.png +0 -0
  114. data/public/images/node-closed-light.png +0 -0
  115. data/public/images/node-closed.png +0 -0
  116. data/public/images/node-opened-2.png +0 -0
  117. data/public/images/node-opened-light.png +0 -0
  118. data/public/images/node-opened.png +0 -0
  119. data/public/img/ajax-loader-light.gif +0 -0
  120. data/public/js/angular-animate.js +0 -4147
  121. data/public/js/angular-cookies.js +0 -322
  122. data/public/js/angular-local-storage.js +0 -455
  123. data/public/js/angular-route.js +0 -1025
  124. data/public/js/angular-sanitize.js +0 -717
  125. data/public/js/angular-strap.js +0 -4339
  126. data/public/js/angular-strap.tpl.js +0 -43
  127. data/public/js/angular-ui-tree.js +0 -1569
  128. data/public/js/angular.js +0 -30868
  129. data/public/js/i18n/angular-locale_pl.js +0 -115
  130. data/public/js/lodash.custom.min.js +0 -99
  131. data/public/js/ng-file-upload-shim.min.js +0 -2
  132. data/public/js/ng-file-upload.min.js +0 -3
  133. data/views/engine2templates.coffee +0 -0
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "engine2",
3
+ "version": "1.0.0",
4
+ "dependencies": {
5
+ "angular-strap": "^2.3.10",
6
+ "angular": "^1.5.8"
7
+ },
8
+ "overrides": {
9
+ "angular": {
10
+ "main": []
11
+ }
12
+ }
13
+ }
@@ -1,4 +1,3 @@
1
- :engine2_resource_loaded: true
2
1
  :default_date_format: yyyy-MM-dd
3
2
  :default_date_short_format: yy-MM-dd
4
3
  :default_date_model_format: yyyy-MM-dd
@@ -88,6 +87,8 @@
88
87
  :invalid_email_format: Incorrect email format
89
88
  :invalid_format: Incorrect format
90
89
 
90
+ :currency_symbol: $
91
+
91
92
  :access_forbidden: Access forbidden
92
93
  :access_unauthorized: Access unauthorized
93
94
  :access_not_found: Not found
@@ -1,4 +1,3 @@
1
- :engine2_resource_loaded: true
2
1
  :default_date_format: yyyy-MM-dd
3
2
  :default_date_short_format: yy-MM-dd
4
3
  :default_date_model_format: yyyy-MM-dd
@@ -93,6 +92,8 @@
93
92
  :access_not_found: Nie znaleziono
94
93
  :access_method_not_allowed: Metoda niedozwolona
95
94
 
95
+ :currency_symbol: zł
96
+
96
97
  :list_locs:
97
98
  :search: Szukaj
98
99
  :page: Strona
@@ -0,0 +1,62 @@
1
+ exports.config =
2
+ npm:
3
+ enabled: true
4
+ globals:
5
+ _: 'lodash'
6
+ angular: 'angular'
7
+ styles:
8
+ "bootstrap": ["dist/css/bootstrap.css"]
9
+ "bootstrap-additions": ["dist/bootstrap-additions.css"]
10
+ "angular-motion": ["dist/angular-motion.css"]
11
+ "angular-ui-tree": ["dist/angular-ui-tree.css"]
12
+ "font-awesome": ["css/font-awesome.css"]
13
+
14
+ modules:
15
+ definition: 'commonjs'
16
+ wrapper: false
17
+
18
+ paths:
19
+ public: 'public'
20
+ watched: ['app']
21
+
22
+ files:
23
+ javascripts:
24
+ joinTo:
25
+ 'engine2vendor.js': /^node_modules|bower_components/
26
+ 'engine2.js': /^app/
27
+
28
+ stylesheets:
29
+ joinTo:
30
+ 'engine2vendor.css': /^node_modules/
31
+ 'engine2app.css': /^app/
32
+ order:
33
+ before: [
34
+ /bootstrap.css$/
35
+ ]
36
+
37
+ plugins:
38
+ on: ["ng-annotate-brunch"]
39
+
40
+ uglify:
41
+ mangle: true
42
+ compress:
43
+ global_defs:
44
+ DEBUG: false
45
+
46
+ replacement:
47
+ replacements: [
48
+ files: [/vendor.js$/]
49
+ match: (
50
+ fix = "$modal.$element = compileData.link(modalScope, function(clonedElement, scope) {});"
51
+ find: fix.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1")
52
+ replace: "#{fix}$modal.$backdrop = backdropElement;"
53
+ )
54
+ ]
55
+
56
+ copycat:
57
+ fonts: [
58
+ "node_modules/font-awesome/fonts"
59
+ "node_modules/bootstrap/fonts"
60
+ ]
61
+ verbose: true
62
+ onlyChanged: true
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.require_paths = ["lib"]
18
18
 
19
19
  spec.add_dependency "sequel", '~> 4'
20
+ spec.add_dependency "rack-contrib", '~> 1.4'
20
21
  if defined? JRUBY_VERSION
21
22
  spec.add_dependency 'jdbc-sqlite3', '~> 3.8'
22
23
  else
@@ -24,11 +25,7 @@ Gem::Specification.new do |spec|
24
25
  end
25
26
  spec.add_dependency "sinatra", '~> 1.4'
26
27
  spec.add_dependency 'slim', '~> 3.0'
27
- spec.add_dependency "execjs", '~> 2.6'
28
- spec.add_dependency 'coffee-script', '~> 2.4'
29
28
 
30
29
  spec.add_development_dependency "bundler", "~> 1.11"
31
- spec.add_development_dependency "rake", "~> 11.1"
32
- spec.add_development_dependency 'uglifier', '~> 3.0'
33
- spec.add_development_dependency 'yui-compressor', '~> 0.12'
30
+ spec.add_development_dependency "rake", "~> 11"
34
31
  end
@@ -6,7 +6,6 @@ require 'sequel'
6
6
  require 'sinatra'
7
7
  require 'json'
8
8
  require 'slim'
9
- require 'tilt/coffee'
10
9
  require 'engine2/version'
11
10
 
12
11
  %w[
@@ -19,6 +18,7 @@ require 'engine2/version'
19
18
  action.rb
20
19
  scheme.rb
21
20
 
21
+ meta/array_meta.rb
22
22
  meta/list_meta.rb
23
23
  meta/view_meta.rb
24
24
  meta/form_meta.rb
@@ -9,6 +9,10 @@ module Engine2
9
9
 
10
10
  class << self
11
11
  attr_accessor :count
12
+
13
+ def default_meta
14
+ Class.new(InlineMeta){meta_type :inline}
15
+ end
12
16
  end
13
17
 
14
18
  def initialize parent, name, meta_class, assets
@@ -46,7 +50,7 @@ module Engine2
46
50
  result
47
51
  end
48
52
 
49
- def define_action name, meta_class = DummyMeta, assets = {}, &blk
53
+ def define_action name, meta_class = Action.default_meta, assets = {}, &blk
50
54
  ::Kernel.raise E2Error.new("Action #{name} already defined") if @actions[name]
51
55
  action = @actions[name] = Action.new(self, name, meta_class, assets)
52
56
  action.*.pre_run
@@ -59,15 +63,15 @@ module Engine2
59
63
  action
60
64
  end
61
65
 
62
- def define_action_meta name, meta_class = DummyMeta, assets = {}, &blk
66
+ def define_action_meta name, meta_class = Action.default_meta, assets = {}, &blk
63
67
  define_action name, meta_class, assets do
64
68
  self.* &blk
65
69
  end
66
70
  end
67
71
 
68
- def define_action_invoke name, meta_class = DummyMeta, assets = {}, &blk
72
+ def define_action_invoke name, meta_class = Action.default_meta, assets = {}, &blk
69
73
  define_action name, meta_class, assets do
70
- self.*.define_singleton_method(:invoke, &blk)
74
+ self.*.define_invoke &blk
71
75
  end
72
76
  end
73
77
 
@@ -101,8 +105,7 @@ module Engine2
101
105
  access: recheck_access ? nil : a.check_access!(handler),
102
106
  recheck_access: a.recheck_access,
103
107
  terminal: a.actions.empty?,
104
- meta: !meta.get.empty?,
105
- invokable: meta.invokable
108
+ meta: !meta.get.empty?
106
109
  }
107
110
  h
108
111
  end
@@ -189,24 +192,6 @@ module Engine2
189
192
  end
190
193
 
191
194
  ::Kernel::puts "ACTIONS: #{Action.count}, Time: #{::Time.now - time}"
192
- # verify_action_usage
193
- end
194
-
195
- def verify_action_usage
196
- t = ::Time.now
197
- each_action do |action|
198
- meta = action.*
199
- model = meta.assets[:model]
200
- if model
201
- model.one_to_many_associations.each do |a|
202
- end
203
- true
204
- else
205
- true
206
- end
207
-
208
- end
209
- ::Kernel::puts "VERIFY #{::Time.now - t}"
210
195
  end
211
196
 
212
197
  def p *args
@@ -123,7 +123,7 @@ class << Sequel
123
123
  attr_accessor :alias_columns_in_joins
124
124
 
125
125
  def split_keys id
126
- id.split('|')
126
+ id.split(Engine2::SETTINGS[:key_separator])
127
127
  end
128
128
  end
129
129
 
@@ -336,7 +336,7 @@ module E2Model
336
336
  else
337
337
  a = model.many_to_one_associations[table] # || model.one_to_one_associations[table]
338
338
  raise Engine2::E2Error.new("Association #{table} not found for model #{model}") unless a
339
- m = Object.const_get(a[:class_name])
339
+ m = a.associated_class
340
340
  end
341
341
  # raise Engine2::E2Error.new("Model not found for table #{table} in model #{model}") unless m
342
342
  info = m.type_info
@@ -379,7 +379,7 @@ module E2Model
379
379
  @opts[:select].compact!
380
380
 
381
381
  joins.reduce(self) do |joined, (table, assoc)|
382
- m = Object.const_get(assoc[:class_name])
382
+ m = assoc.associated_class
383
383
  keys = assoc[:qualified_key]
384
384
  joined.left_join(table, m.primary_keys.zip(keys.is_a?(Array) ? keys : [keys]))
385
385
  end
@@ -395,7 +395,7 @@ module E2Model
395
395
  end
396
396
  when Sequel::SQL::QualifiedIdentifier
397
397
  yield sel.table, sel.column, al
398
- when Sequel::SQL::AliasedExpression
398
+ when Sequel::SQL::AliasedExpression, Sequel::SQL::Function
399
399
  sel
400
400
  # extract_select sel.expression, sel.aliaz, &blk
401
401
  # expr = sel.expression
@@ -433,9 +433,10 @@ end
433
433
  module Engine2
434
434
  LOCS ||= Hash.new{|h, k| ":#{k}:"}
435
435
  PATH ||= File.expand_path('../..', File.dirname(__FILE__))
436
+ SETTINGS ||= {key_separator: '|'}
436
437
 
437
438
  class << self
438
- attr_reader :app, :app_name, :reloading
439
+ attr_reader :app
439
440
  attr_reader :core_loaded
440
441
 
441
442
  def database name
@@ -490,10 +491,10 @@ module Engine2
490
491
  puts "BOOTSTRAP #{app}, Time: #{Time.new - t}"
491
492
  end
492
493
 
493
- def bootstrap app, opts = {}
494
+ def bootstrap app, settings = {}
494
495
  @app = app
495
- @app_name = opts[:name] || File::basename(app)
496
- @reloading = opts[:reloading]
496
+ SETTINGS.merge! settings
497
+ SETTINGS[:name] ||= File::basename(app)
497
498
  bootstrap_e2db
498
499
 
499
500
  require 'engine2/pre_bootstrap'
@@ -106,15 +106,11 @@ module Engine2
106
106
  halt_server_error Rack::Utils.escape_html(error.inspect) + "<hr>" + error.backtrace.take(30).map{|b| Rack::Utils.escape_html(b)}.join("<br>"), LOCS[:error]
107
107
  end
108
108
 
109
- get "/js/*.js" do |c|
110
- coffee c.to_sym
111
- end
112
-
113
109
  get '/*' do |name|
114
110
  headers 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Pragma' => 'no-cache', 'Expires' => '0'
115
111
  if name.empty?
116
112
  if settings.development?
117
- load('engine2.rb') if Engine2::reloading
113
+ load('engine2.rb') if Engine2::SETTINGS[:reloading]
118
114
  Engine2::reload
119
115
  end
120
116
  name = 'index'
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  module Engine2
3
3
  class Meta
4
- attr_reader :action, :assets, :invokable, :static
4
+ attr_reader :action, :assets, :static, :invokable
5
5
 
6
6
  class << self
7
7
  def meta_type mt = nil
@@ -38,12 +38,17 @@ module Engine2
38
38
  raise E2Error.new("Static meta required") if dynamic?
39
39
  end
40
40
 
41
+ def define_invoke &blk
42
+ check_static_meta
43
+ self.class.class_eval{define_method :invoke, &blk}
44
+ end
45
+
41
46
  def invoke! handler
42
47
  if rmp = @request_meta_proc
43
48
  meta = self.class.new(action, assets, self)
44
- meta.instance_exec(handler, *meta.request_meta_proc_params(handler), &rmp)
49
+ meta_result = meta.instance_exec(handler, *meta.request_meta_proc_params(handler), &rmp)
45
50
  meta.post_process
46
- response = meta.invoke(handler)
51
+ response = @requestable ? (meta_result || {}) : meta.invoke(handler)
47
52
  response[:meta] = meta.get
48
53
  response
49
54
  else
@@ -51,6 +56,18 @@ module Engine2
51
56
  end
52
57
  end
53
58
 
59
+ def repeat time
60
+ @meta[:repeat] = time
61
+ end
62
+
63
+ def arguments args
64
+ @meta[:arguments] = args
65
+ end
66
+
67
+ def execute time
68
+ @meta[:execute] = time
69
+ end
70
+
54
71
  def get
55
72
  @meta
56
73
  end
@@ -114,7 +131,16 @@ module Engine2
114
131
  end
115
132
 
116
133
  def post_run
117
- @invokable = respond_to?(:invoke)
134
+ if respond_to? :invoke
135
+ @invokable = true
136
+ else
137
+ if @request_meta_proc
138
+ @invokable = true
139
+ @requestable = true
140
+ else
141
+ @meta[:invokable] = false
142
+ end
143
+ end
118
144
  post_process
119
145
  end
120
146
 
@@ -126,15 +152,14 @@ module Engine2
126
152
  end
127
153
  end
128
154
 
129
- class DummyMeta < Meta
130
- meta_type :dummy
155
+ class InlineMeta < Meta
156
+ meta_type :inline
131
157
  end
132
158
 
133
159
  class RootMeta < Meta
134
160
  def initialize *args
135
161
  super
136
- @meta[:environment] = Handler::environment
137
- @meta[:application] = Engine2::app_name
162
+ @meta.merge! environment: Handler::environment, application: Engine2::SETTINGS[:name], key_separator: Engine2::SETTINGS[:key_separator]
138
163
  end
139
164
  end
140
165
 
@@ -220,7 +245,7 @@ module Engine2
220
245
  end until mdl
221
246
 
222
247
  if asc = @assets[:assoc]
223
- @assets[:model] = Object.const_get(asc[:class_name])
248
+ @assets[:model] = asc.associated_class
224
249
  # raise E2Error.new("Association '#{asc}' for model '#{asc[:class_name]}' not found") unless @assets[:model]
225
250
  else
226
251
  @assets[:model] = mdl
@@ -250,7 +275,7 @@ module Engine2
250
275
  if name =~ /^(\w+)__(\w+?)$/ # (?:___\w+)?
251
276
  assoc = model.many_to_one_associations[$1.to_sym] || model.one_to_one_associations[$1.to_sym]
252
277
  raise E2Error.new("Association #{$1} not found for model #{model}") unless assoc
253
- m = Object.const_get(assoc[:class_name])
278
+ m = assoc.associated_class
254
279
  info = m.type_info.fetch($2.to_sym)
255
280
  else
256
281
  raise E2Error.new("Type info not found for '#{name}' in model '#{model}'")
@@ -546,7 +571,7 @@ module Engine2
546
571
 
547
572
  def pre_run
548
573
  super
549
- config.merge!(per_page: 10, use_count: false, show_item_menu: true, selectable: true) # search_active: false,
574
+ config.merge!(per_page: 10, use_count: false, selectable: true) # search_active: false,
550
575
 
551
576
  panel_template 'scaffold/list'
552
577
  panel_panel_template 'panels/menu_m' unless action.parent.*.assets[:model]
@@ -572,6 +597,11 @@ module Engine2
572
597
  @meta[:state] = [:query, :ui_state]
573
598
  end
574
599
 
600
+ def field_tabs hash
601
+ super
602
+ search_template 'scaffold/search_tabs'
603
+ end
604
+
575
605
  def select_toggle_menu
576
606
  m = menu :menu
577
607
  unless m.option_index(:select_toggle, false)
@@ -670,6 +700,11 @@ module Engine2
670
700
  (@filters ||= {})[name] = blk
671
701
  end
672
702
 
703
+ def filter_case_insensitive name
704
+ raise E2Error.new("Field '#{name}' needs to be a string one") unless get_type_info(name)[:otype] == :string
705
+ filter(name){|query, hash, handler| query.where(name.ilike("%#{hash[name]}%")) }
706
+ end
707
+
673
708
  def order name, &blk
674
709
  (@orders ||= {})[name] = blk
675
710
  end
@@ -770,6 +805,11 @@ module Engine2
770
805
  # modal_action false
771
806
  end
772
807
 
808
+ def field_tabs hash
809
+ super
810
+ panel_template 'scaffold/form_tabs'
811
+ end
812
+
773
813
  def record handler, record
774
814
  end
775
815
 
@@ -909,11 +949,17 @@ module Engine2
909
949
  super
910
950
  panel_template 'scaffold/view'
911
951
  panel_title LOCS[:view_title]
952
+ panel[:backdrop] = true
912
953
 
913
954
  menu(:panel_menu).option :cancel, icon: "remove"
914
955
  action.parent.*.menu(:item_menu).option action.name, icon: "file", button_loc: false
915
956
  end
916
957
 
958
+ def field_tabs hash
959
+ super
960
+ panel_template 'scaffold/view_tabs'
961
+ end
962
+
917
963
  def record handler, record
918
964
  end
919
965
 
@@ -1002,6 +1048,9 @@ module Engine2
1002
1048
  datetime: lambda{|meta, field, info|
1003
1049
  meta.info[field][:render].merge! date_format: info[:date_format], time_format: info[:time_format], date_model_format: info[:date_model_format], time_model_format: info[:time_model_format]
1004
1050
  },
1051
+ currency: lambda{|meta, field, info|
1052
+ meta.info[field][:render].merge! symbol: info[:symbol]
1053
+ },
1005
1054
  # date_range: lambda{|meta, field, info|
1006
1055
  # meta.info[field][:render].merge! other_date: info[:other_date], format: info[:format], model_format: info[:model_format]
1007
1056
  # meta.hide_fields info[:other_date]
@@ -1024,14 +1073,10 @@ module Engine2
1024
1073
  },
1025
1074
  file_store: lambda{|meta, field, info|
1026
1075
  meta.info[field][:render].merge! multiple: info[:multiple]
1027
- # meta[:model] = meta.action.model.table_name
1028
1076
  },
1029
1077
  star_to_many_field: lambda{|meta, field, info|
1030
1078
  field_info = meta.info[field]
1031
1079
  field_info[:assoc] = :"#{info[:assoc_name]}!"
1032
- # meta.info[field][:render].merge! multiple: info[:multiple]
1033
- # field_info = meta.info[field]
1034
- # field_info[:resource] ||= "#{Handler::API}#{meta.model.namespace}/#{info[:assoc_name]}"
1035
1080
  }
1036
1081
  )
1037
1082
 
@@ -1067,15 +1112,7 @@ module Engine2
1067
1112
  keys = info[:keys]
1068
1113
  else
1069
1114
  meta.check_static_meta
1070
- model = Object.const_get(model.many_to_one_associations[field[/^\w+?(?=__)/].to_sym][:class_name])
1071
- # meta.action.define_action :"#{info[:assoc_name]}!" do # assoc_#{aname}
1072
- # define_action :decode, DecodeEntryMeta, assoc: model.association_reflections[info[:assoc_name]] do
1073
- # run_scheme :default_many_to_one
1074
- # end
1075
- # end
1076
-
1077
- # verify associations ?
1078
- # model = Model.models.fetch(field[/^\w+?(?=__)/].to_sym)
1115
+ model = model.many_to_one_associations[field[/^\w+?(?=__)/].to_sym].associated_class
1079
1116
  keys = info[:keys].map{|k| :"#{model.table_name}__#{k}"}
1080
1117
  end
1081
1118