engine2 1.0.8 → 1.0.9
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.
- 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
|