engine2 1.0.4 → 1.0.5

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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -0
  3. data/Rakefile +1 -1
  4. data/app/{engine2actions.coffee → actions.coffee} +192 -142
  5. data/app/app.coffee +0 -0
  6. data/app/app.css +4 -0
  7. data/app/engine2.coffee +87 -175
  8. data/app/modal.coffee +133 -0
  9. data/bower.json +2 -1
  10. data/conf/message.yaml +0 -0
  11. data/conf/message_pl.yaml +0 -0
  12. data/config.coffee +11 -2
  13. data/engine2.gemspec +2 -2
  14. data/lib/engine2.rb +12 -10
  15. data/lib/engine2/action.rb +1290 -134
  16. data/lib/engine2/{meta/array_meta.rb → action/array.rb} +4 -3
  17. data/lib/engine2/{meta/decode_meta.rb → action/decode.rb} +16 -15
  18. data/lib/engine2/action/delete.rb +65 -0
  19. data/lib/engine2/action/form.rb +16 -0
  20. data/lib/engine2/{meta/infra_meta.rb → action/infra.rb} +118 -85
  21. data/lib/engine2/action/link.rb +117 -0
  22. data/lib/engine2/{meta/list_meta.rb → action/list.rb} +61 -62
  23. data/lib/engine2/action/save.rb +30 -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 +120 -77
  27. data/lib/engine2/handler.rb +9 -10
  28. data/lib/engine2/model.rb +4 -20
  29. data/lib/engine2/models/Files.rb +2 -1
  30. data/lib/engine2/models/UserInfo.rb +6 -3
  31. data/lib/engine2/post_bootstrap.rb +3 -2
  32. data/lib/engine2/pre_bootstrap.rb +1 -0
  33. data/lib/engine2/scheme.rb +98 -47
  34. data/lib/engine2/templates.rb +1 -0
  35. data/lib/engine2/type_info.rb +6 -4
  36. data/lib/engine2/version.rb +2 -1
  37. data/package.json +12 -10
  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 +0 -0
  42. data/views/fields/bs_select.slim +0 -0
  43. data/views/fields/bsselect_picker.slim +0 -0
  44. data/views/fields/bsselect_picker_opt.slim +0 -0
  45. data/views/fields/checkbox.slim +0 -0
  46. data/views/fields/checkbox_buttons.slim +0 -0
  47. data/views/fields/checkbox_buttons_opt.slim +0 -0
  48. data/views/fields/currency.slim +0 -0
  49. data/views/fields/date.slim +0 -0
  50. data/views/fields/date_range.slim +0 -0
  51. data/views/fields/date_time.slim +0 -0
  52. data/views/fields/datetime.slim +0 -0
  53. data/views/fields/decimal.slim +0 -0
  54. data/views/fields/decimal_date.slim +0 -0
  55. data/views/fields/decimal_time.slim +0 -0
  56. data/views/fields/email.slim +0 -0
  57. data/views/fields/file_store.slim +7 -7
  58. data/views/fields/input_text.slim +0 -0
  59. data/views/fields/integer.slim +0 -0
  60. data/views/fields/list_bsselect.slim +0 -0
  61. data/views/fields/list_bsselect_opt.slim +0 -0
  62. data/views/fields/list_buttons.slim +0 -0
  63. data/views/fields/list_buttons_opt.slim +0 -0
  64. data/views/fields/list_select.slim +0 -0
  65. data/views/fields/list_select_opt.slim +0 -0
  66. data/views/fields/password.slim +0 -0
  67. data/views/fields/radio_checkbox.slim +0 -0
  68. data/views/fields/scaffold.slim +0 -0
  69. data/views/fields/scaffold_picker.slim +0 -0
  70. data/views/fields/select_picker.slim +0 -0
  71. data/views/fields/select_picker_opt.slim +0 -0
  72. data/views/fields/text_area.slim +1 -0
  73. data/views/fields/time.slim +0 -0
  74. data/views/fields/typeahead_picker.slim +0 -0
  75. data/views/index.slim +3 -3
  76. data/views/infra/index.slim +0 -0
  77. data/views/infra/inspect.slim +20 -0
  78. data/views/modals/close_m.slim +0 -0
  79. data/views/modals/confirm_m.slim +0 -0
  80. data/views/modals/empty_m.slim +0 -0
  81. data/views/modals/menu_m.slim +1 -1
  82. data/views/modals/yes_no_m.slim +0 -0
  83. data/views/panels/menu_m.slim +1 -1
  84. data/views/scaffold/confirm.slim +0 -0
  85. data/views/scaffold/fields.slim +0 -0
  86. data/views/scaffold/form.slim +0 -0
  87. data/views/scaffold/form_collapse.slim +0 -0
  88. data/views/scaffold/form_tabs.slim +0 -0
  89. data/views/scaffold/list.slim +0 -0
  90. data/views/scaffold/message.slim +0 -0
  91. data/views/scaffold/search.slim +0 -0
  92. data/views/scaffold/search_collapse.slim +0 -0
  93. data/views/scaffold/search_tabs.slim +0 -0
  94. data/views/scaffold/view.slim +0 -0
  95. data/views/scaffold/view_collapse.slim +0 -0
  96. data/views/scaffold/view_tabs.slim +0 -0
  97. data/views/search_fields/bsmselect_picker.slim +0 -0
  98. data/views/search_fields/bsselect_picker.slim +0 -0
  99. data/views/search_fields/checkbox.slim +0 -0
  100. data/views/search_fields/checkbox2.slim +0 -0
  101. data/views/search_fields/checkbox_buttons.slim +0 -0
  102. data/views/search_fields/date_range.slim +0 -0
  103. data/views/search_fields/decimal_date_range.slim +0 -0
  104. data/views/search_fields/input_text.slim +0 -0
  105. data/views/search_fields/integer.slim +0 -0
  106. data/views/search_fields/integer_range.slim +0 -0
  107. data/views/search_fields/list_bsmselect.slim +0 -0
  108. data/views/search_fields/list_bsselect.slim +0 -0
  109. data/views/search_fields/list_buttons.slim +0 -0
  110. data/views/search_fields/list_select.slim +0 -0
  111. data/views/search_fields/scaffold_picker.slim +0 -0
  112. data/views/search_fields/select_picker.slim +0 -0
  113. data/views/search_fields/typeahead_picker.slim +0 -0
  114. metadata +41 -42
  115. data/lib/engine2/meta.rb +0 -1216
  116. data/lib/engine2/meta/delete_meta.rb +0 -60
  117. data/lib/engine2/meta/form_meta.rb +0 -15
  118. data/lib/engine2/meta/link_meta.rb +0 -134
  119. data/lib/engine2/meta/save_meta.rb +0 -50
  120. data/lib/engine2/meta/view_meta.rb +0 -7
  121. data/public/__sinatra__/404.png +0 -0
  122. data/public/__sinatra__/500.png +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6174073612b4abd1d1a7c2fefbbf071874c2c566
4
- data.tar.gz: 081dee914669d77bb0a9e32d13c219612aa79d75
3
+ metadata.gz: 61ac9190b96b7053391913f8121f1df0bc1967c0
4
+ data.tar.gz: b532a2ca2828607b2068450761cc55a77d43f597
5
5
  SHA512:
6
- metadata.gz: 5631fd58edca95f2c3966ccc240a29b0089c78e7a80b9d3a7e5e239e2a001e0a02f7baa9ed6cdff6a0d98f061022f02d0768282513b457bf6e9fd180c8adf96e
7
- data.tar.gz: bcc3a19a71996a4c2e8f5f2d511354dc1085de8bdd5eacce667cbe1f24a91587dee04892fb22d51276f7a152a4b21c72681e90f379731ad2f1d546f9c5940294
6
+ metadata.gz: 3afb80475e3f7cad3bed23163f0b03f1d54d9268a46749c5e7d9dbc5aa77cbb0859b83592094e50b8178492ff3656a98eb31123be8f56a99962bac033dc20d1a
7
+ data.tar.gz: a7d20b040fd8a85373a9328508710064fa403103b2c661d2d2d71eaec148910397e2d2ddcffb0aea6712eab3bb3bf49943f496e87bd413997d6e25e1d2586bed
data/Gemfile CHANGED
File without changes
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ task :compile_slim do
10
10
  end
11
11
  end
12
12
 
13
- open("app/engine2templates.js", "wb") << <<-EOF
13
+ open("app/templates.js", "wb") << <<-EOF
14
14
  angular.module('Engine2').run(['$templateCache', function($templateCache) {
15
15
  #{slims.join("\n")}
16
16
  }]);
@@ -8,7 +8,7 @@ angular.module('Engine2')
8
8
  throw "Invalid action path: '#{action_attr}'" unless action_names
9
9
  action_names = action_names.split('/') if _.isString(action_names)
10
10
  create = (action) ->
11
- action.create_action_path(action_names, $scope, $element).then (act) -> act.invoke() if $attrs.invoke
11
+ action.create_action_path(action_names, $scope, $element).then (act) -> act.invoke($parse($attrs.invoke)($scope)) if $attrs.invoke?
12
12
 
13
13
  sc = $scope
14
14
  if sc.action
@@ -22,13 +22,13 @@ angular.module('Engine2')
22
22
  $http.get("api/meta").then (mresponse) -> $scope.$broadcast "bootstrap_action",
23
23
  $scope.action = new E2Actions.root(mresponse.data, $scope, null, $element, action_resource: 'api')
24
24
 
25
- .factory 'E2Actions', (E2, $http, $timeout, $e2Modal, $injector, $compile, $templateCache, $q, localStorageService, $route, $window, $rootScope, $location) ->
25
+ .factory 'E2Actions', (E2, $http, $timeout, $injector, $compile, $templateCache, $q, localStorageService, $rootScope, $location, angularLoad, $websocket, MetaCache, $stateRegistry, $urlRouter) ->
26
26
  globals = E2.globals
27
27
  action: class Action
28
28
  constructor: (response, scope, parent, element, action_info) ->
29
29
  @find_action_info = (name, raise = true) ->
30
30
  act = response.actions[name]
31
- throw "Undefined action '#{name}' for action #{@action_info().name} (under #{@parent()?.action_info().action_resource})" if raise && !act
31
+ throw "Undefined action '#{name}' for action #{@parent()?.action_info().action_resource}/#{@action_info().name}" if raise && !act
32
32
  act
33
33
 
34
34
  _.each response.actions, (act, nm) -> act.name = nm
@@ -51,11 +51,12 @@ angular.module('Engine2')
51
51
  @meta.panel.modal_action = false
52
52
  @meta.panel.footer = true unless @meta.panel.footer == false
53
53
 
54
+ @websocket_connect() if @meta.websocket
54
55
  @initialize()
55
56
 
56
57
  initialize: ->
57
58
  @process_static_meta()
58
- console.log "CREATE #{@action_info().action_resource}"
59
+ console.info "CREATE #{@action_info().action_resource}"
59
60
 
60
61
  process_static_meta: ->
61
62
  if @meta.menus
@@ -67,45 +68,22 @@ angular.module('Engine2')
67
68
  if action_info.access
68
69
  $rootScope.$broadcast "relogin", element?, create
69
70
  else
70
- $e2Modal.error("#{err.status}: #{err.data.message}", err.data.cause || err.data.message)
71
+ @globals().modal().error("#{err.status}: #{err.data.message}", err.data.cause || err.data.message)
71
72
  $q.reject(err)
72
73
 
73
- perform_invoke: (params) ->
74
- info = @action_info()
75
- get_invoke = if @meta.invokable == false then $q.when(data: (response: {})) else
76
- (params ?= {}).initial = true if @meta.panel && !@action_invoked && info.method == 'get'
77
- $http[info.method](info.action_resource, if info.method == 'post' then params else (params: params))
78
-
79
- globals.action_pending = if @meta.panel then @ else @parent()
80
-
81
- get_invoke.then (response) =>
82
- if exec = response.data.$execute
83
- @scope().$eval(exec)
84
- delete response.data.$execute
74
+ save_state: () ->
75
+ _.each @meta.state, (s) => localStorageService.set("#{@globals().application}/#{@action_info().action_resource}/#{s}", @[s])
76
+ load_state: () ->
77
+ _.each @meta.state, (s) => _.merge(@[s], localStorageService.get("#{@globals().application}/#{@action_info().action_resource}/#{s}"))
85
78
 
86
- E2.merge(@, response.data)
87
- @process_meta()
88
- (if @meta.reload_routes then $route.load_routes() else $q.when({})).then =>
89
- @arguments = _.keys(response.data)
90
- unless @meta.panel # persistent action
91
- prnt = @parent()
92
- throw "Attempted parent merge for root action: #{info.name}" unless prnt
93
- E2.merge(prnt, response.data)
94
-
95
- globals.action_pending = false
96
- if @meta.panel && !@action_invoked
97
- @action_invoked = true
98
- @panel_render()
99
- ,
100
- (err) =>
101
- globals.action_pending = false
102
- @handle_error(err, info, @element())
79
+ destroy: (e) ->
80
+ console.log "DESTROY #{@action_info().action_resource}"
103
81
 
104
82
  create_action: (name, sc, el) ->
105
83
  info = @find_action_info(name)
106
84
  info.action_resource = "#{@action_info().action_resource}/#{info.name}"
107
85
  get_meta = if !info.terminal || info.meta
108
- $http.get("#{info.action_resource}/meta", cache: true).then (response) =>
86
+ $http.get("#{info.action_resource}/meta", cache: MetaCache).then (response) =>
109
87
  if info.recheck_access
110
88
  $http.get("#{info.action_resource}/meta", params: (access: true, parent_id: @current_id())).then (aresponse) ->
111
89
  response.data.actions[k].access = v for k, v of aresponse.data
@@ -113,7 +91,7 @@ angular.module('Engine2')
113
91
  else response # $q.when ^
114
92
  else $q.when(data: (meta: {}, actions: []))
115
93
  E2A = $injector.get("E2Actions")
116
- get_meta.then (mresponse) => new (E2A[info.meta_type] ? E2A.default_action)(mresponse.data, sc, @, el, info)
94
+ get_meta.then (mresponse) => new (E2A[info.action_type] ? E2A.default_action)(mresponse.data, sc, @, el, info)
117
95
  ,
118
96
  (err) => @handle_error(err, info, el)
119
97
 
@@ -130,26 +108,44 @@ angular.module('Engine2')
130
108
  pre_invoke: ->
131
109
  post_invoke: ->
132
110
 
133
- invoke: (args) ->
134
- @pre_invoke(args)
135
- _.merge(args ?= {}, @meta.arguments) if @meta.arguments
136
- @perform_invoke(args).then =>
137
- @post_invoke(args)
111
+ invoke: (params) ->
112
+ params ?= {}
113
+ @globals().action_pending = if @meta.panel then @ else @parent()
114
+ @pre_invoke(params)
115
+ _.merge(params, @meta.arguments) if @meta.arguments
116
+
117
+ info = @action_info()
118
+ get_invoke = if @meta.invokable == false then $q.when(data: (response: {})) else
119
+ params.initial = true if @meta.panel && !@action_invoked && info.method == 'get'
120
+ $http[info.method](info.action_resource, if info.method == 'post' then params else (params: params))
121
+
122
+ get_invoke.then (response) =>
123
+ @arguments = _.keys(response.data)
124
+ E2.merge(@, response.data)
125
+ @process_meta()
126
+
127
+ promise = if @meta.panel # persistent action
128
+ if !@action_invoked
129
+ @action_invoked = true
130
+ @panel_render()
131
+ else
132
+ prnt = @parent()
133
+ throw "Attempted parent merge for root action: #{info.name}" unless prnt
134
+ E2.merge(prnt, response.data)
135
+
136
+ @post_invoke(params)
138
137
  @scope().$eval(@meta.execute) if @meta.execute
139
138
  if @meta.repeat
140
- unless @meta.destroy_repeat
141
- @scope().$on("$destroy", => delete @meta.repeat)
142
- @meta.destroy_repeat = true
143
- $timeout (=> @invoke(args)), @meta.repeat
144
- @
139
+ @scope().$on "$destroy", => @destroyed = true
140
+ $timeout (=> @invoke(params)), @meta.repeat unless @destroyed
141
+ delete @meta.repeat
145
142
 
146
- save_state: () ->
147
- _.each @meta.state, (s) => localStorageService.set("#{globals.application}/#{@action_info().action_resource}/#{s}", @[s])
148
- load_state: () ->
149
- _.each @meta.state, (s) => _.merge(@[s], localStorageService.get("#{globals.application}/#{@action_info().action_resource}/#{s}"))
150
-
151
- destroy: (e) ->
152
- console.log "DESTROY #{@action_info().action_resource}"
143
+ @globals().action_pending = false
144
+ promise
145
+ ,
146
+ (err) =>
147
+ @globals().action_pending = false
148
+ @handle_error(err, info, @element())
153
149
 
154
150
  panel_render: ->
155
151
  if @meta.panel.modal_action
@@ -161,13 +157,13 @@ angular.module('Engine2')
161
157
  @panel_shown?()
162
158
 
163
159
  else
164
- $e2Modal.show(@)
160
+ @globals().modal().show(@).then => @
165
161
  else
166
162
  @panel_scope?().$destroy()
167
163
  act = @
168
164
  act = act.parent() until act.element()
169
165
  element = act.element() # @element()
170
- is_modal = $e2Modal.is_modal() && !@element()
166
+ is_modal = @globals().modal().is_modal() && !@element()
171
167
  E2.fetch_panel(@meta.panel, is_modal).then (template) =>
172
168
  @panel_show?()
173
169
  # @panel_scope().$destroy()
@@ -190,7 +186,7 @@ angular.module('Engine2')
190
186
  panel_close: ->
191
187
  if @meta.panel.modal_action
192
188
  @modal_hide()
193
- else
189
+ else if @parent().parent()
194
190
  # @parent().panel_refresh()
195
191
  @panel_hide?()
196
192
  @panel_hidden()
@@ -201,12 +197,39 @@ angular.module('Engine2')
201
197
  panel_menu_cancel: ->
202
198
  @panel_close()
203
199
 
200
+ websocket_connect: ->
201
+ l = $location
202
+ ws_meta = @meta.websocket
203
+ ws = $websocket "ws#{l.protocol().slice(4, 5)}://#{l.host()}:#{l.port()}/#{@action_info().action_resource}", undefined, ws_meta.options
204
+ _.each @globals().ws_methods, (method) =>
205
+ ws_method_impl = @["ws_#{method}"]
206
+ ws_method_exec = ws_meta.execute?[method]
207
+ if ws_method_impl || ws_method_exec
208
+ ws_method = (evt) =>
209
+ is_message = method == 'message'
210
+ if is_message
211
+ msg = JSON.parse(evt.data)
212
+ if msg.error then @globals().modal().error("WebSocket [#{evt.origin}] - #{msg.error.method}", msg.error.exception) else
213
+ E2.merge(@, msg)
214
+ @process_meta()
215
+ else msg = evt
216
+ ws_method_impl.bind(@)(msg, ws, evt) if ws_method_impl
217
+ @scope().$eval(ws_method_exec) if ws_method_exec
218
+
219
+ ws["on#{_.capitalize(method)}"](ws_method)
220
+
221
+ @web_socket = -> ws
222
+ @scope().$on "$destroy", -> ws.close()
223
+
204
224
  root: class RootAction extends Action
205
225
  initialize: ->
206
226
  super()
207
227
  _.merge(globals, @meta)
208
228
  @meta = {}
209
229
 
230
+ invoke: (args) ->
231
+ console.warn "Root action invoked"
232
+
210
233
  default_action: class DefaultAction extends Action
211
234
  initialize: ->
212
235
  super()
@@ -217,6 +240,7 @@ angular.module('Engine2')
217
240
  super()
218
241
  @tree = actions: [name: 'api', number: 0, access: true]
219
242
  @invoke_action('models')
243
+ @invoke_action('environment')
220
244
 
221
245
  open: (stack, node, collapsed, expand) ->
222
246
  tree = @tree
@@ -253,64 +277,65 @@ angular.module('Engine2')
253
277
  has_assoc: (model) ->
254
278
  _.size(model.assoc) > 0
255
279
 
280
+ ws_message: (msg, ws, evt) ->
281
+ @event = evt
282
+
256
283
  menu: class MenuAction extends Action
257
284
  process_static_meta: ->
258
285
 
259
286
  initialize: ->
260
287
  super()
261
- $route.load_routes = =>
288
+ $stateRegistry.load_routes = (init) =>
262
289
  @invoke().then =>
263
- _.each _.keys($route.routes), (k) -> delete $route.routes[k]
264
290
  menu = @meta.menus.menu
265
- $route.routes[null] = reloadOnSearch: true, redirectTo: '/' + (menu.properties.default ? menu.entries[0].name)
291
+ _.each $stateRegistry.get(), (s) -> $stateRegistry.deregister(s.name) unless _.isEmpty(s.name)
292
+ otherwise = menu.properties.default ? menu.entries[0].name
293
+ $urlRouter.otherwise(otherwise)
266
294
  @register(menu.entries)
267
- $route.reload() # $location.path('')
268
295
  @scope().routes = menu.entries
269
296
  out = if _.size(menu.entries) == 0 then angular.element("<div></div>") else $compile(@traverse(menu.entries))(@scope())
270
297
  @element().replaceWith(out)
271
298
  @element = -> out
272
- $route.load_routes()
299
+ loc = $location.path().slice(1)
300
+ @globals().state().go(if init && !_.isEmpty($location.path()) && $stateRegistry.get(loc)? then loc else otherwise)
301
+
302
+ $stateRegistry.load_routes(true)
273
303
 
274
304
  register: (routes) ->
275
305
  _.each routes, (route) =>
276
- if route.menu then @register(route.menu.entries) else
277
- name = '/' + route.name
278
- route.href = '#' + route.name
279
- if route.bootstrap?
280
- action = if route.bootstrap == true then '' else route.bootstrap + '/'
281
- $templateCache.put(route.name + '_route_template!', "<div e2-action='' action=\"'#{action}#{route.name}'\" invoke='true'></div>")
282
-
283
- $route.routes[name] =
284
- reloadOnSearch: true
285
- templateUrl: if route.bootstrap? then route.name + '_route_template!' else route.name
286
- originalPath: name
287
- regexp: new RegExp("^#{name}$")
288
- keys: []
289
-
290
- $route.routes[name + '/'] =
291
- redirectTo: name
292
- originalPath: name + '/'
293
- regexp: new RegExp("^#{name}/$")
294
- keys: []
306
+ unless route.divider
307
+ if route.menu then @register(route.menu.entries) else
308
+ route.href = route.name
309
+ if route.bootstrap?
310
+ action = if route.bootstrap == true then '' else route.bootstrap + '/'
311
+ $templateCache.put(route.name + '_route_template!', "<div e2-action='' action=\"'#{action}#{route.name}'\" invoke='true'></div>")
312
+
313
+ $stateRegistry.register
314
+ name: route.name
315
+ templateUrl: if route.bootstrap? then route.name + '_route_template!' else route.name
316
+ url: '/' + route.name
317
+ # reloadOnSearch: true
295
318
 
296
319
  traverse: (routes) ->
297
- menu_tmpl = _.template("<li><a href='{{href}}'>{{icon}}{{aicon}} {{loc}}</a></li>")
298
- menu_sub_tmpl = _.template("<li e2-dropdown='{{dropdown}}' data-animation='{{animation}}'><a href='javascript://'>{{icon}}{{aicon}} {{loc}}<span class='caret'></span></a></li>")
320
+ menu_tmpl = _.template("<li {{show}} {{hide}} ui-sref-active='active'><a {{href}}>{{icon}} {{loc}}</a></li>")
321
+ menu_sub_tmpl = _.template("<li {{show}} {{hide}} e2-dropdown='{{dropdown}}' href-attr='ui-sref' data-animation='{{animation}}'><a href='javascript://'>{{icon}} {{loc}}<span class='caret'></span></a></li>")
299
322
  animation = @meta.menus.menu.properties.animation
300
323
  out = routes.map (route, i) ->
301
324
  if route.menu
302
325
  menu_sub_tmpl
303
326
  dropdown: "routes[#{i}].menu.entries"
304
327
  animation: animation
305
- icon: route.menu.icon && E2.icon(route.menu.icon) || ""
306
- aicon: route.menu.aicon && E2.aicon(route.menu.aicon) || ""
307
328
  loc: route.menu.loc
329
+ show: route.show && "ng-show=\"#{route.show}\"" || ''
330
+ hide: route.hide && "ng-hide=\"#{route.hide}\"" || ''
331
+ icon: route.menu.icon && E2.icon(route.menu.icon) || ""
308
332
  else
309
333
  menu_tmpl
310
- href: route.href
334
+ href: "ui-sref='#{route.name}'"
311
335
  loc: route.loc
336
+ show: route.show && "ng-show=\"#{route.show}\"" || ''
337
+ hide: route.hide && "ng-hide=\"#{route.hide}\"" || ''
312
338
  icon: route.icon && E2.icon(route.icon) || ''
313
- aicon: route.aicon && E2.aicon(route.aicon) || ''
314
339
  out.join('')
315
340
 
316
341
  list: class ListAction extends Action
@@ -322,7 +347,6 @@ angular.module('Engine2')
322
347
 
323
348
  delete @query.order unless @meta.info[@query.order]?.sort # _.includes(@meta.fields, @query.order)
324
349
  _.each @query.search, ((sv, sn) => delete @query.search[sn] unless _.includes(@meta.search_fields, sn))
325
- # $window.addEventListener 'beforeunload', (e, v) => @save_state()
326
350
 
327
351
  destroy: ->
328
352
  @save_state()
@@ -351,7 +375,7 @@ angular.module('Engine2')
351
375
  @scope().$broadcast 'render_table'
352
376
 
353
377
  menu_show_meta: ->
354
- $e2Modal.show
378
+ @globals().modal().show
355
379
  the_meta: @meta
356
380
  meta: panel: (panel_template: "close_m", template_string: "<pre>{{action.the_meta | json}}</pre>", title: "Meta", class: "modal-huge", backdrop: true, footer: true)
357
381
 
@@ -469,7 +493,6 @@ angular.module('Engine2')
469
493
  @panel_shown()
470
494
 
471
495
  @["panel_menu_#{@default_action_name}"] = -> @panel_menu_default_action()
472
- @scope().$on "return_pressed", (e) => @panel_menu_default_action()
473
496
 
474
497
  post_invoke: (args) ->
475
498
  super()
@@ -505,9 +528,8 @@ angular.module('Engine2')
505
528
  @alert = @errors if (!field || !@meta.info[field] || @meta.info[field].hidden) # ?
506
529
  $timeout => @scope().$broadcast("focus_field", field)
507
530
  #e.scope.$eval(meta.execute) if meta.execute # ?
508
- dfd.reject(@errors)
531
+ dfd.resolve()
509
532
  else
510
- @panel_close()
511
533
  dfd.resolve(@record) # $q.when(true) ?
512
534
  dfd.promise
513
535
 
@@ -533,30 +555,31 @@ angular.module('Engine2')
533
555
  act.meta.info.name.disabled = true
534
556
  act.dont_reload_routes = !reload_routes # true
535
557
  else
536
- @invoke().then => @set_access(true, true)
558
+ @invoke().then => @set_access(true, true, @user)
537
559
 
538
- set_access: (login, load_routes) ->
539
- @find_action_info('logout_form').access = login
540
- @find_action_info('inspect_modal').access = login
541
- @find_action_info('login_form').access = !login
542
- $route.load_routes() if load_routes
560
+ @scope().$on "set_access", (evt, login, load_routes, user) => @set_access(login, load_routes, user)
561
+
562
+ set_access: (login, load_routes, user) ->
563
+ if user || !login
564
+ @user = user
565
+ @find_action_info('logout_form').access = login
566
+ @find_action_info('inspect_modal').access = login
567
+ @find_action_info('login_form').access = !login
568
+ $stateRegistry.load_routes() if load_routes
543
569
 
544
570
  login_form: class LoginFormAction extends FormBaseAction
545
571
  panel_menu_default_action: ->
546
572
  super().then =>
547
- @parent().user = @user
548
- @parent().set_access(true, !@dont_reload_routes)
573
+ $rootScope.$broadcast "set_access", true, !@dont_reload_routes, @user
549
574
 
550
575
  logout_form: class LogoutForm extends Action
551
576
  panel_menu_logout: ->
552
577
  @invoke_action('logout').then =>
553
- @parent().user = null
554
- @parent().set_access(false, true)
578
+ $rootScope.$broadcast "set_access", false, true, null
555
579
  @panel_close()
580
+ MetaCache.removeAll()
556
581
 
557
582
  form: class FormAction extends FormBaseAction
558
- panel_menu_default_action: ->
559
- super().then => @parent().invoke()
560
583
 
561
584
  create: class CreateAction extends FormAction
562
585
  invoke: (args) ->
@@ -578,10 +601,7 @@ angular.module('Engine2')
578
601
  confirm: class ConfirmAction extends Action
579
602
  panel_menu_approve: ->
580
603
  @initial_arguments ?= @arguments
581
- @invoke_action(@default_action_name, _.pick(@, @initial_arguments)).then (act) =>
582
- unless @errors
583
- @parent().invoke()
584
- @panel_close()
604
+ @invoke_action(@default_action_name, _.pick(@, @initial_arguments))
585
605
 
586
606
  decode_action: class DecodeAction extends Action
587
607
  initialize: ->
@@ -606,8 +626,7 @@ angular.module('Engine2')
606
626
  @parentp().search_field_change?(@decode_field)
607
627
 
608
628
  decode_description: (entry) ->
609
- fields = @meta.decode_fields ? @meta.fields
610
- fields.map((f) => E2.render_field(entry, f, @meta)).join(@meta.separator)
629
+ @meta.decode_fields.map((f) => E2.render_field(entry, f, @meta)).join(@meta.separator)
611
630
 
612
631
  parentp: ->
613
632
  @parent().parent()
@@ -675,7 +694,7 @@ angular.module('Engine2')
675
694
  else
676
695
  decode_descriptions = (recs) => @decode = recs.map((fields) => @decode_description(fields)).join(' | ')
677
696
  recs = recs.map (r) => if _.isArray(r) then E2.from_id(r, @meta) else r
678
- if _(recs).every((r) => _(@meta.fields).every((f) -> r[f]?)) then decode_descriptions(recs) else
697
+ if _(recs).every((r) => _(@meta.fields).every((f) -> r[f]?)) && !@meta.dynamic_meta then decode_descriptions(recs) else
679
698
  @invoke(ids: [recs.map((r) => @meta.primary_fields.map (k) -> r[k])]).then => decode_descriptions(@entries)
680
699
 
681
700
  open: ->
@@ -743,8 +762,9 @@ angular.module('Engine2')
743
762
  @query.parent_id = @parent().current_id()
744
763
 
745
764
  # link_list: implicit
746
- item_menu_confirm_unlink: (index) ->
747
- @invoke_action('confirm_unlink', id: E2.id_for(@entries[index], @meta), parent_id: @query.parent_id)
765
+ item_menu_confirm_unlink: (args) ->
766
+ args.parent_id = @query.parent_id
767
+ @item_menu_confirm_unlink_super(args)
748
768
 
749
769
  star_to_many_bulk_unlink: class StarToManyBulkUnlinkAction extends Action
750
770
  invoke: ->
@@ -762,26 +782,63 @@ angular.module('Engine2')
762
782
  panel_menu_link: ->
763
783
  selection = _.keys(@selection)
764
784
  if selection.length > 0
765
- @invoke_action('link', parent_id: @query.parent_id, ids: selection).then (act) =>
766
- unless @errors
767
- @parent().invoke()
768
- @panel_close()
785
+ @invoke_action('link', parent_id: @query.parent_id, ids: selection)
769
786
 
770
787
  star_to_many_field: class StarToManyField extends ListAction
771
788
  initialize: ->
772
789
  super()
773
790
  @query.parent_id = E2.id_for(@parent().record, @parent().meta)
774
- links = @parent().record[@scope().$parent.f]
775
- @links = links ? (linked: [], unlinked: [])
791
+ @changes = (@parent().record[@scope().$parent.f] ?= (link: [], unlink: [], create: [], modify: [], delete: []))
776
792
  @invoke()
777
793
 
778
794
  invoke: ->
779
- @query.unlinked = [@links.unlinked]
780
- @query.linked = [@links.linked]
795
+ @query.changes = @changes
781
796
  super()
782
797
 
783
- sync_record: ->
784
- @parent().record[@scope().$parent.f] = @links
798
+ current_entry_is: (mode) ->
799
+ key = E2.id_for(@current_entry(), @meta)
800
+ _.find(@changes[mode], (e) => E2.id_for(e, @meta) == key)
801
+
802
+ star_to_many_field_view: class StarToManyFieldView extends ViewAction
803
+ invoke: (args) ->
804
+ if entry = @parent().current_entry_is('create') ? @parent().current_entry_is('modify')
805
+ @meta.invokable = false
806
+ @record = entry
807
+ super(args)
808
+
809
+ star_to_many_field_modify: class StarToManyFieldModifyAction extends ModifyAction
810
+ invoke: (args) ->
811
+ if entry = @parent().current_entry_is('create') ? @parent().current_entry_is('modify')
812
+ @meta.invokable = false
813
+ @record = entry
814
+ super(args)
815
+
816
+ star_to_many_field_approve: class StarToManyFieldApprove extends Action
817
+ post_invoke: (args) ->
818
+ super(args)
819
+ unless @errors
820
+ pparent = @parent().parent()
821
+ if @parent() instanceof StarToManyFieldModifyAction
822
+ if entry = pparent.current_entry_is('create') ? pparent.current_entry_is('modify')
823
+ _.assign(entry, @parent().record)
824
+ else
825
+ pparent.changes.modify.push @parent().record
826
+ else # CreateAction
827
+ _(@parent().meta.primary_fields).each (k) => @parent().record[k] = E2.uuid(5)
828
+ pparent.changes.create.push @parent().record
829
+
830
+ star_to_many_field_delete: class StarToManyFieldDelete extends Action
831
+ invoke: (args) ->
832
+ pparent = @parent().parent()
833
+ if entry = pparent.current_entry_is('create')
834
+ _.remove(pparent.changes.create, entry)
835
+ else if entry = pparent.current_entry_is('modify')
836
+ _.remove(pparent.changes.modify, entry)
837
+ pparent.changes.delete.push args.id
838
+ else
839
+ pparent.changes.delete.push args.id
840
+ @meta.invokable = false
841
+ super(args)
785
842
 
786
843
  star_to_many_field_link_list: class StarToManyFieldLinkList extends ListAction
787
844
  initialize: ->
@@ -791,57 +848,50 @@ angular.module('Engine2')
791
848
  @selection = {}
792
849
 
793
850
  invoke: ->
794
- @query.unlinked = [@parent().links.unlinked]
795
- @query.linked = [@parent().links.linked]
851
+ @query.changes = @parent().changes
796
852
  super()
797
853
 
798
854
  panel_menu_link: ->
799
855
  if @selected_size() > 0
800
856
  _.each @selection, (v, k) =>
801
857
  id = k
802
- if _.includes(@parent().links.unlinked, id) then _.pull(@parent().links.unlinked, id) else @parent().links.linked.push id
858
+ if _.includes(@parent().changes.unlink, id) then _.pull(@parent().changes.unlink, id) else @parent().changes.link.push id
803
859
  @parent().invoke()
804
- @parent().sync_record()
805
860
  @panel_close()
806
861
 
807
862
  star_to_many_field_unlink: class StarToManyFieldUnlink extends Action
808
863
  invoke: (args) ->
809
864
  id = args.id
810
865
  pparent = @parent().parent()
811
- if _.includes(pparent.links.linked, id) then _.pull(pparent.links.linked, id) else pparent.links.unlinked.push id
812
- pparent.sync_record()
866
+ if _.includes(pparent.changes.link, id) then _.pull(pparent.changes.link, id) else pparent.changes.unlink.push id
867
+ @meta.invokable = false
868
+ super(args)
813
869
 
814
870
  file_store: class FileStoreAction extends Action
815
871
  initialize: ->
816
872
  super()
817
873
  @progress = 0
818
874
  id = E2.id_for(@parent().record, @parent().meta)
819
- if id.length > 0
820
- @invoke(owner: id).then => @sync_record()
821
- else
822
- @files = []
823
- @sync_record()
824
-
825
- sync_record: ->
826
- @parent().record[@scope().f] = @files
875
+ files = @parent().record[@scope().f]
876
+ @invoke(owner: id).then =>
877
+ @parent().record[@scope().f] = if files? then files else @files
878
+ delete @files
827
879
 
828
880
  select: (files) ->
829
881
  _.each files, (file) =>
830
882
  upload = $injector.get('Upload').upload url: "#{@action_info().action_resource}/upload", file: file
831
883
  upload.progress (e) =>
832
- globals.action_pending = false
884
+ @globals().action_pending = false
833
885
  @progress = parseInt(100.0 * e.loaded / e.total)
834
886
  upload.success (data, status, headers, config) =>
835
- @files.push mime: file.type, name: file.name, rackname: data.rackname, id: data.id
887
+ @parent().record[@scope().f].push mime: file.type, name: file.name, rackname: data.rackname, id: data.id, new: true
836
888
  @message = "Wysłano, #{file.name}"
837
- globals.action_pending = false
838
- @sync_record()
889
+ @globals().action_pending = false
839
890
 
840
891
  delete_file: (file) ->
841
892
  @scope().$broadcast 'confirm_delete',
842
893
  confirm: =>
843
- @sync_record()
844
- file.deleted = true
894
+ if file.new then _.pull(@parent().record[@scope().f], file) else file.deleted = true
845
895
  @scope().$broadcast 'confirm_delete_close'
846
896
 
847
897
  show_file: (file) ->