engine2 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +3 -117
- data/{views → app}/app.coffee +0 -0
- data/{public/css → app}/app.css +203 -196
- data/{views → app}/engine2.coffee +111 -60
- data/{views → app}/engine2actions.coffee +47 -28
- data/bower.json +13 -0
- data/conf/message.yaml +2 -1
- data/conf/message_pl.yaml +2 -1
- data/config.coffee +62 -0
- data/engine2.gemspec +2 -5
- data/lib/engine2.rb +1 -1
- data/lib/engine2/action.rb +9 -24
- data/lib/engine2/core.rb +9 -8
- data/lib/engine2/handler.rb +1 -5
- data/lib/engine2/meta.rb +61 -24
- data/lib/engine2/meta/array_meta.rb +82 -0
- data/lib/engine2/meta/decode_meta.rb +1 -1
- data/lib/engine2/meta/infra_meta.rb +21 -26
- data/lib/engine2/meta/list_meta.rb +2 -3
- data/lib/engine2/model.rb +5 -5
- data/lib/engine2/pre_bootstrap.rb +9 -1
- data/lib/engine2/scheme.rb +4 -0
- data/lib/engine2/type_info.rb +8 -1
- data/lib/engine2/version.rb +1 -1
- data/package.json +38 -0
- data/public/img/ajax-loader.gif +0 -0
- data/views/fields/blob.slim +4 -5
- data/views/fields/bs_select.slim +2 -2
- data/views/fields/bsselect_picker.slim +1 -2
- data/views/fields/bsselect_picker_opt.slim +1 -2
- data/views/fields/checkbox.slim +1 -1
- data/views/fields/checkbox_buttons.slim +1 -1
- data/views/fields/checkbox_buttons_opt.slim +1 -1
- data/views/fields/currency.slim +2 -2
- data/views/fields/date.slim +0 -1
- data/views/fields/date_range.slim +0 -1
- data/views/fields/date_time.slim +0 -1
- data/views/fields/datetime.slim +0 -2
- data/views/fields/decimal.slim +0 -1
- data/views/fields/decimal_date.slim +0 -1
- data/views/fields/decimal_time.slim +0 -1
- data/views/fields/email.slim +1 -2
- data/views/fields/file_store.slim +1 -1
- data/views/fields/input_text.slim +1 -2
- data/views/fields/integer.slim +1 -1
- data/views/fields/list_bsselect.slim +1 -2
- data/views/fields/list_bsselect_opt.slim +2 -3
- data/views/fields/list_buttons.slim +1 -1
- data/views/fields/list_buttons_opt.slim +1 -1
- data/views/fields/list_select.slim +1 -2
- data/views/fields/list_select_opt.slim +2 -3
- data/views/fields/password.slim +1 -2
- data/views/fields/radio_checkbox.slim +1 -1
- data/views/fields/scaffold.slim +1 -1
- data/views/fields/scaffold_picker.slim +1 -2
- data/views/fields/select_picker.slim +1 -2
- data/views/fields/select_picker_opt.slim +1 -2
- data/views/fields/text_area.slim +0 -1
- data/views/fields/time.slim +0 -1
- data/views/fields/typeahead_picker.slim +1 -2
- data/views/index.slim +4 -8
- data/views/scaffold/fields.slim +4 -4
- data/views/scaffold/form.slim +1 -7
- data/views/scaffold/form_collapse.slim +19 -0
- data/views/scaffold/form_tabs.slim +9 -0
- data/views/scaffold/list.slim +1 -12
- data/views/scaffold/search.slim +2 -9
- data/views/scaffold/search_collapse.slim +26 -0
- data/views/scaffold/search_tabs.slim +15 -0
- data/views/scaffold/view.slim +5 -15
- data/views/scaffold/view_collapse.slim +22 -0
- data/views/scaffold/view_tabs.slim +11 -0
- data/views/search_fields/bsmselect_picker.slim +1 -2
- data/views/search_fields/bsselect_picker.slim +1 -2
- data/views/search_fields/checkbox.slim +3 -3
- data/views/search_fields/checkbox2.slim +5 -5
- data/views/search_fields/checkbox_buttons.slim +2 -2
- data/views/search_fields/date_range.slim +0 -2
- data/views/search_fields/decimal_date_range.slim +5 -5
- data/views/search_fields/input_text.slim +2 -2
- data/views/search_fields/integer.slim +1 -1
- data/views/search_fields/integer_range.slim +2 -2
- data/views/search_fields/list_bsmselect.slim +1 -1
- data/views/search_fields/list_bsselect.slim +0 -1
- data/views/search_fields/list_buttons.slim +2 -2
- data/views/search_fields/list_select.slim +1 -2
- data/views/search_fields/scaffold_picker.slim +1 -2
- data/views/search_fields/select_picker.slim +1 -2
- data/views/search_fields/typeahead_picker.slim +1 -2
- metadata +29 -103
- data/public/assets/javascripts.js +0 -13
- data/public/assets/styles.css +0 -4
- data/public/css/angular-motion.css +0 -1022
- data/public/css/angular-ui-tree.min.css +0 -1
- data/public/css/bootstrap-additions.css +0 -1560
- data/public/css/bootstrap.min.css +0 -11
- data/public/css/font-awesome.min.css +0 -4
- data/public/fonts/FontAwesome.otf +0 -0
- data/public/fonts/fontawesome-webfont.eot +0 -0
- data/public/fonts/fontawesome-webfont.svg +0 -655
- data/public/fonts/fontawesome-webfont.ttf +0 -0
- data/public/fonts/fontawesome-webfont.woff +0 -0
- data/public/fonts/fontawesome-webfont.woff2 +0 -0
- data/public/fonts/glyphicons-halflings-regular.eot +0 -0
- data/public/fonts/glyphicons-halflings-regular.svg +0 -288
- data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/public/fonts/glyphicons-halflings-regular.woff +0 -0
- data/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
- data/public/images/file.png +0 -0
- data/public/images/folder-closed.png +0 -0
- data/public/images/folder.png +0 -0
- data/public/images/node-closed-2.png +0 -0
- data/public/images/node-closed-light.png +0 -0
- data/public/images/node-closed.png +0 -0
- data/public/images/node-opened-2.png +0 -0
- data/public/images/node-opened-light.png +0 -0
- data/public/images/node-opened.png +0 -0
- data/public/img/ajax-loader-light.gif +0 -0
- data/public/js/angular-animate.js +0 -4147
- data/public/js/angular-cookies.js +0 -322
- data/public/js/angular-local-storage.js +0 -455
- data/public/js/angular-route.js +0 -1025
- data/public/js/angular-sanitize.js +0 -717
- data/public/js/angular-strap.js +0 -4339
- data/public/js/angular-strap.tpl.js +0 -43
- data/public/js/angular-ui-tree.js +0 -1569
- data/public/js/angular.js +0 -30868
- data/public/js/i18n/angular-locale_pl.js +0 -115
- data/public/js/lodash.custom.min.js +0 -99
- data/public/js/ng-file-upload-shim.min.js +0 -2
- data/public/js/ng-file-upload.min.js +0 -3
- data/views/engine2templates.coffee +0 -0
@@ -1,20 +1,15 @@
|
|
1
1
|
'use strict'
|
2
|
+
require 'angular-route'
|
3
|
+
require 'angular-sanitize'
|
4
|
+
require 'angular-animate'
|
5
|
+
require 'angular-cookies'
|
6
|
+
require 'angular-local-storage'
|
7
|
+
require 'angular-ui-tree'
|
8
|
+
require 'ng-file-upload'
|
9
|
+
|
2
10
|
_.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
3
11
|
|
4
12
|
angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStrap', 'ngFileUpload', 'ui.tree', 'LocalStorageModule']) # 'draggabilly'
|
5
|
-
.factory 'E2Snippets', ->
|
6
|
-
icon = (name) -> "<span class='glyphicon glyphicon-#{name}'></span>"
|
7
|
-
aicon = (name) -> "<i class='fa fa-#{name}'></i>"
|
8
|
-
ng_class_names = ['active', 'enabled', 'disabled']
|
9
|
-
icon: icon
|
10
|
-
aicon: aicon
|
11
|
-
boolean_true_value: icon('check')
|
12
|
-
boolean_false_value: icon('unchecked')
|
13
|
-
make_ng_class: (o) ->
|
14
|
-
out = []
|
15
|
-
_.each ng_class_names, (e) -> out.push(if e == 'enabled' then "'disabled': !(#{o[e]})" else "'#{e}': #{o[e]}") if o[e]?
|
16
|
-
if out.length > 0 then "ng-class=\"{#{out.join(',')}}\"" else ""
|
17
|
-
|
18
13
|
.config ($httpProvider, $routeProvider, $compileProvider, localStorageServiceProvider, $logProvider) ->
|
19
14
|
loaderOn = -> angular.element(document.querySelectorAll('.loader')).eq(-1).css("visibility", 'visible')
|
20
15
|
$httpProvider.interceptors.push 'e2HttpInterceptor'
|
@@ -51,7 +46,23 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
51
46
|
$injector.get('$e2Modal').error("#{E2Snippets.icon('bell')} #{response.status}: #{message}", cause)
|
52
47
|
$q.reject(response)
|
53
48
|
|
54
|
-
.factory '
|
49
|
+
.factory 'E2Snippets', ->
|
50
|
+
icon = (name) -> "<span class='glyphicon glyphicon-#{name}'></span>"
|
51
|
+
aicon = (name) -> "<i class='fa fa-#{name}'></i>"
|
52
|
+
ng_class_names = ['active', 'enabled', 'disabled']
|
53
|
+
icon: icon
|
54
|
+
aicon: aicon
|
55
|
+
boolean_true_value: icon('check')
|
56
|
+
boolean_false_value: icon('unchecked')
|
57
|
+
make_ng_class: (o) ->
|
58
|
+
out = []
|
59
|
+
_.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?
|
61
|
+
if out.length > 0 then "ng-class=\"{#{out.join(',')}}\"" else ""
|
62
|
+
|
63
|
+
.factory 'E2', ($templateCache, $http, E2Snippets, $e2Modal, $q, $injector, e2HttpInterceptor, $route, $dateFormatter, $parse) ->
|
64
|
+
globals: {}
|
65
|
+
|
55
66
|
compact: (o) ->
|
56
67
|
_.each o, (v, k) =>
|
57
68
|
if (v == null || (_.isString(v) && !v)) || (!_.isDate(v) && _.isObject(v) && @compact(v) && _.isEmpty(v))
|
@@ -66,6 +77,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
66
77
|
else
|
67
78
|
# delete o[k]
|
68
79
|
o[k] = null
|
80
|
+
|
69
81
|
merge: (dst, src) ->
|
70
82
|
for k, v of src
|
71
83
|
if _.isObject(v) && !_.isArray(v)
|
@@ -80,8 +92,8 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
80
92
|
transpose: (a) ->
|
81
93
|
_.keys(a[0]).map((c) -> a.map (r) -> r[c])
|
82
94
|
|
83
|
-
join_keys: (keys) -> keys.join(
|
84
|
-
split_keys: (key) -> key.split(
|
95
|
+
join_keys: (keys) -> keys.join(@globals.key_separator)
|
96
|
+
split_keys: (key) -> key.split(@globals.key_separator)
|
85
97
|
id_for: (rec, meta) -> @join_keys(meta.primary_fields.map((e) -> rec[e]))
|
86
98
|
from_id: (id, meta) -> _.zipObject(meta.primary_fields, id) # _.zip(meta.primary_fields, id).reduce(((rec, [k, v]) -> rec[k] = v; rec), {})
|
87
99
|
|
@@ -121,13 +133,15 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
121
133
|
m.click = fun_invoke
|
122
134
|
|
123
135
|
if click
|
124
|
-
action[fun_name] = (
|
125
|
-
processor.arg_fun(action,
|
136
|
+
action[fun_name] = (arg) ->
|
137
|
+
processor.arg_fun(action, arg)
|
126
138
|
action.scope().$eval(click)
|
127
139
|
else
|
128
|
-
action[fun_name] ?= (
|
129
|
-
processor.arg_fun(action,
|
130
|
-
|
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)
|
131
145
|
|
132
146
|
if action.find_action_info(m.name, false)?
|
133
147
|
show = if m.show then " && " + m.show else ""
|
@@ -136,17 +150,16 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
136
150
|
menu_processors:
|
137
151
|
menu:
|
138
152
|
arg_name: ''
|
139
|
-
arg_fun: (action) ->
|
140
|
-
arg_ret: (action) ->
|
153
|
+
arg_fun: (action) ->
|
154
|
+
arg_ret: (action) -> {}
|
141
155
|
panel_menu:
|
142
156
|
arg_name: ''
|
143
|
-
arg_fun: (action) ->
|
144
|
-
arg_ret: (action) ->
|
157
|
+
arg_fun: (action) ->
|
158
|
+
arg_ret: (action) -> {}
|
145
159
|
item_menu:
|
146
160
|
arg_name: '$index'
|
147
|
-
|
148
|
-
|
149
|
-
action.current_id = $injector.get('E2').id_for(action.entries[index], action.meta)
|
161
|
+
arg_fun: (action, index) -> action.current_index = index
|
162
|
+
arg_ret: (action) -> id: action.current_id()
|
150
163
|
|
151
164
|
renderers:
|
152
165
|
boolean: (value, render) =>
|
@@ -180,7 +193,8 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
180
193
|
if f_info? && type = f_info.type
|
181
194
|
@renderers[type](value, f_info.render)
|
182
195
|
else
|
183
|
-
|
196
|
+
if f_info?.escape == false then value else
|
197
|
+
(value + "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")
|
184
198
|
else
|
185
199
|
value
|
186
200
|
|
@@ -200,7 +214,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
200
214
|
constructor: () ->
|
201
215
|
backdrop_z_index: (num, index) -> angular.element(document.querySelectorAll('.modal-backdrop')).eq(num).css('z-index', index)
|
202
216
|
modal_num: (num) -> angular.element(document.querySelectorAll('.modal')).eq(num)
|
203
|
-
backdrop: -> 'static'
|
217
|
+
backdrop: (bdr) -> bdr ? 'static'
|
204
218
|
show_before: ->
|
205
219
|
@z_index = MManager.Z_INDEX + MManager.index * 2
|
206
220
|
@modal.css('z-index', @z_index + 1)
|
@@ -218,7 +232,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
218
232
|
constructor: () ->
|
219
233
|
super()
|
220
234
|
@threshold = 2
|
221
|
-
backdrop: -> if MManager.index > @threshold then false else super()
|
235
|
+
backdrop: (bdr) -> if MManager.index > @threshold then false else super(bdr)
|
222
236
|
show_before: ->
|
223
237
|
super()
|
224
238
|
if MManager.index > @threshold
|
@@ -234,7 +248,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
234
248
|
@modal_num((MManager.index - 1) - @threshold).css('display', 'block')
|
235
249
|
|
236
250
|
class SingleBackdropMManager extends MManager
|
237
|
-
backdrop: -> if MManager.index > 0 then false else super()
|
251
|
+
backdrop: (bdr) -> if MManager.index > 0 then false else super(bdr)
|
238
252
|
show_before: ->
|
239
253
|
super()
|
240
254
|
@backdrop_z_index(0, @z_index)
|
@@ -253,33 +267,38 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
253
267
|
e.stopPropagation()
|
254
268
|
manager.modal = m.$element
|
255
269
|
manager.backdrop = m.$backdrop
|
256
|
-
throw "Modal has element" if
|
257
|
-
|
258
|
-
|
270
|
+
throw "Modal has element" if action.element?()
|
271
|
+
action.element = -> m.$element
|
272
|
+
action.panel_show?()
|
259
273
|
manager.show_before()
|
260
274
|
MManager.index++
|
261
275
|
|
262
276
|
scope.$on 'modal.show', (e, m) ->
|
263
277
|
e.stopPropagation()
|
264
278
|
manager.show()
|
265
|
-
|
279
|
+
action.panel_shown?()
|
266
280
|
|
267
281
|
scope.$on 'modal.hide.before', (e) ->
|
268
282
|
e.stopPropagation()
|
269
283
|
MManager.index--
|
270
284
|
manager.hide_before()
|
271
|
-
|
285
|
+
action.panel_hide?()
|
272
286
|
|
273
287
|
scope.$on 'modal.hide', (e) ->
|
274
288
|
e.stopPropagation()
|
275
289
|
manager.hide()
|
276
|
-
|
290
|
+
action.panel_hidden?()
|
277
291
|
scope.$destroy()
|
278
292
|
|
279
|
-
$injector.get('E2').fetch_panel(
|
280
|
-
|
281
|
-
|
282
|
-
|
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()
|
283
302
|
modal.$promise.then ->
|
284
303
|
modal.show()
|
285
304
|
modal
|
@@ -385,31 +404,54 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
385
404
|
elem.after($compile(body)(scope))
|
386
405
|
|
387
406
|
.directive 'e2TableBody', ($parse, $compile) ->
|
407
|
+
table_tmpl = _.template("<thead><tr>{{thead}}</tr></thead><tbody>{{tbody}}</tbody>")
|
388
408
|
scope: false
|
389
409
|
restrict: 'A'
|
390
410
|
link: (scope, elem, attrs) ->
|
391
411
|
scope.$on 'render_table', (a, ev) ->
|
392
412
|
# ev.stopPropagation()
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
413
|
+
action = scope.action
|
414
|
+
meta = action.meta
|
415
|
+
position = meta.menus.item_menu.properties.position ? 0
|
416
|
+
right_style = if position >= meta.fields.length then "style=\"text-align: right\"" else ""
|
417
|
+
|
418
|
+
thead = ""
|
419
|
+
fields = meta.fields.slice()
|
420
|
+
fields.splice(position, 0, null)
|
421
|
+
_.each fields, (f) ->
|
422
|
+
if f
|
423
|
+
info = meta.info[f]
|
424
|
+
thead += "<th>"
|
425
|
+
title = if info.title then "title=\"#{info.title}\"" else ""
|
426
|
+
if info.sort
|
427
|
+
thead += "<a ng-click=\"action.order('#{f}')\" #{title}><strong>#{info.loc}</strong></a>"
|
428
|
+
if action.ui.order == f
|
429
|
+
cls = if action.ui.asc then "glyphicon-chevron-up" else "glyphicon-chevron-down"
|
430
|
+
thead += " <span class=\"glyphicon #{cls}\"></span>"
|
431
|
+
else
|
432
|
+
thead += "<span #{title}>#{info.loc}</span>"
|
433
|
+
thead += "</th>"
|
434
|
+
else
|
435
|
+
thead += "<th class=\"#{meta.menus.menu.properties.class || ''}\" #{right_style}><div e2-button-set=\"action.meta.menus.menu\"></div></th>"
|
436
|
+
|
437
|
+
tbody = ""
|
438
|
+
_.each action.entries, (e, i) ->
|
439
|
+
tbody += if action.selection then "<tr ng-class=\"action.selected_class(#{i})\" class=\"tr_hover\" ng-click=\"action.select(#{i}, $event)\">" else
|
398
440
|
row_cls = e.$row_info?.class
|
399
441
|
if row_cls then "<tr class=\"#{row_cls}\">" else "<tr>"
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
442
|
+
_.each fields, (f) ->
|
443
|
+
if f
|
444
|
+
tbody += if col_cls = meta.info[f].column_class then "<td class=\"#{col_cls}\">" else "<td>"
|
445
|
+
tbody += action.list_cell(e, f) ? ''
|
446
|
+
tbody += "</td>"
|
447
|
+
else
|
448
|
+
tbody += "<td #{right_style}><div e2-button-set=\"action.meta.menus.item_menu\" index=\"#{i}\"></div></td>"
|
449
|
+
tbody += "</tr>"
|
408
450
|
|
409
451
|
elem.empty()
|
410
|
-
elem.append($compile(
|
452
|
+
elem.append($compile(table_tmpl thead: thead, tbody: tbody)(scope))
|
411
453
|
|
412
|
-
.directive '
|
454
|
+
.directive 'e2Dropdown', ($parse, $dropdown, $timeout, E2Snippets) ->
|
413
455
|
event_num = 0
|
414
456
|
dropdown_sub_tmpl = _.template("<li class='dropdown-submenu'><a href=''> {{icon}}{{aicon}} {{loc}}</a>{{sub}}</li>")
|
415
457
|
dropdown_tmpl = _.template("<li {{clazz}} {{show}} {{hide}}> <a href='{{href}}' {{click}}> {{icon}}{{aicon}} {{loc}}</a></li>")
|
@@ -446,7 +488,8 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
446
488
|
elem.off "mousedown"
|
447
489
|
# event.preventDefault()
|
448
490
|
# event.stopPropagation()
|
449
|
-
|
491
|
+
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
|
450
493
|
dropdown.$promise.then ->
|
451
494
|
event_hide = scope.$on "#{event_num}.tooltip.hide", (e) ->
|
452
495
|
e.stopPropagation()
|
@@ -463,13 +506,14 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
463
506
|
|
464
507
|
.directive 'e2ButtonSet', ($parse, $compile, E2Snippets) ->
|
465
508
|
button_set_tmpl = _.template("<div class='btn btn-default' {{clazz}} {{click}} {{show}} {{hide}} {{title}}> {{icon}}{{aicon}} {{loc}}</div>")
|
466
|
-
button_set_arr_tmpl = _.template("<div class='btn btn-default' e2-
|
509
|
+
button_set_arr_tmpl = _.template("<div class='btn btn-default' e2-dropdown='{{dropdown}}' data-animation='{{animation}}'>{{icon}}{{aicon}}<span class='caret'></span></div>")
|
467
510
|
scope: true # because $index
|
468
511
|
link: (scope, elem, attrs) ->
|
469
512
|
menu = $parse(attrs.e2ButtonSet)(scope)
|
470
513
|
if menu && menu.entries.length > 0
|
471
514
|
group_class = menu.properties.group_class || ''
|
472
515
|
brk = menu.properties.break
|
516
|
+
animation = menu.properties.animation
|
473
517
|
out = ""
|
474
518
|
for m, i in menu.entries
|
475
519
|
if i >= brk
|
@@ -477,6 +521,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
477
521
|
else if m.menu
|
478
522
|
out += button_set_arr_tmpl
|
479
523
|
dropdown: "#{attrs.e2ButtonSet}.entries[#{i}].menu.entries"
|
524
|
+
animation: animation
|
480
525
|
icon: m.menu.icon && "#{E2Snippets.icon(m.menu.icon)} " || ''
|
481
526
|
aicon: m.menu.aicon && "#{E2Snippets.aicon(m.menu.aicon)} " || ''
|
482
527
|
else if m.divider
|
@@ -491,7 +536,13 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
491
536
|
loc: !(m.button_loc == false) && m.loc || ''
|
492
537
|
title: (m.button_loc == false) && "title=\"#{m.loc}\"" || ''
|
493
538
|
|
494
|
-
|
539
|
+
if menu.entries.length > brk
|
540
|
+
out += button_set_arr_tmpl
|
541
|
+
dropdown: "#{attrs.e2ButtonSet}.entries.slice(#{brk})"
|
542
|
+
animation: animation
|
543
|
+
icon: ''
|
544
|
+
aicon: ''
|
545
|
+
|
495
546
|
out = "<div class='btn-group #{group_class}'>#{out}</div>"
|
496
547
|
out = $compile(angular.element(out))(scope)
|
497
548
|
if attrs.index && !scope.$index?
|
@@ -1,3 +1,4 @@
|
|
1
|
+
'use strict'
|
1
2
|
angular.module('Engine2')
|
2
3
|
.directive 'e2Action', (E2Actions) ->
|
3
4
|
scope: true
|
@@ -22,7 +23,7 @@ angular.module('Engine2')
|
|
22
23
|
$scope.action = new E2Actions.root(mresponse.data, $scope, null, $element, action_resource: 'api')
|
23
24
|
|
24
25
|
.factory 'E2Actions', (E2, $http, $timeout, $e2Modal, $injector, $compile, $templateCache, $q, localStorageService, $route, $window, $rootScope, $location) ->
|
25
|
-
globals =
|
26
|
+
globals = E2.globals
|
26
27
|
action: class Action
|
27
28
|
constructor: (response, scope, parent, element, action_info) ->
|
28
29
|
@find_action_info = (name, raise = true) ->
|
@@ -71,14 +72,17 @@ angular.module('Engine2')
|
|
71
72
|
|
72
73
|
perform_invoke: (params) ->
|
73
74
|
info = @action_info()
|
74
|
-
get_invoke = if
|
75
|
-
params.initial = true if
|
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'
|
76
77
|
$http[info.method](info.action_resource, if info.method == 'post' then params else (params: params))
|
77
|
-
else $q.when(data: (response: {}))
|
78
78
|
|
79
79
|
globals.action_pending = if @meta.panel then @ else @parent()
|
80
80
|
|
81
81
|
get_invoke.then (response) =>
|
82
|
+
if exec = response.data.$execute
|
83
|
+
@scope().$eval(exec)
|
84
|
+
delete response.data.$execute
|
85
|
+
|
82
86
|
E2.merge(@, response.data)
|
83
87
|
@process_meta()
|
84
88
|
(if @meta.reload_routes then $route.load_routes() else $q.when({})).then =>
|
@@ -103,7 +107,7 @@ angular.module('Engine2')
|
|
103
107
|
get_meta = if !info.terminal || info.meta
|
104
108
|
$http.get("#{info.action_resource}/meta", cache: true).then (response) =>
|
105
109
|
if info.recheck_access
|
106
|
-
$http.get("#{info.action_resource}/meta", params: (access: true, parent_id: @current_id)).then (aresponse) ->
|
110
|
+
$http.get("#{info.action_resource}/meta", params: (access: true, parent_id: @current_id())).then (aresponse) ->
|
107
111
|
response.data.actions[k].access = v for k, v of aresponse.data
|
108
112
|
response
|
109
113
|
else response # $q.when ^
|
@@ -113,8 +117,8 @@ angular.module('Engine2')
|
|
113
117
|
,
|
114
118
|
(err) => @handle_error(err, info, el)
|
115
119
|
|
116
|
-
invoke_action: (name,
|
117
|
-
@create_action(name, @scope()).then (act) -> act.invoke(
|
120
|
+
invoke_action: (name, args) ->
|
121
|
+
@create_action(name, @scope()).then (act) -> act.invoke(args)
|
118
122
|
|
119
123
|
create_action_path: (action_names, sc, elem) ->
|
120
124
|
last_name = action_names.pop()
|
@@ -126,17 +130,23 @@ angular.module('Engine2')
|
|
126
130
|
pre_invoke: ->
|
127
131
|
post_invoke: ->
|
128
132
|
|
129
|
-
invoke: ->
|
130
|
-
args
|
131
|
-
|
132
|
-
@perform_invoke(args
|
133
|
-
@post_invoke(args
|
133
|
+
invoke: (args) ->
|
134
|
+
@pre_invoke(args)
|
135
|
+
_.merge(args ?= {}, @meta.arguments) if @meta.arguments
|
136
|
+
@perform_invoke(args).then =>
|
137
|
+
@post_invoke(args)
|
138
|
+
@scope().$eval(@meta.execute) if @meta.execute
|
139
|
+
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
|
134
144
|
@
|
135
145
|
|
136
146
|
save_state: () ->
|
137
147
|
_.each @meta.state, (s) => localStorageService.set("#{globals.application}/#{@action_info().action_resource}/#{s}", @[s])
|
138
148
|
load_state: () ->
|
139
|
-
_.each @meta.state, (s) =>
|
149
|
+
_.each @meta.state, (s) => _.merge(@[s], localStorageService.get("#{globals.application}/#{@action_info().action_resource}/#{s}"))
|
140
150
|
|
141
151
|
destroy: (e) ->
|
142
152
|
console.log "DESTROY #{@action_info().action_resource}"
|
@@ -194,7 +204,7 @@ angular.module('Engine2')
|
|
194
204
|
root: class RootAction extends Action
|
195
205
|
initialize: ->
|
196
206
|
super()
|
197
|
-
|
207
|
+
_.merge(globals, @meta)
|
198
208
|
@meta = {}
|
199
209
|
|
200
210
|
default_action: class DefaultAction extends Action
|
@@ -266,10 +276,13 @@ angular.module('Engine2')
|
|
266
276
|
if route.menu then @register(route.menu.entries) else
|
267
277
|
name = '/' + route.name
|
268
278
|
route.href = '#' + route.name
|
269
|
-
|
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
|
+
|
270
283
|
$route.routes[name] =
|
271
284
|
reloadOnSearch: true
|
272
|
-
templateUrl: route.name
|
285
|
+
templateUrl: if route.bootstrap? then route.name + '_route_template!' else route.name
|
273
286
|
originalPath: name
|
274
287
|
regexp: new RegExp("^#{name}$")
|
275
288
|
keys: []
|
@@ -282,14 +295,16 @@ angular.module('Engine2')
|
|
282
295
|
|
283
296
|
traverse: (routes) ->
|
284
297
|
menu_tmpl = _.template("<li><a href='{{href}}'>{{icon}}{{aicon}} {{loc}}</a></li>")
|
285
|
-
menu_sub_tmpl = _.template("<li e2-
|
298
|
+
menu_sub_tmpl = _.template("<li e2-dropdown='{{dropdown}}' data-animation='{{animation}}'><a href='javascript://'>{{icon}}{{aicon}} {{loc}}<span class='caret'></span></a></li>")
|
299
|
+
animation = @meta.menus.menu.properties.animation
|
286
300
|
out = routes.map (route, i) ->
|
287
301
|
if route.menu
|
288
302
|
menu_sub_tmpl
|
303
|
+
dropdown: "routes[#{i}].menu.entries"
|
304
|
+
animation: animation
|
289
305
|
icon: route.menu.icon && E2.icon(route.menu.icon) || ""
|
290
306
|
aicon: route.menu.aicon && E2.aicon(route.menu.aicon) || ""
|
291
307
|
loc: route.menu.loc
|
292
|
-
dropdown: "routes[#{i}].menu.entries"
|
293
308
|
else
|
294
309
|
menu_tmpl
|
295
310
|
href: route.href
|
@@ -298,8 +313,6 @@ angular.module('Engine2')
|
|
298
313
|
aicon: route.aicon && E2.aicon(route.aicon) || ''
|
299
314
|
out.join('')
|
300
315
|
|
301
|
-
# dummy: class DummyAction extends Action
|
302
|
-
|
303
316
|
list: class ListAction extends Action
|
304
317
|
initialize: ->
|
305
318
|
super()
|
@@ -340,7 +353,7 @@ angular.module('Engine2')
|
|
340
353
|
menu_show_meta: ->
|
341
354
|
$e2Modal.show
|
342
355
|
the_meta: @meta
|
343
|
-
meta: panel: (panel_template: "close_m", template_string: "<pre>{{action.the_meta | json}}</pre>", title: "Meta", class: "modal-huge")
|
356
|
+
meta: panel: (panel_template: "close_m", template_string: "<pre>{{action.the_meta | json}}</pre>", title: "Meta", class: "modal-huge", backdrop: true, footer: true)
|
344
357
|
|
345
358
|
# show_assoc: (index, assoc) ->
|
346
359
|
# # parent_id = E2.id_for(@entries[index], @meta)
|
@@ -350,14 +363,20 @@ angular.module('Engine2')
|
|
350
363
|
# @current_id = E2.id_for(@entries[index], @meta)
|
351
364
|
# @invoke_action(assoc)
|
352
365
|
|
366
|
+
current_entry: ->
|
367
|
+
@entries[@current_index]
|
368
|
+
|
369
|
+
current_id: ->
|
370
|
+
E2.id_for(@current_entry(), @meta)
|
371
|
+
|
353
372
|
list_cell: (e, f) ->
|
354
373
|
E2.render_field(e, f, @meta)
|
355
374
|
|
356
|
-
invoke: (
|
375
|
+
invoke: (args = {}) ->
|
357
376
|
@save_state()
|
358
377
|
query = _.cloneDeep(@query)
|
359
378
|
delete query.search if _.isEmpty(E2.compact(query.search))
|
360
|
-
_.merge(query,
|
379
|
+
_.merge(query, args)
|
361
380
|
super(query).then =>
|
362
381
|
@ui = _.pick @query, ['order', 'asc', 'page']
|
363
382
|
@ui.pagination_active = @ui.page != 0 || @entries.length >= @meta.config.per_page
|
@@ -599,7 +618,7 @@ angular.module('Engine2')
|
|
599
618
|
@multiple = @dinfo.render.multiple
|
600
619
|
@clear_selected()
|
601
620
|
@if_fk_values (fk_values) =>
|
602
|
-
@selected = if @multiple then E2.transpose(fk_values).map(E2.join_keys) else E2.join_keys(fk_values)
|
621
|
+
@selected = if @multiple then E2.transpose(fk_values).map((e) -> E2.join_keys(e)) else E2.join_keys(fk_values)
|
603
622
|
@invoke()
|
604
623
|
|
605
624
|
clear_selected: -> @selected = if @multiple then [] else null # no need to null complex keys
|
@@ -652,7 +671,7 @@ angular.module('Engine2')
|
|
652
671
|
|
653
672
|
invoke_decode: (recs, f) ->
|
654
673
|
if @multiple && _.size(recs) > @meta.show_max_selected
|
655
|
-
@decode = "#{_.size(recs)} #{@meta.decode_selected}"
|
674
|
+
@decode = "#{_.size(recs)} #{@meta.loc.decode_selected}"
|
656
675
|
else
|
657
676
|
decode_descriptions = (recs) => @decode = recs.map((fields) => @decode_description(fields)).join(' | ')
|
658
677
|
recs = recs.map (r) => if _.isArray(r) then E2.from_id(r, @meta) else r
|
@@ -721,7 +740,7 @@ angular.module('Engine2')
|
|
721
740
|
star_to_many_list: class StarToManyList extends ListAction
|
722
741
|
initialize: ->
|
723
742
|
super()
|
724
|
-
@query.parent_id = @parent().current_id
|
743
|
+
@query.parent_id = @parent().current_id()
|
725
744
|
|
726
745
|
# link_list: implicit
|
727
746
|
item_menu_confirm_unlink: (index) ->
|
@@ -786,8 +805,8 @@ angular.module('Engine2')
|
|
786
805
|
@panel_close()
|
787
806
|
|
788
807
|
star_to_many_field_unlink: class StarToManyFieldUnlink extends Action
|
789
|
-
invoke: (
|
790
|
-
id =
|
808
|
+
invoke: (args) ->
|
809
|
+
id = args.id
|
791
810
|
pparent = @parent().parent()
|
792
811
|
if _.includes(pparent.links.linked, id) then _.pull(pparent.links.linked, id) else pparent.links.unlinked.push id
|
793
812
|
pparent.sync_record()
|