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
File without changes
@@ -61,6 +61,10 @@ tr.tr_hover {
61
61
  font-weight:normal;
62
62
  }
63
63
 
64
+ textarea {
65
+ white-space: nowrap;
66
+ }
67
+
64
68
  /*.modal-backdrop{
65
69
  position:fixed;
66
70
  top:0;
@@ -1,34 +1,55 @@
1
1
  'use strict'
2
- require 'angular-route'
3
2
  require 'angular-sanitize'
4
3
  require 'angular-animate'
5
4
  require 'angular-cookies'
6
5
  require 'angular-local-storage'
7
6
  require 'angular-ui-tree'
7
+ require '@uirouter/angularjs'
8
8
  require 'ng-file-upload'
9
+ require 'angular-load'
9
10
 
10
11
  _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
11
12
 
12
- angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStrap', 'ngFileUpload', 'ui.tree', 'LocalStorageModule']) # 'draggabilly'
13
- .config ($httpProvider, $routeProvider, $compileProvider, localStorageServiceProvider, $logProvider) ->
14
- loaderOn = -> angular.element(document.querySelectorAll('.loader')).eq(-1).css("visibility", 'visible')
13
+ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStrap', 'ngFileUpload', 'ui.tree', 'LocalStorageModule', 'angularLoad', 'ngWebSocket', 'ui.router']) # 'draggabilly'
14
+ .config ($httpProvider, $compileProvider, localStorageServiceProvider, $logProvider, $qProvider, $locationProvider, $provide) ->
15
15
  $httpProvider.interceptors.push 'e2HttpInterceptor'
16
- $httpProvider.defaults.transformRequest.push (data, headersGetter) ->
17
- loaderOn()
18
- data
16
+ $provide.decorator '$httpBackend', ($delegate) ->
17
+ (method, url, post, callback, headers, timeout, withCredentials, responseType) ->
18
+ url = url.replace(/;/g, '%3B') unless method == 'POST'
19
+ $delegate(method, url, post, callback, headers, timeout, withCredentials, responseType)
19
20
  # $httpProvider.defaults.headers.common['Cache-Control'] = 'no-cache'
20
21
  # $httpProvider.defaults.cache = false;
21
- $httpProvider.defaults.headers.get ||= {} # if !$httpProvider.defaults.headers.get
22
+ $httpProvider.defaults.headers.get ?= {} # if !$httpProvider.defaults.headers.get
22
23
  $httpProvider.defaults.headers.get['If-Modified-Since'] = '0'
23
24
  # localStorageServiceProvider.setStorageType('sessionStorage')
24
25
  localStorageServiceProvider.setPrefix('E2')
25
26
  $compileProvider.debugInfoEnabled(false)
26
27
  $logProvider.debugEnabled(true)
27
28
  $httpProvider.useApplyAsync(true)
28
- # $locationProvider.html5Mode(true);
29
+ # $qProvider.errorOnUnhandledRejections(false)
30
+ # $locationProvider.hashPrefix('')
31
+ # $locationProvider.html5Mode(false)
29
32
 
33
+ .factory 'PushJS', -> require 'push.js'
34
+ .factory 'MetaCache', ($cacheFactory) -> $cacheFactory('MetaCache')
30
35
  .factory 'e2HttpInterceptor', ($q, $injector, E2Snippets) ->
31
- loaderOff = -> angular.element(document.querySelectorAll('.loader')).eq(-1).css("visibility", 'hidden')
36
+ loaderToggle = (toggle) -> angular.element(document.querySelectorAll('.loader')).eq(-1).css("visibility", toggle)
37
+ loaderOn = -> loaderToggle('visible')
38
+ timeout = null
39
+ loaderOff = ->
40
+ if timeout
41
+ clearTimeout timeout
42
+ timeout = null
43
+ loaderToggle('hidden')
44
+
45
+ request: (request) ->
46
+ if timeout
47
+ clearTimeout timeout
48
+ timeout = null
49
+ else
50
+ timeout = setTimeout(loaderOn, 200)
51
+ request
52
+
32
53
  response: (response) ->
33
54
  loaderOff()
34
55
  response
@@ -47,21 +68,37 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
47
68
  $q.reject(response)
48
69
 
49
70
  .factory 'E2Snippets', ->
50
- icon = (name) -> "<span class='glyphicon glyphicon-#{name}'></span>"
51
- aicon = (name) -> "<i class='fa fa-#{name}'></i>"
71
+ icon = (name) ->
72
+ if name.slice(0, 3) == 'fa_'
73
+ "<i class='fa fa-#{name.slice(3)}'></i>"
74
+ else
75
+ "<span class='glyphicon glyphicon-#{name}'></span>"
76
+
52
77
  ng_class_names = ['active', 'enabled', 'disabled']
53
78
  icon: icon
54
- aicon: aicon
55
79
  boolean_true_value: icon('check')
56
80
  boolean_false_value: icon('unchecked')
57
81
  make_ng_class: (o) ->
58
82
  out = []
59
83
  _.each ng_class_names, (e) -> out.push(if e == 'enabled' then "'disabled': !(#{o[e]})" else "'#{e}': #{o[e]}") if o[e]?
60
- _.each(o.class, (v, k) -> out.push "#{k}: #{v}") if o.class?
84
+ _.each(o.class, (v, k) -> out.push "'#{k}': #{v}") if o.class?
61
85
  if out.length > 0 then "ng-class=\"{#{out.join(',')}}\"" else ""
62
86
 
63
- .factory 'E2', ($templateCache, $http, E2Snippets, $e2Modal, $q, $injector, e2HttpInterceptor, $route, $dateFormatter, $parse) ->
64
- globals: {}
87
+ .factory 'E2', ($templateCache, $http, E2Snippets, $q, $dateFormatter, $parse, PushJS, $state, $e2Modal) ->
88
+ globals:
89
+ element: (id) ->
90
+ element = document.querySelector(id)
91
+ console.warn "Element #{id} not found" unless element
92
+ element
93
+
94
+ notification: (name, body, icon, timeoutx, on_close) ->
95
+ PushJS.create name, body: body, icon: icon, timeout: timeoutx, onClick: on_close
96
+
97
+ state: -> $state
98
+ modal: -> $e2Modal
99
+
100
+ uuid: (length) ->
101
+ Math.random().toString(36).substring(length)
65
102
 
66
103
  compact: (o) ->
67
104
  _.each o, (v, k) =>
@@ -80,13 +117,12 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
80
117
 
81
118
  merge: (dst, src) ->
82
119
  for k, v of src
120
+ throw "Attempted to override function '#{k}'" if _.isFunction(dst[k])
121
+ insn = k.slice(-1)
83
122
  if _.isObject(v) && !_.isArray(v)
84
- if k.slice(-1) == '!'
85
- dst[k.slice(0, -1)] = v
86
- else
87
- dst[k] = @merge(dst[k] ? {}, v)
123
+ if insn == '!' then dst[k.slice(0, -1)] = v else dst[k] = @merge(dst[k] ? {}, v)
88
124
  else
89
- dst[k] = v
125
+ if insn == '?' then dst[k.slice(0, -1)] ?= v else dst[k] = v
90
126
  dst
91
127
 
92
128
  transpose: (a) ->
@@ -98,7 +134,6 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
98
134
  from_id: (id, meta) -> _.zipObject(meta.primary_fields, id) # _.zip(meta.primary_fields, id).reduce(((rec, [k, v]) -> rec[k] = v; rec), {})
99
135
 
100
136
  icon: E2Snippets.icon
101
- aicon: E2Snippets.aicon
102
137
 
103
138
  fetch_template: (template) ->
104
139
  $q.when($templateCache.get(template) || $http.get(template)).then (res) ->
@@ -137,11 +172,21 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
137
172
  processor.arg_fun(action, arg)
138
173
  action.scope().$eval(click)
139
174
  else
140
- action[fun_name] ?= (arg) ->
141
- processor.arg_fun(action, arg)
142
- args = processor.arg_ret(action)
143
- _.merge(args, $parse(m.arguments)(action.scope())) if m.arguments?
144
- action.invoke_action(m.name, args)
175
+ if ofun = action[fun_name]
176
+ action["#{fun_name}_super"] = (args) ->
177
+ _.merge(args, $parse(m.arguments)(action.scope())) if m.arguments?
178
+ action.invoke_action(m.name, args)
179
+
180
+ action[fun_name] = (args) ->
181
+ processor.arg_fun(action, args)
182
+ args = processor.arg_ret(action)
183
+ ofun.bind(action)(args)
184
+ else
185
+ action[fun_name] = (arg) ->
186
+ processor.arg_fun(action, arg)
187
+ args = processor.arg_ret(action)
188
+ _.merge(args, $parse(m.arguments)(action.scope())) if m.arguments?
189
+ action.invoke_action(m.name, args)
145
190
 
146
191
  if action.find_action_info(m.name, false)?
147
192
  show = if m.show then " && " + m.show else ""
@@ -206,138 +251,6 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
206
251
  parser = @parsers[info.type]
207
252
  if parser then parser(value, info) else value
208
253
 
209
- .provider '$e2Modal', ->
210
- $get: ($rootScope, $modal, $timeout, $window, $injector) ->
211
- class MManager
212
- @Z_INDEX: 1050
213
- @index: 0
214
- constructor: () ->
215
- backdrop_z_index: (num, index) -> angular.element(document.querySelectorAll('.modal-backdrop')).eq(num).css('z-index', index)
216
- modal_num: (num) -> angular.element(document.querySelectorAll('.modal')).eq(num)
217
- backdrop: (bdr) -> bdr ? 'static'
218
- show_before: ->
219
- @z_index = MManager.Z_INDEX + MManager.index * 2
220
- @modal.css('z-index', @z_index + 1)
221
- hide_before: ->
222
- @z_index = MManager.Z_INDEX + ((MManager.index - 1) * 2)
223
- show: ->
224
- hide: -> angular.element($window.document.body).addClass('modal-open modal-with-am-fade') if MManager.index > 0
225
-
226
- class DefaultMManager extends MManager
227
- show_before: ->
228
- super()
229
- @backdrop.css('z-index', @z_index) # @backdrop_z_index(-MManager.index - 1, z_index)
230
-
231
- class FirstMManager extends MManager
232
- constructor: () ->
233
- super()
234
- @threshold = 2
235
- backdrop: (bdr) -> if MManager.index > @threshold then false else super(bdr)
236
- show_before: ->
237
- super()
238
- if MManager.index > @threshold
239
- @modal_num((MManager.index - 1) - @threshold).css('display', 'none')
240
- @backdrop_z_index(0, @z_index)
241
- else
242
- @backdrop.css('z-index', @z_index) # @backdrop_z_index(-MManager.index - 1, z_index)
243
-
244
- hide_before: ->
245
- super()
246
- if MManager.index > @threshold
247
- @backdrop_z_index(0, @z_index)
248
- @modal_num((MManager.index - 1) - @threshold).css('display', 'block')
249
-
250
- class SingleBackdropMManager extends MManager
251
- backdrop: (bdr) -> if MManager.index > 0 then false else super(bdr)
252
- show_before: ->
253
- super()
254
- @backdrop_z_index(0, @z_index)
255
- hide_before: ->
256
- super()
257
- @backdrop_z_index(0, @z_index)
258
-
259
- is_modal: -> MManager.index > 0
260
-
261
- show: (action) ->
262
- scope = if action.scope then action.scope().$new(true) else $rootScope.$new()
263
- scope.action = action
264
- manager = new SingleBackdropMManager()
265
-
266
- scope.$on 'modal.show.before', (e, m) ->
267
- e.stopPropagation()
268
- manager.modal = m.$element
269
- manager.backdrop = m.$backdrop
270
- throw "Modal has element" if action.element?()
271
- action.element = -> m.$element
272
- action.panel_show?()
273
- manager.show_before()
274
- MManager.index++
275
-
276
- scope.$on 'modal.show', (e, m) ->
277
- e.stopPropagation()
278
- manager.show()
279
- action.panel_shown?()
280
-
281
- scope.$on 'modal.hide.before', (e) ->
282
- e.stopPropagation()
283
- MManager.index--
284
- manager.hide_before()
285
- action.panel_hide?()
286
-
287
- scope.$on 'modal.hide', (e) ->
288
- e.stopPropagation()
289
- manager.hide()
290
- action.panel_hidden?()
291
- scope.$destroy()
292
-
293
- $injector.get('E2').fetch_panel(action.meta.panel, true).then (template) ->
294
- modal = $modal
295
- scope: scope
296
- show: false
297
- template: template
298
- backdrop: manager.backdrop(action.meta.panel.backdrop)
299
- animation: action.meta.panel.animation ? 'am-fade'
300
-
301
- action.modal_hide = -> modal.$scope.$hide()
302
- modal.$promise.then ->
303
- modal.show()
304
- modal
305
-
306
- error: (title, msg, html) ->
307
- body = if html then msg else "<div class='alert alert-danger'>#{msg}</div>"
308
- clazz = if html then "modal-huge" else "modal-large"
309
- @show meta: panel: (panel_template: "close_m", template_string: body, title: title, class: clazz, footer: true) # message: msg,
310
-
311
- confirm: (title, msg, action) ->
312
- body = "<div class='alert alert-warning'>#{msg}</div>"
313
- clazz = "modal-large"
314
- @show
315
- confirm: action,
316
- meta: panel: (panel_template: "confirm_m", template_string: body, title: title, class: clazz, footer: true) # message: msg,
317
-
318
- .directive 'e2Modal', ($e2Modal) ->
319
- restrict: 'E'
320
- # replace: true
321
- # transclude: true
322
- scope: true
323
- compile: (celem, cattr) ->
324
- obody = celem[0].children[0]
325
- celem.empty() if obody
326
- (scope, elem, attrs) ->
327
- scope.$on attrs.name, (ev, args) ->
328
- return if ev.defaultPrevented
329
- ev.preventDefault()
330
-
331
- panel = panel_template: attrs.panelTemplate, title: attrs.title, class: attrs.clazz, footer: true
332
- if obody then panel.template_string = obody.outerHTML else panel.template = attrs.template
333
- action = meta: (panel: panel), scope: -> scope
334
- _.assign(action, args)
335
-
336
- modal = $e2Modal.show(action)
337
- hide_off = scope.$on "#{attrs.name}_close", ->
338
- hide_off()
339
- modal.then (m) -> m.$scope.$hide()
340
-
341
254
  .directive 'e2Field', ($timeout, $filter) ->
342
255
  require: 'ngModel'
343
256
  restrict: 'A'
@@ -360,8 +273,8 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
360
273
  if elem[0].type in ['text', 'password']
361
274
  elem.on 'keypress', (ev) ->
362
275
  scope.$apply ->
363
- # scope.action.panel_menu_save() if ev.keyCode == 13 # && elem[0].type != 'textarea'
364
- scope.$emit "return_pressed" if ev.keyCode == 13 # && elem[0].type != 'textarea'
276
+ scope.action.panel_menu_default_action() if ev.keyCode == 13
277
+
365
278
  ev.stopPropagation()
366
279
 
367
280
  if info.filter
@@ -397,11 +310,11 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
397
310
  scope: false
398
311
  link: (scope, elem, attrs) ->
399
312
  name = $parse(attrs.template)(scope)
400
- $http.get(name, cache: $templateCache).success (body) ->
313
+ $http.get(name, cache: $templateCache).then (response) ->
401
314
  # elem.html($compile(body)(scope))
402
315
  # elem.replaceWith($compile(body)(scope))
403
316
  elem.empty()
404
- elem.after($compile(body)(scope))
317
+ elem.after($compile(response.data)(scope))
405
318
 
406
319
  .directive 'e2TableBody', ($parse, $compile) ->
407
320
  table_tmpl = _.template("<thead><tr>{{thead}}</tr></thead><tbody>{{tbody}}</tbody>")
@@ -453,10 +366,10 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
453
366
 
454
367
  .directive 'e2Dropdown', ($parse, $dropdown, $timeout, E2Snippets) ->
455
368
  event_num = 0
456
- dropdown_sub_tmpl = _.template("<li class='dropdown-submenu'><a href=''> {{icon}}{{aicon}} {{loc}}</a>{{sub}}</li>")
457
- dropdown_tmpl = _.template("<li {{clazz}} {{show}} {{hide}}> <a href='{{href}}' {{click}}> {{icon}}{{aicon}} {{loc}}</a></li>")
369
+ dropdown_sub_tmpl = _.template("<li class='dropdown-submenu' {{show}} {{hide}}><a href=''> {{icon}} {{loc}}</a>{{sub}}</li>")
370
+ dropdown_tmpl = _.template("<li {{clazz}} {{show}} {{hide}}> <a {{href}} {{click}}> {{icon}} {{loc}}</a></li>")
458
371
 
459
- render = (menu, level) ->
372
+ render = (menu, href) ->
460
373
  out = menu.map (m) ->
461
374
  switch
462
375
  when m.divider
@@ -464,18 +377,18 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
464
377
  when m.menu
465
378
  dropdown_sub_tmpl
466
379
  icon: m.menu.icon && E2Snippets.icon(m.menu.icon) || ''
467
- aicon: m.menu.aicon && E2Snippets.aicon(m.menu.aicon) || ''
468
380
  loc: m.menu.loc
381
+ show: m.menu.show && "ng-show=\"#{m.menu.show}\"" || ''
382
+ hide: m.menu.hide && "ng-hide=\"#{m.menu.hide}\"" || ''
469
383
  sub: render(m.menu.entries)
470
384
  else
471
385
  dropdown_tmpl
472
386
  clazz: E2Snippets.make_ng_class(m)
473
387
  show: m.show && "ng-show=\"#{m.show}\"" || ''
474
388
  hide: m.hide && "ng-hide=\"#{m.hide}\"" || ''
475
- href: m.href || ''
389
+ href: m.href && "#{href}=\"#{m.href}\"" || ''
476
390
  click: m.click && "ng-click=\"#{m.click}\"" || ''
477
391
  icon: m.icon && E2Snippets.icon(m.icon) || ''
478
- aicon: m.aicon && E2Snippets.aicon(m.aicon) || ''
479
392
  loc: m.loc
480
393
  "<ul class='dropdown-menu'>#{out.join('')}</ul>"
481
394
 
@@ -489,7 +402,8 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
489
402
  # event.preventDefault()
490
403
  # event.stopPropagation()
491
404
  menu = $parse(attrs.e2Dropdown)(scope)
492
- dropdown = $dropdown(elem, (scope: scope, template: render(menu, 0), animation: attrs.animation || 'am-flip-x', prefixEvent: "#{event_num}.tooltip")) # , delay: 1
405
+ href = attrs.hrefAttr ? 'href'
406
+ dropdown = $dropdown(elem, (scope: scope, template: render(menu, href), animation: attrs.animation || 'am-flip-x', prefixEvent: "#{event_num}.tooltip")) # , delay: 1
493
407
  dropdown.$promise.then ->
494
408
  event_hide = scope.$on "#{event_num}.tooltip.hide", (e) ->
495
409
  e.stopPropagation()
@@ -505,8 +419,8 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
505
419
  elem.on "mousedown", hook
506
420
 
507
421
  .directive 'e2ButtonSet', ($parse, $compile, E2Snippets) ->
508
- button_set_tmpl = _.template("<div class='btn btn-default' {{clazz}} {{click}} {{show}} {{hide}} {{title}}> {{icon}}{{aicon}} {{loc}}</div>")
509
- button_set_arr_tmpl = _.template("<div class='btn btn-default' e2-dropdown='{{dropdown}}' data-animation='{{animation}}'>{{icon}}{{aicon}}<span class='caret'></span></div>")
422
+ button_set_tmpl = _.template("<div class='btn btn-default' {{clazz}} {{click}} {{show}} {{hide}} {{title}}> {{icon}} {{loc}}</div>")
423
+ button_set_arr_tmpl = _.template("<div class='btn btn-default' e2-dropdown='{{dropdown}}' data-animation='{{animation}}'>{{icon}}<span class='caret'></span></div>")
510
424
  scope: true # because $index
511
425
  link: (scope, elem, attrs) ->
512
426
  menu = $parse(attrs.e2ButtonSet)(scope)
@@ -523,7 +437,6 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
523
437
  dropdown: "#{attrs.e2ButtonSet}.entries[#{i}].menu.entries"
524
438
  animation: animation
525
439
  icon: m.menu.icon && "#{E2Snippets.icon(m.menu.icon)}&nbsp;" || ''
526
- aicon: m.menu.aicon && "#{E2Snippets.aicon(m.menu.aicon)}&nbsp;" || ''
527
440
  else if m.divider
528
441
  else
529
442
  out += button_set_tmpl
@@ -532,7 +445,6 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
532
445
  show: m.show && "ng-show=\"#{m.show}\"" || ''
533
446
  hide: m.hide && "ng-hide=\"#{m.hide}\"" || ''
534
447
  icon: m.icon && E2Snippets.icon(m.icon) || ''
535
- aicon: m.aicon && E2Snippets.aicon(m.aicon) || ''
536
448
  loc: !(m.button_loc == false) && m.loc || ''
537
449
  title: (m.button_loc == false) && "title=\"#{m.loc}\"" || ''
538
450
 
@@ -541,12 +453,12 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
541
453
  dropdown: "#{attrs.e2ButtonSet}.entries.slice(#{brk})"
542
454
  animation: animation
543
455
  icon: ''
544
- aicon: ''
545
456
 
546
457
  out = "<div class='btn-group #{group_class}'>#{out}</div>"
547
458
  out = $compile(angular.element(out))(scope)
548
459
  if attrs.index && !scope.$index?
549
460
  scope.$index = attrs.index | 0
461
+ scope.$entry = scope.action.entries[scope.$index]
550
462
  # scope.data = attrs.data
551
463
  elem.after(out) # elem.append(out) # elem.replaceWith(out)
552
464
 
@@ -0,0 +1,133 @@
1
+ 'use strict'
2
+ angular.module('Engine2')
3
+ .provider '$e2Modal', ->
4
+ $get: ($rootScope, $modal, $timeout, $window, $injector) ->
5
+ class MManager
6
+ @Z_INDEX: 1050
7
+ @index: 0
8
+ constructor: () ->
9
+ backdrop_z_index: (num, index) -> angular.element(document.querySelectorAll('.modal-backdrop')).eq(num).css('z-index', index)
10
+ modal_num: (num) -> angular.element(document.querySelectorAll('.modal')).eq(num)
11
+ backdrop: (bdr) -> bdr ? 'static'
12
+ show_before: ->
13
+ @z_index = MManager.Z_INDEX + MManager.index * 2
14
+ @modal.css('z-index', @z_index + 1)
15
+ hide_before: ->
16
+ @z_index = MManager.Z_INDEX + ((MManager.index - 1) * 2)
17
+ show: ->
18
+ hide: -> angular.element($window.document.body).addClass('modal-open modal-with-am-fade') if MManager.index > 0
19
+
20
+ class DefaultMManager extends MManager
21
+ show_before: ->
22
+ super()
23
+ @backdrop.css('z-index', @z_index) # @backdrop_z_index(-MManager.index - 1, z_index)
24
+
25
+ class FirstMManager extends MManager
26
+ constructor: () ->
27
+ super()
28
+ @threshold = 2
29
+ backdrop: (bdr) -> if MManager.index > @threshold then false else super(bdr)
30
+ show_before: ->
31
+ super()
32
+ if MManager.index > @threshold
33
+ @modal_num((MManager.index - 1) - @threshold).css('display', 'none')
34
+ @backdrop_z_index(0, @z_index)
35
+ else
36
+ @backdrop.css('z-index', @z_index) # @backdrop_z_index(-MManager.index - 1, z_index)
37
+
38
+ hide_before: ->
39
+ super()
40
+ if MManager.index > @threshold
41
+ @backdrop_z_index(0, @z_index)
42
+ @modal_num((MManager.index - 1) - @threshold).css('display', 'block')
43
+
44
+ class SingleBackdropMManager extends MManager
45
+ backdrop: (bdr) -> if MManager.index > 0 then false else super(bdr)
46
+ show_before: ->
47
+ super()
48
+ @backdrop_z_index(0, @z_index)
49
+ hide_before: ->
50
+ super()
51
+ @backdrop_z_index(0, @z_index)
52
+
53
+ is_modal: -> MManager.index > 0
54
+
55
+ show: (action) ->
56
+ scope = if action.scope then action.scope().$new(true) else $rootScope.$new()
57
+ scope.action = action
58
+ manager = new SingleBackdropMManager()
59
+
60
+ scope.$on 'modal.show.before', (e, m) ->
61
+ e.stopPropagation()
62
+ manager.modal = m.$element
63
+ manager.backdrop = m.$backdrop
64
+ throw "Modal has element" if action.element?()
65
+ action.element = -> m.$element
66
+ action.panel_show?()
67
+ manager.show_before()
68
+ MManager.index++
69
+
70
+ scope.$on 'modal.show', (e, m) ->
71
+ e.stopPropagation()
72
+ manager.show()
73
+ action.panel_shown?()
74
+
75
+ scope.$on 'modal.hide.before', (e) ->
76
+ e.stopPropagation()
77
+ MManager.index--
78
+ manager.hide_before()
79
+ action.panel_hide?()
80
+
81
+ scope.$on 'modal.hide', (e) ->
82
+ e.stopPropagation()
83
+ manager.hide()
84
+ action.panel_hidden?()
85
+ scope.$destroy()
86
+
87
+ $injector.get('E2').fetch_panel(action.meta.panel, true).then (template) ->
88
+ modal = $modal
89
+ scope: scope
90
+ show: false
91
+ template: template
92
+ backdrop: manager.backdrop(action.meta.panel.backdrop)
93
+ animation: action.meta.panel.animation ? 'am-fade'
94
+
95
+ action.modal_hide = -> modal.$scope.$hide()
96
+ modal.$promise.then ->
97
+ modal.show()
98
+ modal
99
+
100
+ error: (title, msg, html) ->
101
+ body = if html then msg else "<div class='alert alert-danger'>#{msg}</div>"
102
+ clazz = if html then "modal-huge" else "modal-large"
103
+ @show meta: panel: (panel_template: "close_m", template_string: body, title: title, class: clazz, footer: true) # message: msg,
104
+
105
+ confirm: (title, msg, action) ->
106
+ body = "<div class='alert alert-warning'>#{msg}</div>"
107
+ clazz = "modal-large"
108
+ @show
109
+ confirm: action,
110
+ meta: panel: (panel_template: "confirm_m", template_string: body, title: title, class: clazz, footer: true) # message: msg,
111
+
112
+ .directive 'e2Modal', ($e2Modal) ->
113
+ restrict: 'E'
114
+ # replace: true
115
+ # transclude: true
116
+ scope: true
117
+ compile: (celem, cattr) ->
118
+ obody = celem[0].children[0]
119
+ celem.empty() if obody
120
+ (scope, elem, attrs) ->
121
+ scope.$on attrs.name, (ev, args) ->
122
+ return if ev.defaultPrevented
123
+ ev.preventDefault()
124
+
125
+ panel = panel_template: attrs.panelTemplate, title: attrs.title, class: attrs.clazz, footer: true
126
+ if obody then panel.template_string = obody.outerHTML else panel.template = attrs.template
127
+ action = meta: (panel: panel), scope: -> scope
128
+ _.assign(action, args)
129
+
130
+ modal = $e2Modal.show(action)
131
+ hide_off = scope.$on "#{attrs.name}_close", ->
132
+ hide_off()
133
+ modal.then (m) -> m.$scope.$hide()