engine2 1.0.4 → 1.0.5

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