engine2 1.0.8 → 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +3 -3
- data/app/actions.coffee +87 -50
- data/app/app.css +2 -1
- data/app/engine2.coffee +37 -19
- data/app/modal.coffee +8 -3
- data/bower.json +3 -2
- data/conf/message.yaml +3 -0
- data/conf/message_pl.yaml +5 -2
- data/config.coffee +16 -15
- data/engine2.gemspec +1 -1
- data/lib/engine2/action.rb +51 -23
- data/lib/engine2/action/array.rb +94 -1
- data/lib/engine2/action/decode.rb +29 -3
- data/lib/engine2/action/delete.rb +1 -2
- data/lib/engine2/action/infra.rb +5 -4
- data/lib/engine2/action/list.rb +70 -25
- data/lib/engine2/action/save.rb +0 -2
- data/lib/engine2/action_node.rb +2 -4
- data/lib/engine2/core.rb +30 -21
- data/lib/engine2/handler.rb +5 -5
- data/lib/engine2/model.rb +18 -9
- data/lib/engine2/models/Files.rb +2 -0
- data/lib/engine2/scheme.rb +1 -6
- data/lib/engine2/templates.rb +32 -6
- data/lib/engine2/type_info.rb +9 -5
- data/lib/engine2/version.rb +1 -1
- data/package.json +9 -8
- data/views/fields/checkbox_button.slim +6 -0
- data/views/fields/checkbox_buttons.slim +1 -1
- data/views/fields/list_mbuttons.slim +9 -0
- data/views/fields/list_mbuttons_opt.slim +11 -0
- data/views/fields/list_mselect.slim +12 -0
- data/views/fields/scaffold.slim +1 -1
- data/views/fields/typeahead_picker.slim +8 -5
- data/views/infra/inspect.slim +19 -16
- data/views/scaffold/fields.slim +3 -1
- data/views/scaffold/search.slim +2 -2
- data/views/scaffold/search_collapse.slim +2 -2
- data/views/scaffold/search_tabs.slim +2 -2
- data/views/search_fields/date.slim +20 -0
- data/views/search_fields/list_mbuttons.slim +12 -0
- data/views/search_fields/typeahead_picker.slim +4 -3
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc5654aaf1573375a69ca96d3d957b07e1970ef777e0deb65c18f28c40666489
|
4
|
+
data.tar.gz: aa79d8a00f564a0e23e4520ea1198446a6049c241b5bdb714416aa7ed378de6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 271c8416bd7551d08fa8574319be948aa9b8658fc431e432c65a19deb456deead3fc92e213259e2f9ad0783a77099a8dbce13c460fe45d715abab7bf09efc392
|
7
|
+
data.tar.gz: b65bd605e3d622586f433d5900d9da115e880e62a0827913f03c2e18dc9ce744fb6ebaa88f4a31e3582251c8551be9b71a0f03299498d1042082dd3eeb0f3074
|
data/Rakefile
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
desc "Compile SLIM"
|
2
2
|
task :compile_slim do
|
3
3
|
require 'slim'
|
4
|
-
view_dirs = ["fields", "scaffold", "search_fields", "modals"]
|
4
|
+
view_dirs = ["fields", "scaffold", "search_fields", "modals", "panels"]
|
5
5
|
slims = view_dirs.each.map do |view_dir|
|
6
6
|
Dir["views/#{view_dir}/*.slim"].map do |slim_file|
|
7
7
|
slim = Slim::Template.new(slim_file).render.gsub('"', '\"')
|
8
8
|
tpl_name = slim_file.sub("views/", "").sub(".slim", "")
|
9
|
-
"
|
9
|
+
"c.put('#{tpl_name}', \"#{slim}\");"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
open("app/templates.js", "wb") << <<-EOF
|
14
|
-
angular.module('Engine2').run(['$templateCache', function(
|
14
|
+
angular.module('Engine2').run(['$templateCache', function(c) {
|
15
15
|
#{slims.join("\n")}
|
16
16
|
}]);
|
17
17
|
EOF
|
data/app/actions.coffee
CHANGED
@@ -51,9 +51,16 @@ angular.module('Engine2')
|
|
51
51
|
@meta.panel.modal_action = false
|
52
52
|
@meta.panel.footer = true unless @meta.panel.footer == false
|
53
53
|
|
54
|
+
|
55
|
+
if scope && @meta.invokable != false
|
56
|
+
scope.$on action_info.action_resource, (e, args) => @invoke(args)
|
57
|
+
|
54
58
|
@websocket_connect() if @meta.websocket
|
55
59
|
@initialize()
|
56
60
|
|
61
|
+
broadcast: (sub_action, args) ->
|
62
|
+
@scope().$broadcast(@action_info().action_resource + '/' + sub_action, args)
|
63
|
+
|
57
64
|
initialize: ->
|
58
65
|
@process_static_meta()
|
59
66
|
console.info "CREATE #{@action_info().action_resource}"
|
@@ -68,7 +75,13 @@ angular.module('Engine2')
|
|
68
75
|
if action_info.access
|
69
76
|
$rootScope.$broadcast "relogin", element?, create
|
70
77
|
else
|
71
|
-
|
78
|
+
tle = "#{err.status}: #{err.data.message}"
|
79
|
+
msg = err.data.cause || err.data.message
|
80
|
+
if msg.length > 500
|
81
|
+
@globals().modal().error(tle, msg)
|
82
|
+
else
|
83
|
+
@globals().toastr().error(tle, msg, extendedTimeOut: 5000, closeButton: true)
|
84
|
+
|
72
85
|
$q.reject(err)
|
73
86
|
|
74
87
|
save_state: () ->
|
@@ -100,28 +113,35 @@ angular.module('Engine2')
|
|
100
113
|
|
101
114
|
create_action_path: (action_names, sc, elem) ->
|
102
115
|
last_name = action_names.pop()
|
103
|
-
_.reduce(action_names, ((pr, nm) -> pr.then (act) -> act.create_action(nm)), $q.when(@)).then (act) ->
|
116
|
+
_.reduce(action_names, ((pr, nm) -> pr.then (act) -> act.create_action(nm)), $q.when(@)).then (act) -> # self = @
|
104
117
|
act.create_action(last_name, sc, elem).then (act) -> sc.action = act
|
105
118
|
|
106
119
|
globals: -> globals
|
120
|
+
_ : -> _
|
121
|
+
current: -> @globals().current_action
|
107
122
|
action_pending: -> globals.action_pending == @
|
108
123
|
pre_invoke: ->
|
109
124
|
post_invoke: ->
|
110
125
|
|
111
126
|
invoke: (params) ->
|
127
|
+
@globals().current_action = @
|
112
128
|
params ?= {}
|
113
129
|
@globals().action_pending = if @meta.panel then @ else @parent()
|
114
130
|
@pre_invoke(params)
|
115
|
-
_.merge(params, @meta.arguments)
|
131
|
+
if @meta.arguments # _.merge(params, @meta.arguments)
|
132
|
+
_.each @meta.arguments, (v, k) =>
|
133
|
+
if _.endsWith(k, '!') then params[k.slice(0, -1)] = @scope().$eval(v) else params[k] = v
|
134
|
+
|
116
135
|
|
117
136
|
info = @action_info()
|
118
137
|
get_invoke = if @meta.invokable == false then $q.when(data: (response: {})) else
|
119
138
|
params.initial = true if @meta.panel && !@action_invoked && info.method == 'get'
|
120
139
|
$http[info.method](info.action_resource, if info.method == 'post' then params else (params: params))
|
121
140
|
|
141
|
+
@execute_commands('pre_execute')
|
122
142
|
get_invoke.then (response) =>
|
123
143
|
@arguments = _.keys(response.data)
|
124
|
-
E2.
|
144
|
+
E2.merge_meta(@, response.data)
|
125
145
|
@process_meta()
|
126
146
|
|
127
147
|
promise = if @meta.panel # persistent action
|
@@ -131,20 +151,22 @@ angular.module('Engine2')
|
|
131
151
|
else
|
132
152
|
prnt = @parent()
|
133
153
|
throw "Attempted parent merge for root action: #{info.name}" unless prnt
|
134
|
-
E2.
|
154
|
+
E2.merge_meta(prnt, response.data)
|
135
155
|
|
136
156
|
@post_invoke(params)
|
137
|
-
@execute_commands()
|
157
|
+
@execute_commands('execute')
|
138
158
|
if @meta.repeat
|
139
159
|
@scope().$on "$destroy", => @destroyed = true
|
140
160
|
$timeout (=> @invoke(params)), @meta.repeat unless @destroyed
|
141
161
|
delete @meta.repeat
|
142
162
|
|
143
163
|
@globals().action_pending = false
|
164
|
+
@globals().current_action = null
|
144
165
|
promise
|
145
166
|
,
|
146
167
|
(err) =>
|
147
168
|
@globals().action_pending = false
|
169
|
+
@globals().current_action = null
|
148
170
|
@handle_error(err, info, @element())
|
149
171
|
|
150
172
|
panel_render: ->
|
@@ -203,26 +225,28 @@ angular.module('Engine2')
|
|
203
225
|
websocket_connect: ->
|
204
226
|
l = $location
|
205
227
|
ws_meta = @meta.websocket
|
206
|
-
ws = $websocket "ws#{l.protocol().slice(4, 5)}://#{l.host()}:#{l.port()}
|
228
|
+
ws = $websocket "ws#{l.protocol().slice(4, 5)}://#{l.host()}:#{l.port()}#{'/'}#{@action_info().action_resource}", undefined, ws_meta.options
|
207
229
|
_.each @globals().ws_methods, (method) =>
|
208
230
|
ws_method_impl = @["ws_#{method}"]
|
209
231
|
ws["on#{_.capitalize(method)}"] (evt) =>
|
210
232
|
if method == 'message'
|
211
233
|
msg = JSON.parse(evt.data)
|
212
234
|
if msg.error then @globals().modal().error("WebSocket [#{evt.origin}] - #{msg.error.method}", msg.error.exception) else
|
213
|
-
E2.
|
235
|
+
E2.merge_meta(@, msg)
|
214
236
|
@process_meta()
|
215
237
|
else msg = evt
|
216
238
|
ws_method_impl.bind(@)(msg, ws, evt) if ws_method_impl
|
217
|
-
@execute_commands()
|
218
|
-
delete @meta.execute
|
239
|
+
@execute_commands('execute')
|
219
240
|
|
220
241
|
@web_socket = -> ws
|
221
242
|
@scope().$on "$destroy", -> ws.close()
|
222
243
|
|
223
|
-
execute_commands: ->
|
224
|
-
|
225
|
-
|
244
|
+
execute_commands: (execute) ->
|
245
|
+
if @meta[execute]
|
246
|
+
scope = @scope()
|
247
|
+
_.reduce(@meta[execute], ((pr, cmd) -> pr.then -> scope.$eval(cmd)), $q.when())
|
248
|
+
@meta[execute].splice(0, @meta[execute].length)
|
249
|
+
delete @meta[execute]
|
226
250
|
|
227
251
|
console_log: (o) ->
|
228
252
|
console.log o
|
@@ -303,7 +327,7 @@ angular.module('Engine2')
|
|
303
327
|
$urlRouter.otherwise(otherwise)
|
304
328
|
@register(menu.entries)
|
305
329
|
@scope().routes = menu.entries
|
306
|
-
out =
|
330
|
+
out = $compile(@traverse(menu.entries))(@scope())
|
307
331
|
@element().replaceWith(out)
|
308
332
|
@element = -> out
|
309
333
|
loc = $location.path().slice(1)
|
@@ -331,7 +355,9 @@ angular.module('Engine2')
|
|
331
355
|
menu_sub_tmpl = _.template("<li {{show}} {{hide}} e2-dropdown='{{dropdown}}' nav='true' data-animation='{{animation}}'><a href='javascript://'>{{icon}} {{loc}}<span class='caret'></span></a></li>")
|
332
356
|
animation = @meta.menus.menu.properties.animation
|
333
357
|
out = routes.map (route, i) ->
|
334
|
-
if route.
|
358
|
+
if route.render == false
|
359
|
+
''
|
360
|
+
else if route.menu
|
335
361
|
menu_sub_tmpl
|
336
362
|
dropdown: "routes[#{i}].menu.entries"
|
337
363
|
animation: animation
|
@@ -346,7 +372,8 @@ angular.module('Engine2')
|
|
346
372
|
show: route.show && "ng-show=\"#{route.show}\"" || ''
|
347
373
|
hide: route.hide && "ng-hide=\"#{route.hide}\"" || ''
|
348
374
|
icon: route.icon && E2.icon(route.icon) || ''
|
349
|
-
out.join('')
|
375
|
+
out = out.join('')
|
376
|
+
if _.size(out) == 0 then "<div></div>" else out
|
350
377
|
|
351
378
|
list: class ListAction extends Action
|
352
379
|
initialize: ->
|
@@ -391,7 +418,7 @@ angular.module('Engine2')
|
|
391
418
|
menu_show_meta: ->
|
392
419
|
@globals().modal().show
|
393
420
|
the_meta: @meta
|
394
|
-
meta: panel: (panel_template: "close_m", template_string: "<pre>{{action.the_meta |
|
421
|
+
meta: panel: (panel_template: "close_m", template_string: "<pre>{{action.the_meta | yaml}}</pre>", title: "Meta", class: "modal-huge", backdrop: true, footer: true)
|
395
422
|
|
396
423
|
# show_assoc: (index, assoc) ->
|
397
424
|
# # parent_id = E2.id_for(@entries[index], @meta)
|
@@ -453,12 +480,12 @@ angular.module('Engine2')
|
|
453
480
|
search_field_change: (f) ->
|
454
481
|
info = @meta.fields[f]
|
455
482
|
|
456
|
-
@scope().$eval(info.onchange) if info.onchange
|
483
|
+
@scope().$eval(info.onchange.action) if info.onchange
|
457
484
|
|
458
485
|
if remote_onchange = info.remote_onchange
|
459
486
|
params = value: @query.search[f]
|
460
|
-
params.record = @query.search if
|
461
|
-
@invoke_action(remote_onchange, params).then =>
|
487
|
+
params.record = @query.search if remote_onchange.record
|
488
|
+
@invoke_action(remote_onchange.action, params).then =>
|
462
489
|
@load_new() if info.search_live
|
463
490
|
else
|
464
491
|
@load_new() if info.search_live
|
@@ -490,6 +517,11 @@ angular.module('Engine2')
|
|
490
517
|
entry_moved: (index) ->
|
491
518
|
@moved_from = index
|
492
519
|
|
520
|
+
list_parent_action: ->
|
521
|
+
parent = @parent()
|
522
|
+
parent = parent.parent() until parent instanceof ListAction
|
523
|
+
parent
|
524
|
+
|
493
525
|
bulk_delete: class BulkDeleteAction extends Action
|
494
526
|
invoke: ->
|
495
527
|
super(ids: [_.keys(@parent().parent().selection)]).then =>
|
@@ -502,17 +534,6 @@ angular.module('Engine2')
|
|
502
534
|
form_base_action: class FormBaseAction extends Action
|
503
535
|
initialize: ->
|
504
536
|
super()
|
505
|
-
_.each @meta.fields, (info, name) =>
|
506
|
-
if info.remote_onchange
|
507
|
-
@scope().$watch (=> @record?[name]), (n) => if n? #if typeof(n) != "undefined"
|
508
|
-
params = value: @record[name]
|
509
|
-
params.record = @record if info.remote_onchange_record
|
510
|
-
@invoke_action(info.remote_onchange, params)
|
511
|
-
|
512
|
-
if info.onchange
|
513
|
-
@scope().$watch (=> @record?[name]), (n) => if n?
|
514
|
-
@scope().$eval(info.onchange)
|
515
|
-
|
516
537
|
if @meta.tab_list
|
517
538
|
@scope().$watch "action.activeTab", (tab) => if tab? # && tab >= 0
|
518
539
|
@panel_shown()
|
@@ -522,12 +543,26 @@ angular.module('Engine2')
|
|
522
543
|
post_invoke: (args) ->
|
523
544
|
super()
|
524
545
|
_.each @meta.fields, (info, name) =>
|
525
|
-
if
|
546
|
+
if @record[name] is undefined
|
547
|
+
@record[name] = null
|
548
|
+
else if _.isString(@record[name]) && !info.dont_strip
|
526
549
|
@record[name] = @record[name].trim()
|
527
550
|
|
551
|
+
if info.onchange || info.remote_onchange
|
552
|
+
onchange = => @scope().$eval(info.onchange.action)
|
553
|
+
remote_onchange = =>
|
554
|
+
params = value: @record[name]
|
555
|
+
params.record = @record if info.remote_onchange.record
|
556
|
+
@invoke_action(info.remote_onchange.action, params)
|
557
|
+
|
558
|
+
@scope().$watch (=> @record[name]), (n, o) => if n != o
|
559
|
+
onchange() if info.onchange
|
560
|
+
remote_onchange() if info.remote_onchange
|
561
|
+
|
562
|
+
onchange() if info.onchange?.trigger_on_start
|
563
|
+
remote_onchange() if info.remote_onchange?.trigger_on_start
|
564
|
+
|
528
565
|
panel_menu_default_action: ->
|
529
|
-
_.each @meta.fields, (v, n) =>
|
530
|
-
@record[n] = null if @record[n] is undefined
|
531
566
|
params = record: @record
|
532
567
|
params.parent_id ?= @parent().query?.parent_id # and StarToManyList ?
|
533
568
|
@invoke_action(@default_action_name, params).then =>
|
@@ -734,29 +769,31 @@ angular.module('Engine2')
|
|
734
769
|
typeahead: class TypeAheadAction extends DecodeAction
|
735
770
|
initialize: ->
|
736
771
|
super()
|
737
|
-
@if_fk_values (fk_values) =>
|
738
|
-
@invoke(id: E2.join_keys(fk_values)).then =>
|
739
|
-
if @entry
|
740
|
-
@decode = id: E2.id_for(@entry, @meta), value: @decode_description(@entry)
|
741
|
-
|
742
772
|
@scope().$on "$typeahead.select", (e, v, index) =>
|
743
773
|
e.stopPropagation()
|
744
774
|
_(@dinfo.fields).zip(E2.split_keys(@values[index].id)).each(([fk, k]) => @record()[fk] = E2.parse_entry(k, @parentp().meta.fields[fk])).value
|
775
|
+
@parentp().scope().$digest()
|
745
776
|
@parentp().search_field_change?(@decode_field)
|
746
777
|
|
747
|
-
@scope().$watch "action.decode", (e) => if e
|
748
|
-
|
778
|
+
@scope().$watch "action.decode", (e) => @reset() if e == null
|
779
|
+
|
780
|
+
@if_fk_values (fk_values) =>
|
781
|
+
@invoke(id: E2.join_keys(fk_values)).then =>
|
782
|
+
if @entry
|
783
|
+
@decode = id: E2.id_for(@entry, @meta), value: @decode_description(@entry)
|
784
|
+
|
785
|
+
@decode = '' unless @decode?
|
786
|
+
# @dinfo.render.min_length == 0
|
749
787
|
|
750
788
|
load: (value) ->
|
751
|
-
if value
|
752
|
-
@invoke(query: value).then =>
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
@values
|
789
|
+
if _.isString(value)
|
790
|
+
@invoke(query: value).then => if @entries # ?
|
791
|
+
@values = @entries.map (e) => id: E2.id_for(e, @meta), value: @decode_description(e)
|
792
|
+
delete @entries
|
793
|
+
@values
|
757
794
|
|
758
795
|
clean: ->
|
759
|
-
|
796
|
+
@decode = ''
|
760
797
|
@clear_record()
|
761
798
|
|
762
799
|
many_to_one_list: class ManyToOneListAction extends ListAction
|
@@ -780,7 +817,7 @@ angular.module('Engine2')
|
|
780
817
|
star_to_many_list: class StarToManyList extends ListAction
|
781
818
|
initialize: ->
|
782
819
|
super()
|
783
|
-
@query.parent_id = @
|
820
|
+
@query.parent_id = @list_parent_action().current_id()
|
784
821
|
|
785
822
|
# link_list: implicit
|
786
823
|
item_menu_confirm_unlink: (args) ->
|
@@ -860,7 +897,7 @@ angular.module('Engine2')
|
|
860
897
|
else
|
861
898
|
pparent.changes.modify.push @parent().record
|
862
899
|
else # CreateAction
|
863
|
-
_(@parent().meta.primary_fields).each (k) => @parent().record[k] = E2.uuid(
|
900
|
+
_(@parent().meta.primary_fields).each (k) => @parent().record[k] = E2.uuid()
|
864
901
|
if draggable = pparent.meta.draggable
|
865
902
|
max = _.maxBy(pparent.entries, (e) -> e.position)
|
866
903
|
@parent().record[draggable.position_field] = if max then max[draggable.position_field] + 1 else 1
|
data/app/app.css
CHANGED
data/app/engine2.coffee
CHANGED
@@ -13,7 +13,7 @@ require 'angular-drag-and-drop-lists'
|
|
13
13
|
|
14
14
|
_.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
15
15
|
|
16
|
-
angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStrap', 'ngFileUpload', 'ui.tree', 'LocalStorageModule', 'angularLoad', 'ngWebSocket', 'ui.router', 'dndLists']) # 'ui.select'
|
16
|
+
angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStrap', 'ngFileUpload', 'ui.tree', 'LocalStorageModule', 'angularLoad', 'ngWebSocket', 'ui.router', 'dndLists', 'toastr']) # 'ui.select'
|
17
17
|
.config ($httpProvider, $compileProvider, localStorageServiceProvider, $logProvider, $qProvider, $locationProvider, $provide) ->
|
18
18
|
$httpProvider.interceptors.push 'e2HttpInterceptor'
|
19
19
|
$provide.decorator '$httpBackend', ($delegate) ->
|
@@ -44,6 +44,9 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
44
44
|
$delegate
|
45
45
|
|
46
46
|
.factory 'PushJS', -> require 'push.js'
|
47
|
+
.factory 'PrettyYAML', -> require 'json-to-pretty-yaml'
|
48
|
+
.filter 'yaml', (PrettyYAML) -> (input) -> PrettyYAML.stringify(input, 4)
|
49
|
+
|
47
50
|
.factory 'MetaCache', ($cacheFactory) -> $cacheFactory('MetaCache')
|
48
51
|
.factory 'e2HttpInterceptor', ($q, $injector, E2Snippets) ->
|
49
52
|
loaderToggle = (toggle) -> angular.element(document.querySelectorAll('.loader')).eq(-1).css("visibility", toggle)
|
@@ -97,7 +100,7 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
97
100
|
_.each(o.class, (v, k) -> out.push "'#{k}': #{v}") if o.class?
|
98
101
|
if out.length > 0 then "ng-class=\"{#{out.join(',')}}\"" else ""
|
99
102
|
|
100
|
-
.factory 'E2', ($templateCache, $http, E2Snippets, $q, $dateFormatter, $parse, PushJS, $state, $e2Modal) ->
|
103
|
+
.factory 'E2', ($templateCache, $http, E2Snippets, $q, $dateFormatter, $parse, PushJS, $state, $e2Modal, toastr) ->
|
101
104
|
globals:
|
102
105
|
element: (id) ->
|
103
106
|
element = document.querySelector(id)
|
@@ -107,11 +110,12 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
107
110
|
notification: (name, body, icon, timeoutx, on_close) ->
|
108
111
|
PushJS.create name, body: body, icon: icon, timeout: timeoutx, onClick: on_close
|
109
112
|
|
113
|
+
toastr: -> toastr
|
110
114
|
state: -> $state
|
111
115
|
modal: -> $e2Modal
|
112
116
|
|
113
117
|
uuid: (length) ->
|
114
|
-
Math.random().toString(
|
118
|
+
Math.random().toString(10).substr(2, 8)
|
115
119
|
|
116
120
|
compact: (o) ->
|
117
121
|
_.each o, (v, k) =>
|
@@ -125,17 +129,19 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
125
129
|
else if _.isObject(v) && !_.isDate(v)
|
126
130
|
@clean(v)
|
127
131
|
else
|
128
|
-
# delete o[k]
|
129
|
-
o[k] = null
|
132
|
+
o[k] = null # delete o[k]
|
130
133
|
|
131
|
-
|
134
|
+
merge_meta: (dst, src) ->
|
132
135
|
for k, v of src
|
133
136
|
throw "Attempted to override function '#{k}'" if _.isFunction(dst[k])
|
134
|
-
|
135
|
-
|
136
|
-
if insn == '!' then dst[k.slice(0, -1)] = v else dst[k] = @merge(dst[k] ? {}, v)
|
137
|
+
if (k == 'execute' || k == 'pre_execute') && dst[k] && src[k]
|
138
|
+
dst[k] = dst[k].concat(src[k])
|
137
139
|
else
|
138
|
-
|
140
|
+
insn = k.slice(-1)
|
141
|
+
if _.isObject(v) && !_.isArray(v)
|
142
|
+
if insn == '!' then dst[k.slice(0, -1)] = v else dst[k] = @merge_meta(dst[k] ? {}, v)
|
143
|
+
else
|
144
|
+
if insn == '?' then dst[k.slice(0, -1)] ?= v else dst[k] = v
|
139
145
|
dst
|
140
146
|
|
141
147
|
transpose: (a) ->
|
@@ -289,7 +295,7 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
289
295
|
if elem[0].type in ['text', 'password']
|
290
296
|
elem.on 'keypress', (ev) ->
|
291
297
|
scope.$apply ->
|
292
|
-
scope.action.panel_menu_default_action() if ev.keyCode == 13
|
298
|
+
scope.action.panel_menu_default_action?() if ev.keyCode == 13
|
293
299
|
|
294
300
|
ev.stopPropagation()
|
295
301
|
|
@@ -337,9 +343,13 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
337
343
|
scope: false
|
338
344
|
restrict: 'A'
|
339
345
|
link: (scope, elem, attrs) ->
|
346
|
+
table_scope = null
|
340
347
|
scope.$on 'render_table', (a, ev) ->
|
341
348
|
# ev.stopPropagation()
|
342
|
-
|
349
|
+
table_scope.$destroy() if table_scope
|
350
|
+
table_scope = scope.$new(false)
|
351
|
+
|
352
|
+
action = table_scope.action
|
343
353
|
meta = action.meta
|
344
354
|
draggable = meta.draggable
|
345
355
|
position = meta.menus.item_menu.properties.position ? 0
|
@@ -382,7 +392,7 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
382
392
|
|
383
393
|
tbody_attrs = if draggable then 'dnd-list=\"action.entries\" dnd-drop=\"action.entry_dropped(index, external, type)\"' else ''
|
384
394
|
elem.empty()
|
385
|
-
elem.append($compile(table_tmpl thead: thead, tbody: tbody, tbody_attrs: tbody_attrs)(
|
395
|
+
elem.append($compile(table_tmpl thead: thead, tbody: tbody, tbody_attrs: tbody_attrs)(table_scope))
|
386
396
|
|
387
397
|
.directive 'e2Dropdown', ($parse, $dropdown, $timeout, E2Snippets) ->
|
388
398
|
event_num = 0
|
@@ -466,7 +476,7 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
466
476
|
hide: m.hide && "ng-hide=\"#{m.hide}\"" || ''
|
467
477
|
icon: m.icon && E2Snippets.icon(m.icon) || ''
|
468
478
|
loc: !(m.button_loc == false) && m.loc || ''
|
469
|
-
title: (m.button_loc == false) && "title=\"#{m.loc}\"" || ''
|
479
|
+
title: if m.title then "title=\"#{m.title}\"" else ((m.button_loc == false) && "title=\"#{m.loc}\"" || '')
|
470
480
|
|
471
481
|
if menu.entries.length > brk
|
472
482
|
out += button_set_arr_tmpl
|
@@ -516,27 +526,35 @@ angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStr
|
|
516
526
|
when "decimal_date"
|
517
527
|
match = value.match(/^(\d{4}|\d{2})(\d{2})(\d{2})$/)
|
518
528
|
if match then match.slice(1, 4).join('-') else value
|
519
|
-
else
|
529
|
+
else
|
530
|
+
match = value.match(/(.*)(?:\s[-+]\d+)$/)
|
531
|
+
if match then match[1] else value
|
520
532
|
|
521
533
|
scope: true
|
522
534
|
require: 'ngModel'
|
523
535
|
link: (scope, element, attr, controller) ->
|
524
536
|
action = scope.action
|
525
537
|
mode = attr.e2Datepicker
|
538
|
+
has_mode = !_.isEmpty(mode)
|
526
539
|
field = scope.other_date ? scope.other_time ? scope.f
|
527
540
|
info = action.meta.fields[field]
|
528
541
|
|
529
542
|
if action.query
|
530
|
-
|
531
|
-
|
543
|
+
f = action.query.search[scope.f]
|
544
|
+
if has_mode
|
545
|
+
scope.value[mode] = parse(f[mode], info)
|
546
|
+
scope.$on "search_reset", -> scope.value[mode] = null
|
547
|
+
else
|
548
|
+
scope.value.at = parse(f, info)
|
549
|
+
scope.$on "search_reset", -> scope.value.at = null
|
532
550
|
else
|
533
551
|
value = parse(action.record[field], info)
|
534
|
-
if
|
552
|
+
if has_mode then scope.value[mode] = value else scope.value = value
|
535
553
|
|
536
554
|
scope.$watch attr.ngModel, (model, o) -> if model != o
|
537
555
|
date = format(model, attr.e2ModelFormat)
|
538
556
|
if action.query
|
539
|
-
action.query.search[scope.f][mode] = date
|
557
|
+
if has_mode then action.query.search[scope.f][mode] = date else action.query.search[scope.f] = date
|
540
558
|
scope.action.search_field_change(scope.f) if date?
|
541
559
|
else
|
542
560
|
action.record[field] = date
|