engine2 1.0.4 → 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +0 -0
- data/Rakefile +4 -4
- data/app/{engine2actions.coffee → actions.coffee} +341 -215
- data/app/app.coffee +0 -0
- data/app/app.css +17 -0
- data/app/engine2.coffee +158 -208
- data/app/modal.coffee +138 -0
- data/bower.json +4 -2
- data/conf/message.yaml +5 -0
- data/conf/message_pl.yaml +7 -2
- data/config.coffee +24 -12
- data/engine2.gemspec +8 -8
- data/lib/engine2.rb +12 -10
- data/lib/engine2/action.rb +1338 -133
- data/lib/engine2/action/array.rb +189 -0
- data/lib/engine2/{meta/decode_meta.rb → action/decode.rb} +52 -21
- data/lib/engine2/action/delete.rb +64 -0
- data/lib/engine2/action/form.rb +16 -0
- data/lib/engine2/{meta/infra_meta.rb → action/infra.rb} +123 -89
- data/lib/engine2/action/link.rb +117 -0
- data/lib/engine2/action/list.rb +333 -0
- data/lib/engine2/action/save.rb +28 -0
- data/lib/engine2/action/view.rb +8 -0
- data/lib/engine2/action_node.rb +221 -0
- data/lib/engine2/core.rb +175 -87
- data/lib/engine2/handler.rb +14 -13
- data/lib/engine2/model.rb +85 -43
- data/lib/engine2/models/Files.rb +4 -1
- data/lib/engine2/models/UserInfo.rb +6 -3
- data/lib/engine2/post_bootstrap.rb +4 -3
- data/lib/engine2/pre_bootstrap.rb +10 -6
- data/lib/engine2/scheme.rb +107 -65
- data/lib/engine2/templates.rb +41 -6
- data/lib/engine2/type_info.rb +51 -23
- data/lib/engine2/version.rb +2 -1
- data/package.json +22 -16
- data/public/favicon.ico +0 -0
- data/public/img/ajax-loader-dark.gif +0 -0
- data/public/img/ajax-loader.gif +0 -0
- data/views/fields/blob.slim +1 -1
- data/views/fields/bs_select.slim +2 -2
- data/views/fields/bsselect_picker.slim +4 -4
- data/views/fields/bsselect_picker_opt.slim +5 -5
- data/views/fields/checkbox.slim +4 -4
- data/views/fields/checkbox_button.slim +6 -0
- data/views/fields/checkbox_buttons.slim +3 -3
- data/views/fields/checkbox_buttons_opt.slim +3 -3
- data/views/fields/currency.slim +2 -2
- data/views/fields/date.slim +4 -4
- data/views/fields/date_range.slim +9 -9
- data/views/fields/date_time.slim +9 -9
- data/views/fields/datetime.slim +8 -8
- data/views/fields/decimal.slim +1 -1
- data/views/fields/decimal_date.slim +3 -3
- data/views/fields/decimal_time.slim +3 -3
- data/views/fields/email.slim +3 -3
- data/views/fields/file_store.slim +11 -11
- data/views/fields/input_text.slim +4 -4
- data/views/fields/integer.slim +1 -1
- data/views/fields/list_bsmselect.slim +20 -0
- data/views/fields/list_bsselect.slim +5 -5
- data/views/fields/list_bsselect_opt.slim +6 -6
- data/views/fields/list_buttons.slim +1 -1
- data/views/fields/list_buttons_opt.slim +2 -2
- 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/list_select.slim +4 -4
- data/views/fields/list_select_opt.slim +5 -5
- data/views/fields/password.slim +4 -4
- data/views/fields/radio_checkbox.slim +3 -3
- data/views/fields/scaffold.slim +2 -2
- data/views/fields/scaffold_picker.slim +5 -5
- data/views/fields/select_picker.slim +3 -3
- data/views/fields/select_picker_opt.slim +4 -4
- data/views/fields/text_area.slim +4 -3
- data/views/fields/time.slim +5 -4
- data/views/fields/typeahead_picker.slim +12 -9
- data/views/index.slim +3 -3
- data/views/infra/index.slim +0 -0
- data/views/infra/inspect.slim +41 -10
- data/views/modals/close_m.slim +0 -0
- data/views/modals/confirm_m.slim +0 -0
- data/views/modals/empty_m.slim +0 -0
- data/views/modals/menu_m.slim +1 -1
- data/views/modals/yes_no_m.slim +0 -0
- data/views/panels/menu_m.slim +1 -1
- data/views/scaffold/confirm.slim +0 -0
- data/views/scaffold/fields.slim +6 -4
- data/views/scaffold/form.slim +1 -1
- data/views/scaffold/form_collapse.slim +4 -3
- data/views/scaffold/form_tabs.slim +3 -2
- data/views/scaffold/list.slim +0 -0
- data/views/scaffold/message.slim +0 -0
- data/views/scaffold/search.slim +4 -4
- data/views/scaffold/search_collapse.slim +8 -7
- data/views/scaffold/search_tabs.slim +6 -5
- data/views/scaffold/view.slim +2 -2
- data/views/scaffold/view_collapse.slim +5 -4
- data/views/scaffold/view_tabs.slim +4 -3
- data/views/search_fields/bsmselect_picker.slim +4 -4
- data/views/search_fields/bsselect_picker.slim +4 -4
- data/views/search_fields/checkbox.slim +3 -3
- data/views/search_fields/checkbox2.slim +5 -5
- data/views/search_fields/checkbox_buttons.slim +3 -3
- data/views/search_fields/date.slim +20 -0
- data/views/search_fields/date_range.slim +8 -8
- 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 +4 -4
- data/views/search_fields/list_bsselect.slim +4 -4
- data/views/search_fields/list_buttons.slim +2 -2
- data/views/search_fields/list_mbuttons.slim +12 -0
- data/views/search_fields/list_select.slim +3 -3
- data/views/search_fields/scaffold_picker.slim +2 -2
- data/views/search_fields/select_picker.slim +3 -3
- data/views/search_fields/typeahead_picker.slim +8 -7
- metadata +53 -48
- data/lib/engine2/meta.rb +0 -1216
- data/lib/engine2/meta/array_meta.rb +0 -82
- data/lib/engine2/meta/delete_meta.rb +0 -60
- data/lib/engine2/meta/form_meta.rb +0 -15
- data/lib/engine2/meta/link_meta.rb +0 -134
- data/lib/engine2/meta/list_meta.rb +0 -281
- data/lib/engine2/meta/save_meta.rb +0 -50
- data/lib/engine2/meta/view_meta.rb +0 -7
- data/public/__sinatra__/404.png +0 -0
- data/public/__sinatra__/500.png +0 -0
data/app/app.coffee
CHANGED
File without changes
|
data/app/app.css
CHANGED
@@ -61,6 +61,11 @@ tr.tr_hover {
|
|
61
61
|
font-weight:normal;
|
62
62
|
}
|
63
63
|
|
64
|
+
textarea {
|
65
|
+
/*white-space: nowrap;*/
|
66
|
+
white-space: pre-wrap;
|
67
|
+
}
|
68
|
+
|
64
69
|
/*.modal-backdrop{
|
65
70
|
position:fixed;
|
66
71
|
top:0;
|
@@ -201,3 +206,15 @@ button {
|
|
201
206
|
}*/
|
202
207
|
|
203
208
|
a[ng-click] {cursor:pointer;}
|
209
|
+
|
210
|
+
.dndDragging {
|
211
|
+
}
|
212
|
+
|
213
|
+
.dndDraggingSource {
|
214
|
+
}
|
215
|
+
|
216
|
+
.dndPlaceholder{
|
217
|
+
}
|
218
|
+
|
219
|
+
.dndDragover {
|
220
|
+
}
|
data/app/engine2.coffee
CHANGED
@@ -1,34 +1,71 @@
|
|
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/core'
|
8
|
+
require '@uirouter/angularjs'
|
8
9
|
require 'ng-file-upload'
|
10
|
+
require 'angular-load'
|
11
|
+
require 'angular-drag-and-drop-lists'
|
12
|
+
# require 'ui-select'
|
9
13
|
|
10
14
|
_.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
11
15
|
|
12
|
-
angular.module('Engine2', ['
|
13
|
-
.config ($httpProvider, $
|
14
|
-
loaderOn = -> angular.element(document.querySelectorAll('.loader')).eq(-1).css("visibility", 'visible')
|
16
|
+
angular.module('Engine2', ['ngSanitize', 'ngAnimate', 'ngCookies', 'mgcrea.ngStrap', 'ngFileUpload', 'ui.tree', 'LocalStorageModule', 'angularLoad', 'ngWebSocket', 'ui.router', 'dndLists', 'toastr']) # 'ui.select'
|
17
|
+
.config ($httpProvider, $compileProvider, localStorageServiceProvider, $logProvider, $qProvider, $locationProvider, $provide) ->
|
15
18
|
$httpProvider.interceptors.push 'e2HttpInterceptor'
|
16
|
-
$
|
17
|
-
|
18
|
-
|
19
|
+
$provide.decorator '$httpBackend', ($delegate) ->
|
20
|
+
(method, url, post, callback, headers, timeout, withCredentials, responseType) ->
|
21
|
+
url = url.replace(/;/g, '%3B') unless method == 'POST'
|
22
|
+
$delegate(method, url, post, callback, headers, timeout, withCredentials, responseType)
|
19
23
|
# $httpProvider.defaults.headers.common['Cache-Control'] = 'no-cache'
|
20
24
|
# $httpProvider.defaults.cache = false;
|
21
|
-
$httpProvider.defaults.headers.get
|
25
|
+
$httpProvider.defaults.headers.get ?= {} # if !$httpProvider.defaults.headers.get
|
22
26
|
$httpProvider.defaults.headers.get['If-Modified-Since'] = '0'
|
23
27
|
# localStorageServiceProvider.setStorageType('sessionStorage')
|
24
28
|
localStorageServiceProvider.setPrefix('E2')
|
25
29
|
$compileProvider.debugInfoEnabled(false)
|
26
30
|
$logProvider.debugEnabled(true)
|
27
31
|
$httpProvider.useApplyAsync(true)
|
28
|
-
# $
|
29
|
-
|
32
|
+
# $qProvider.errorOnUnhandledRejections(false)
|
33
|
+
# $locationProvider.hashPrefix('')
|
34
|
+
# $locationProvider.html5Mode(false)
|
35
|
+
$provide.decorator 'ngModelDirective', ($delegate) ->
|
36
|
+
directive = $delegate[0]
|
37
|
+
compile = directive.compile
|
38
|
+
directive.compile = (elem, attrs, trans) ->
|
39
|
+
comp = compile(elem, attrs, trans)
|
40
|
+
pre: comp.pre
|
41
|
+
post: (scope, element, attr, ctrls) ->
|
42
|
+
ctrls[0].$parsers.push (vw) -> if vw == "" then null else vw
|
43
|
+
comp.post(scope, element, attr, ctrls)
|
44
|
+
$delegate
|
45
|
+
|
46
|
+
.factory 'PushJS', -> require 'push.js'
|
47
|
+
.factory 'PrettyYAML', -> require 'json-to-pretty-yaml'
|
48
|
+
.filter 'yaml', (PrettyYAML) -> (input) -> PrettyYAML.stringify(input, 4)
|
49
|
+
|
50
|
+
.factory 'MetaCache', ($cacheFactory) -> $cacheFactory('MetaCache')
|
30
51
|
.factory 'e2HttpInterceptor', ($q, $injector, E2Snippets) ->
|
31
|
-
|
52
|
+
loaderToggle = (toggle) -> angular.element(document.querySelectorAll('.loader')).eq(-1).css("visibility", toggle)
|
53
|
+
loaderOn = -> loaderToggle('visible')
|
54
|
+
timeout = null
|
55
|
+
loaderOff = ->
|
56
|
+
if timeout
|
57
|
+
clearTimeout timeout
|
58
|
+
timeout = null
|
59
|
+
loaderToggle('hidden')
|
60
|
+
|
61
|
+
request: (request) ->
|
62
|
+
if timeout
|
63
|
+
clearTimeout timeout
|
64
|
+
timeout = null
|
65
|
+
else
|
66
|
+
timeout = setTimeout(loaderOn, 200)
|
67
|
+
request
|
68
|
+
|
32
69
|
response: (response) ->
|
33
70
|
loaderOff()
|
34
71
|
response
|
@@ -47,21 +84,38 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
47
84
|
$q.reject(response)
|
48
85
|
|
49
86
|
.factory 'E2Snippets', ->
|
50
|
-
icon = (name) ->
|
51
|
-
|
87
|
+
icon = (name) ->
|
88
|
+
if name.slice(0, 3) == 'fa_'
|
89
|
+
"<i class='fa fa-#{name.slice(3)}'></i>"
|
90
|
+
else
|
91
|
+
"<span class='glyphicon glyphicon-#{name}'></span>"
|
92
|
+
|
52
93
|
ng_class_names = ['active', 'enabled', 'disabled']
|
53
94
|
icon: icon
|
54
|
-
aicon: aicon
|
55
95
|
boolean_true_value: icon('check')
|
56
96
|
boolean_false_value: icon('unchecked')
|
57
97
|
make_ng_class: (o) ->
|
58
98
|
out = []
|
59
99
|
_.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?
|
100
|
+
_.each(o.class, (v, k) -> out.push "'#{k}': #{v}") if o.class?
|
61
101
|
if out.length > 0 then "ng-class=\"{#{out.join(',')}}\"" else ""
|
62
102
|
|
63
|
-
.factory 'E2', ($templateCache, $http, E2Snippets, $
|
64
|
-
globals:
|
103
|
+
.factory 'E2', ($templateCache, $http, E2Snippets, $q, $dateFormatter, $parse, PushJS, $state, $e2Modal, toastr) ->
|
104
|
+
globals:
|
105
|
+
element: (id) ->
|
106
|
+
element = document.querySelector(id)
|
107
|
+
console.warn "Element #{id} not found" unless element
|
108
|
+
element
|
109
|
+
|
110
|
+
notification: (name, body, icon, timeoutx, on_close) ->
|
111
|
+
PushJS.create name, body: body, icon: icon, timeout: timeoutx, onClick: on_close
|
112
|
+
|
113
|
+
toastr: -> toastr
|
114
|
+
state: -> $state
|
115
|
+
modal: -> $e2Modal
|
116
|
+
|
117
|
+
uuid: (length) ->
|
118
|
+
Math.random().toString(10).substr(2, 8)
|
65
119
|
|
66
120
|
compact: (o) ->
|
67
121
|
_.each o, (v, k) =>
|
@@ -75,18 +129,19 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
75
129
|
else if _.isObject(v) && !_.isDate(v)
|
76
130
|
@clean(v)
|
77
131
|
else
|
78
|
-
# delete o[k]
|
79
|
-
o[k] = null
|
132
|
+
o[k] = null # delete o[k]
|
80
133
|
|
81
|
-
|
134
|
+
merge_meta: (dst, src) ->
|
82
135
|
for k, v of src
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
else
|
87
|
-
dst[k] = @merge(dst[k] ? {}, v)
|
136
|
+
throw "Attempted to override function '#{k}'" if _.isFunction(dst[k])
|
137
|
+
if (k == 'execute' || k == 'pre_execute') && dst[k] && src[k]
|
138
|
+
dst[k] = dst[k].concat(src[k])
|
88
139
|
else
|
89
|
-
|
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
|
90
145
|
dst
|
91
146
|
|
92
147
|
transpose: (a) ->
|
@@ -98,7 +153,6 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
98
153
|
from_id: (id, meta) -> _.zipObject(meta.primary_fields, id) # _.zip(meta.primary_fields, id).reduce(((rec, [k, v]) -> rec[k] = v; rec), {})
|
99
154
|
|
100
155
|
icon: E2Snippets.icon
|
101
|
-
aicon: E2Snippets.aicon
|
102
156
|
|
103
157
|
fetch_template: (template) ->
|
104
158
|
$q.when($templateCache.get(template) || $http.get(template)).then (res) ->
|
@@ -137,11 +191,21 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
137
191
|
processor.arg_fun(action, arg)
|
138
192
|
action.scope().$eval(click)
|
139
193
|
else
|
140
|
-
action[fun_name]
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
194
|
+
if ofun = action[fun_name]
|
195
|
+
action["#{fun_name}_super"] = (args) ->
|
196
|
+
_.merge(args, $parse(m.arguments)(action.scope())) if m.arguments?
|
197
|
+
action.invoke_action(m.name, args)
|
198
|
+
|
199
|
+
action[fun_name] = (args) ->
|
200
|
+
processor.arg_fun(action, args)
|
201
|
+
args = processor.arg_ret(action)
|
202
|
+
ofun.bind(action)(args)
|
203
|
+
else
|
204
|
+
action[fun_name] = (arg) ->
|
205
|
+
processor.arg_fun(action, arg)
|
206
|
+
args = processor.arg_ret(action)
|
207
|
+
_.merge(args, $parse(m.arguments)(action.scope())) if m.arguments?
|
208
|
+
action.invoke_action(m.name, args)
|
145
209
|
|
146
210
|
if action.find_action_info(m.name, false)?
|
147
211
|
show = if m.show then " && " + m.show else ""
|
@@ -167,11 +231,14 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
167
231
|
when render.true_value then E2Snippets.boolean_true_value
|
168
232
|
when render.false_value then E2Snippets.boolean_false_value
|
169
233
|
else "?"
|
170
|
-
list_select: (value, render) ->
|
171
|
-
render.list_hash ||= render.
|
172
|
-
render.
|
234
|
+
list_select: (value, render, separator) ->
|
235
|
+
render.list_hash ||= render.values.reduce(((h, [a, b]) -> h[a] = b; h), {})
|
236
|
+
if render.multiselect && _.isArray(value)
|
237
|
+
value.map((v) -> render.list_hash[v] ? ":#{value}:").join(separator)
|
238
|
+
else
|
239
|
+
render.list_hash[value] ? ":#{value}:"
|
173
240
|
datetime: (value, render) ->
|
174
|
-
value.split('\.')[0]
|
241
|
+
value.split('\.')[0].split(' ', 2).join(' ')
|
175
242
|
# $dateFormatter.formatDate(value, "yyyy-MM-dd", $dateFormatter.getDefaultLocale())
|
176
243
|
integer: (value, render) -> # ?
|
177
244
|
value.toString()
|
@@ -186,12 +253,12 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
186
253
|
value.toString()
|
187
254
|
|
188
255
|
|
189
|
-
render_field: (entry, name, meta) ->
|
256
|
+
render_field: (entry, name, meta, separator) ->
|
190
257
|
value = entry[name]
|
191
|
-
if value? && info = meta.
|
258
|
+
if value? && info = meta.fields
|
192
259
|
f_info = info[name]
|
193
260
|
if f_info? && type = f_info.type
|
194
|
-
@renderers[type](value, f_info.render)
|
261
|
+
@renderers[type](value, f_info.render, separator)
|
195
262
|
else
|
196
263
|
if f_info?.escape == false then value else
|
197
264
|
(value + "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")
|
@@ -206,138 +273,6 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
206
273
|
parser = @parsers[info.type]
|
207
274
|
if parser then parser(value, info) else value
|
208
275
|
|
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
276
|
.directive 'e2Field', ($timeout, $filter) ->
|
342
277
|
require: 'ngModel'
|
343
278
|
restrict: 'A'
|
@@ -347,7 +282,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
347
282
|
|
348
283
|
name = attrs.e2Field || scope.f
|
349
284
|
meta = scope.action.meta
|
350
|
-
info = meta.
|
285
|
+
info = meta.fields[name]
|
351
286
|
scope.$on "focus_field", (event, n, mode) ->
|
352
287
|
if n == name
|
353
288
|
elem[0].focus()
|
@@ -360,8 +295,8 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
360
295
|
if elem[0].type in ['text', 'password']
|
361
296
|
elem.on 'keypress', (ev) ->
|
362
297
|
scope.$apply ->
|
363
|
-
|
364
|
-
|
298
|
+
scope.action.panel_menu_default_action?() if ev.keyCode == 13
|
299
|
+
|
365
300
|
ev.stopPropagation()
|
366
301
|
|
367
302
|
if info.filter
|
@@ -380,7 +315,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
380
315
|
link: (scope, elem, attrs, controller) ->
|
381
316
|
name = attrs.e2Field || scope.f
|
382
317
|
meta = scope.action.meta
|
383
|
-
info = meta.
|
318
|
+
info = meta.fields[name]
|
384
319
|
if info.filter
|
385
320
|
filter = $filter(info.filter)
|
386
321
|
controller.$parsers.push (value) ->
|
@@ -397,37 +332,43 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
397
332
|
scope: false
|
398
333
|
link: (scope, elem, attrs) ->
|
399
334
|
name = $parse(attrs.template)(scope)
|
400
|
-
$http.get(name, cache: $templateCache).
|
335
|
+
$http.get(name, cache: $templateCache).then (response) ->
|
401
336
|
# elem.html($compile(body)(scope))
|
402
337
|
# elem.replaceWith($compile(body)(scope))
|
403
338
|
elem.empty()
|
404
|
-
elem.after($compile(
|
339
|
+
elem.after($compile(response.data)(scope))
|
405
340
|
|
406
341
|
.directive 'e2TableBody', ($parse, $compile) ->
|
407
|
-
table_tmpl = _.template("<thead><tr>{{thead}}</tr></thead><tbody>{{tbody}}</tbody>")
|
342
|
+
table_tmpl = _.template("<thead><tr>{{thead}}</tr></thead><tbody {{tbody_attrs}}>{{tbody}}</tbody>")
|
408
343
|
scope: false
|
409
344
|
restrict: 'A'
|
410
345
|
link: (scope, elem, attrs) ->
|
346
|
+
table_scope = null
|
411
347
|
scope.$on 'render_table', (a, ev) ->
|
412
348
|
# ev.stopPropagation()
|
413
|
-
|
349
|
+
table_scope.$destroy() if table_scope
|
350
|
+
table_scope = scope.$new(false)
|
351
|
+
|
352
|
+
action = table_scope.action
|
414
353
|
meta = action.meta
|
354
|
+
draggable = meta.draggable
|
415
355
|
position = meta.menus.item_menu.properties.position ? 0
|
416
|
-
right_style = if position >= meta.
|
356
|
+
right_style = if position >= meta.field_list.length then "style=\"text-align: right\"" else ""
|
417
357
|
|
418
358
|
thead = ""
|
419
|
-
fields = meta.
|
359
|
+
fields = meta.field_list.slice()
|
420
360
|
fields.splice(position, 0, null)
|
421
361
|
_.each fields, (f) ->
|
422
362
|
if f
|
423
|
-
info = meta.
|
363
|
+
info = meta.fields[f]
|
424
364
|
thead += "<th>"
|
425
365
|
title = if info.title then "title=\"#{info.title}\"" else ""
|
426
366
|
if info.sort
|
427
367
|
thead += "<a ng-click=\"action.order('#{f}')\" #{title}><strong>#{info.loc}</strong></a>"
|
428
|
-
if action.ui.order == f
|
429
|
-
|
430
|
-
|
368
|
+
thead += if action.ui.order == f
|
369
|
+
" <span class=\"fa fa-arrow-#{if action.ui.asc then "up" else "down"}\"></span>"
|
370
|
+
else
|
371
|
+
" <span class=\"fa fa-sort\"></span>"
|
431
372
|
else
|
432
373
|
thead += "<span #{title}>#{info.loc}</span>"
|
433
374
|
thead += "</th>"
|
@@ -438,25 +379,27 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
438
379
|
_.each action.entries, (e, i) ->
|
439
380
|
tbody += if action.selection then "<tr ng-class=\"action.selected_class(#{i})\" class=\"tr_hover\" ng-click=\"action.select(#{i}, $event)\">" else
|
440
381
|
row_cls = e.$row_info?.class
|
441
|
-
if
|
382
|
+
tr_attrs = if draggable then "dnd-draggable=\"action.entries[#{i}]\" dnd-dragstart=\"action.entry_moved(#{i})\"" else ''
|
383
|
+
if row_cls then "<tr class=\"#{row_cls}\" #{tr_attrs}>" else "<tr #{tr_attrs}>"
|
442
384
|
_.each fields, (f) ->
|
443
385
|
if f
|
444
|
-
tbody += if col_cls = meta.
|
386
|
+
tbody += if col_cls = meta.fields[f].column_class then "<td class=\"#{col_cls}\">" else "<td>"
|
445
387
|
tbody += action.list_cell(e, f) ? ''
|
446
388
|
tbody += "</td>"
|
447
389
|
else
|
448
390
|
tbody += "<td #{right_style}><div e2-button-set=\"action.meta.menus.item_menu\" index=\"#{i}\"></div></td>"
|
449
391
|
tbody += "</tr>"
|
450
392
|
|
393
|
+
tbody_attrs = if draggable then 'dnd-list=\"action.entries\" dnd-drop=\"action.entry_dropped(index, external, type)\"' else ''
|
451
394
|
elem.empty()
|
452
|
-
elem.append($compile(table_tmpl thead: thead, tbody: tbody)(
|
395
|
+
elem.append($compile(table_tmpl thead: thead, tbody: tbody, tbody_attrs: tbody_attrs)(table_scope))
|
453
396
|
|
454
397
|
.directive 'e2Dropdown', ($parse, $dropdown, $timeout, E2Snippets) ->
|
455
398
|
event_num = 0
|
456
|
-
dropdown_sub_tmpl = _.template("<li class='dropdown-submenu'><a href=''> {{icon}}
|
457
|
-
dropdown_tmpl = _.template("<li {{clazz}} {{show}} {{hide}}> <a
|
399
|
+
dropdown_sub_tmpl = _.template("<li class='dropdown-submenu' {{show}} {{hide}}><a href=''> {{icon}} {{loc}}</a>{{sub}}</li>")
|
400
|
+
dropdown_tmpl = _.template("<li {{clazz}} {{show}} {{hide}} {{active}}> <a {{href}} {{click}}> {{icon}} {{loc}}</a></li>")
|
458
401
|
|
459
|
-
render = (menu,
|
402
|
+
render = (menu, nav) ->
|
460
403
|
out = menu.map (m) ->
|
461
404
|
switch
|
462
405
|
when m.divider
|
@@ -464,18 +407,19 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
464
407
|
when m.menu
|
465
408
|
dropdown_sub_tmpl
|
466
409
|
icon: m.menu.icon && E2Snippets.icon(m.menu.icon) || ''
|
467
|
-
aicon: m.menu.aicon && E2Snippets.aicon(m.menu.aicon) || ''
|
468
410
|
loc: m.menu.loc
|
469
|
-
|
411
|
+
show: m.menu.show && "ng-show=\"#{m.menu.show}\"" || ''
|
412
|
+
hide: m.menu.hide && "ng-hide=\"#{m.menu.hide}\"" || ''
|
413
|
+
sub: render(m.menu.entries, nav)
|
470
414
|
else
|
471
415
|
dropdown_tmpl
|
472
416
|
clazz: E2Snippets.make_ng_class(m)
|
473
417
|
show: m.show && "ng-show=\"#{m.show}\"" || ''
|
474
418
|
hide: m.hide && "ng-hide=\"#{m.hide}\"" || ''
|
475
|
-
href: m.href || ''
|
419
|
+
href: m.href && "#{if nav then 'ui-sref' else 'href'}=\"#{m.href}\"" || ''
|
420
|
+
active: nav && "ui-sref-active='active'" || ''
|
476
421
|
click: m.click && "ng-click=\"#{m.click}\"" || ''
|
477
422
|
icon: m.icon && E2Snippets.icon(m.icon) || ''
|
478
|
-
aicon: m.aicon && E2Snippets.aicon(m.aicon) || ''
|
479
423
|
loc: m.loc
|
480
424
|
"<ul class='dropdown-menu'>#{out.join('')}</ul>"
|
481
425
|
|
@@ -489,7 +433,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
489
433
|
# event.preventDefault()
|
490
434
|
# event.stopPropagation()
|
491
435
|
menu = $parse(attrs.e2Dropdown)(scope)
|
492
|
-
dropdown = $dropdown(elem, (scope: scope, template: render(menu,
|
436
|
+
dropdown = $dropdown(elem, (scope: scope, template: render(menu, attrs.nav?), animation: attrs.animation || 'am-flip-x', prefixEvent: "#{event_num}.tooltip")) # , delay: 1
|
493
437
|
dropdown.$promise.then ->
|
494
438
|
event_hide = scope.$on "#{event_num}.tooltip.hide", (e) ->
|
495
439
|
e.stopPropagation()
|
@@ -505,8 +449,8 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
505
449
|
elem.on "mousedown", hook
|
506
450
|
|
507
451
|
.directive 'e2ButtonSet', ($parse, $compile, E2Snippets) ->
|
508
|
-
button_set_tmpl = _.template("<div class='btn btn-default' {{clazz}} {{click}} {{show}} {{hide}} {{title}}> {{icon}}
|
509
|
-
button_set_arr_tmpl = _.template("<div class='btn btn-default' e2-dropdown='{{dropdown}}' data-animation='{{animation}}'>{{icon}}
|
452
|
+
button_set_tmpl = _.template("<div class='btn btn-default' {{clazz}} {{click}} {{show}} {{hide}} {{title}}> {{icon}} {{loc}}</div>")
|
453
|
+
button_set_arr_tmpl = _.template("<div class='btn btn-default' e2-dropdown='{{dropdown}}' data-animation='{{animation}}'>{{icon}}<span class='caret'></span></div>")
|
510
454
|
scope: true # because $index
|
511
455
|
link: (scope, elem, attrs) ->
|
512
456
|
menu = $parse(attrs.e2ButtonSet)(scope)
|
@@ -523,7 +467,6 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
523
467
|
dropdown: "#{attrs.e2ButtonSet}.entries[#{i}].menu.entries"
|
524
468
|
animation: animation
|
525
469
|
icon: m.menu.icon && "#{E2Snippets.icon(m.menu.icon)} " || ''
|
526
|
-
aicon: m.menu.aicon && "#{E2Snippets.aicon(m.menu.aicon)} " || ''
|
527
470
|
else if m.divider
|
528
471
|
else
|
529
472
|
out += button_set_tmpl
|
@@ -532,21 +475,20 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
532
475
|
show: m.show && "ng-show=\"#{m.show}\"" || ''
|
533
476
|
hide: m.hide && "ng-hide=\"#{m.hide}\"" || ''
|
534
477
|
icon: m.icon && E2Snippets.icon(m.icon) || ''
|
535
|
-
aicon: m.aicon && E2Snippets.aicon(m.aicon) || ''
|
536
478
|
loc: !(m.button_loc == false) && m.loc || ''
|
537
|
-
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}\"" || '')
|
538
480
|
|
539
481
|
if menu.entries.length > brk
|
540
482
|
out += button_set_arr_tmpl
|
541
483
|
dropdown: "#{attrs.e2ButtonSet}.entries.slice(#{brk})"
|
542
484
|
animation: animation
|
543
485
|
icon: ''
|
544
|
-
aicon: ''
|
545
486
|
|
546
487
|
out = "<div class='btn-group #{group_class}'>#{out}</div>"
|
547
488
|
out = $compile(angular.element(out))(scope)
|
548
489
|
if attrs.index && !scope.$index?
|
549
490
|
scope.$index = attrs.index | 0
|
491
|
+
scope.$entry = scope.action.entries[scope.$index]
|
550
492
|
# scope.data = attrs.data
|
551
493
|
elem.after(out) # elem.append(out) # elem.replaceWith(out)
|
552
494
|
|
@@ -584,27 +526,35 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm
|
|
584
526
|
when "decimal_date"
|
585
527
|
match = value.match(/^(\d{4}|\d{2})(\d{2})(\d{2})$/)
|
586
528
|
if match then match.slice(1, 4).join('-') else value
|
587
|
-
else
|
529
|
+
else
|
530
|
+
match = value.match(/(.*)(?:\s[-+]\d+)$/)
|
531
|
+
if match then match[1] else value
|
588
532
|
|
589
533
|
scope: true
|
590
534
|
require: 'ngModel'
|
591
535
|
link: (scope, element, attr, controller) ->
|
592
536
|
action = scope.action
|
593
537
|
mode = attr.e2Datepicker
|
538
|
+
has_mode = !_.isEmpty(mode)
|
594
539
|
field = scope.other_date ? scope.other_time ? scope.f
|
595
|
-
info = action.meta.
|
540
|
+
info = action.meta.fields[field]
|
596
541
|
|
597
542
|
if action.query
|
598
|
-
|
599
|
-
|
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
|
600
550
|
else
|
601
551
|
value = parse(action.record[field], info)
|
602
|
-
if
|
552
|
+
if has_mode then scope.value[mode] = value else scope.value = value
|
603
553
|
|
604
554
|
scope.$watch attr.ngModel, (model, o) -> if model != o
|
605
555
|
date = format(model, attr.e2ModelFormat)
|
606
556
|
if action.query
|
607
|
-
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
|
608
558
|
scope.action.search_field_change(scope.f) if date?
|
609
559
|
else
|
610
560
|
action.record[field] = date
|