engine2 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/Rakefile +138 -0
- data/conf/message.yaml +93 -0
- data/conf/message_pl.yaml +93 -0
- data/engine2.gemspec +34 -0
- data/lib/engine2.rb +34 -0
- data/lib/engine2/action.rb +217 -0
- data/lib/engine2/core.rb +572 -0
- data/lib/engine2/handler.rb +134 -0
- data/lib/engine2/meta.rb +969 -0
- data/lib/engine2/meta/decode_meta.rb +110 -0
- data/lib/engine2/meta/delete_meta.rb +73 -0
- data/lib/engine2/meta/form_meta.rb +144 -0
- data/lib/engine2/meta/infra_meta.rb +292 -0
- data/lib/engine2/meta/link_meta.rb +133 -0
- data/lib/engine2/meta/list_meta.rb +284 -0
- data/lib/engine2/meta/save_meta.rb +63 -0
- data/lib/engine2/meta/view_meta.rb +22 -0
- data/lib/engine2/model.rb +390 -0
- data/lib/engine2/models/Files.rb +38 -0
- data/lib/engine2/models/UserInfo.rb +24 -0
- data/lib/engine2/post_bootstrap.rb +83 -0
- data/lib/engine2/pre_bootstrap.rb +27 -0
- data/lib/engine2/scheme.rb +202 -0
- data/lib/engine2/templates.rb +229 -0
- data/lib/engine2/type_info.rb +342 -0
- data/lib/engine2/version.rb +9 -0
- data/public/assets/javascripts.js +13 -0
- data/public/assets/styles.css +4 -0
- data/public/css/angular-motion.css +1022 -0
- data/public/css/angular-ui-tree.min.css +1 -0
- data/public/css/app.css +196 -0
- data/public/css/bootstrap-additions.css +1560 -0
- data/public/css/bootstrap.min.css +11 -0
- data/public/css/font-awesome.min.css +4 -0
- data/public/favicon.ico +0 -0
- data/public/fonts/FontAwesome.otf +0 -0
- data/public/fonts/fontawesome-webfont.eot +0 -0
- data/public/fonts/fontawesome-webfont.svg +655 -0
- 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 +288 -0
- 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-dark.gif +0 -0
- data/public/img/ajax-loader-light.gif +0 -0
- data/public/img/ajax-loader.gif +0 -0
- data/public/js/angular-animate.js +4115 -0
- data/public/js/angular-cookies.js +322 -0
- data/public/js/angular-local-storage.js +455 -0
- data/public/js/angular-route.js +1022 -0
- data/public/js/angular-sanitize.js +717 -0
- data/public/js/angular-strap.js +4339 -0
- data/public/js/angular-strap.tpl.js +43 -0
- data/public/js/angular-ui-tree.js +1569 -0
- data/public/js/angular.js +30714 -0
- data/public/js/i18n/angular-locale_pl.js +115 -0
- data/public/js/lodash.custom.min.js +97 -0
- data/public/js/ng-file-upload-shim.min.js +2 -0
- data/public/js/ng-file-upload.min.js +3 -0
- data/views/app.coffee +3 -0
- data/views/engine2.coffee +557 -0
- data/views/engine2actions.coffee +849 -0
- data/views/engine2templates.coffee +0 -0
- data/views/fields/blob.slim +22 -0
- data/views/fields/bs_select.slim +10 -0
- data/views/fields/bsselect_picker.slim +18 -0
- data/views/fields/bsselect_picker_opt.slim +22 -0
- data/views/fields/checkbox.slim +11 -0
- data/views/fields/checkbox_buttons.slim +6 -0
- data/views/fields/checkbox_buttons_opt.slim +8 -0
- data/views/fields/currency.slim +10 -0
- data/views/fields/date.slim +21 -0
- data/views/fields/date_range.slim +44 -0
- data/views/fields/date_time.slim +42 -0
- data/views/fields/datetime.slim +42 -0
- data/views/fields/decimal.slim +11 -0
- data/views/fields/decimal_date.slim +22 -0
- data/views/fields/decimal_time.slim +26 -0
- data/views/fields/email.slim +13 -0
- data/views/fields/file_store.slim +61 -0
- data/views/fields/input_text.slim +14 -0
- data/views/fields/integer.slim +11 -0
- data/views/fields/list_bsselect.slim +18 -0
- data/views/fields/list_bsselect_opt.slim +21 -0
- data/views/fields/list_buttons.slim +3 -0
- data/views/fields/list_buttons_opt.slim +5 -0
- data/views/fields/list_select.slim +11 -0
- data/views/fields/list_select_opt.slim +15 -0
- data/views/fields/password.slim +14 -0
- data/views/fields/radio_checkbox.slim +10 -0
- data/views/fields/scaffold.slim +2 -0
- data/views/fields/scaffold_picker.slim +20 -0
- data/views/fields/select_picker.slim +12 -0
- data/views/fields/select_picker_opt.slim +16 -0
- data/views/fields/text_area.slim +10 -0
- data/views/fields/time.slim +22 -0
- data/views/fields/typeahead_picker.slim +25 -0
- data/views/index.slim +44 -0
- data/views/infra/index.slim +5 -0
- data/views/infra/inspect.slim +81 -0
- data/views/modals/close_m.slim +15 -0
- data/views/modals/confirm_m.slim +19 -0
- data/views/modals/empty_m.slim +12 -0
- data/views/modals/menu_m.slim +13 -0
- data/views/modals/yes_no_m.slim +19 -0
- data/views/panels/menu_m.slim +9 -0
- data/views/scaffold/confirm.slim +3 -0
- data/views/scaffold/fields.slim +10 -0
- data/views/scaffold/form.slim +11 -0
- data/views/scaffold/list.slim +42 -0
- data/views/scaffold/message.slim +3 -0
- data/views/scaffold/search.slim +20 -0
- data/views/scaffold/view.slim +18 -0
- data/views/search_fields/bsmselect_picker.slim +25 -0
- data/views/search_fields/bsselect_picker.slim +24 -0
- data/views/search_fields/checkbox.slim +11 -0
- data/views/search_fields/checkbox2.slim +14 -0
- data/views/search_fields/checkbox_buttons.slim +10 -0
- data/views/search_fields/date_range.slim +46 -0
- data/views/search_fields/decimal_date_range.slim +47 -0
- data/views/search_fields/input_text.slim +18 -0
- data/views/search_fields/integer.slim +18 -0
- data/views/search_fields/integer_range.slim +27 -0
- data/views/search_fields/list_bsmselect.slim +24 -0
- data/views/search_fields/list_bsselect.slim +22 -0
- data/views/search_fields/list_buttons.slim +8 -0
- data/views/search_fields/list_select.slim +17 -0
- data/views/search_fields/scaffold_picker.slim +19 -0
- data/views/search_fields/select_picker.slim +17 -0
- data/views/search_fields/typeahead_picker.slim +25 -0
- metadata +327 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Engine2
|
4
|
+
class StarToManyLinkMeta < Meta
|
5
|
+
include MetaModelSupport
|
6
|
+
http_method :post
|
7
|
+
meta_type :star_to_many_link
|
8
|
+
|
9
|
+
def invoke handler
|
10
|
+
json = handler.post_to_json
|
11
|
+
parent = json[:parent_id]
|
12
|
+
ids = json[:ids]
|
13
|
+
handler.permit parent && ids
|
14
|
+
model = assets[:model]
|
15
|
+
assoc = assets[:assoc]
|
16
|
+
case assoc[:type]
|
17
|
+
when :one_to_many
|
18
|
+
model.db.transaction do
|
19
|
+
self.class.one_to_many_link_db model, assoc, split_keys(parent), ids
|
20
|
+
end
|
21
|
+
{}
|
22
|
+
when :many_to_many
|
23
|
+
self.class.many_to_many_link_db model, assoc, split_keys(parent), ids
|
24
|
+
{}
|
25
|
+
else unsupported_association
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.one_to_many_link_db model, assoc, parent, ids
|
30
|
+
pk = Hash[assoc[:keys].zip(parent)]
|
31
|
+
ids.each do |id|
|
32
|
+
model.where(model.primary_keys_hash(Sequel::split_keys(id))).update(pk)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.many_to_many_link_db model, assoc, parent, ids
|
37
|
+
p_pk = Hash[assoc[:left_keys].zip(parent)]
|
38
|
+
values = ids.map do |id|
|
39
|
+
p_pk.merge Hash[assoc[:right_keys].zip(Sequel::split_keys(id))]
|
40
|
+
end
|
41
|
+
model.db[assoc[:join_table]].multi_insert values
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class StarToManyUnlinkMetaBase < Meta
|
46
|
+
include MetaModelSupport
|
47
|
+
http_method :delete
|
48
|
+
|
49
|
+
def one_to_many_unlink_db handler, ids
|
50
|
+
model = assets[:model]
|
51
|
+
assoc = assets[:assoc]
|
52
|
+
keys = assoc[:keys]
|
53
|
+
if keys.all?{|k|model.db_schema[k][:allow_null] == true}
|
54
|
+
model.db.transaction do
|
55
|
+
self.class.one_to_many_unlink_db model, assoc, ids
|
56
|
+
end
|
57
|
+
{}
|
58
|
+
else
|
59
|
+
handler.halt_method_not_allowed LOCS[:"non_nullable"]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.one_to_many_unlink_db model, assoc, ids
|
64
|
+
keys = assoc[:keys]
|
65
|
+
ids.each do |id|
|
66
|
+
model.where(model.primary_keys_hash(Sequel::split_keys(id))).update(Hash[keys.zip([nil])])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def many_to_many_unlink_db parent, ids
|
71
|
+
model = assets[:model]
|
72
|
+
assoc = assets[:assoc]
|
73
|
+
|
74
|
+
model.db.transaction do
|
75
|
+
self.class.many_to_many_unlink_db model, assoc, Sequel::split_keys(parent), ids
|
76
|
+
end
|
77
|
+
{}
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.many_to_many_unlink_db model, assoc, parent, ids
|
81
|
+
p_pk = Hash[assoc[:left_keys].zip(parent)]
|
82
|
+
ds = model.db[assoc[:join_table]]
|
83
|
+
ids.each do |id|
|
84
|
+
ds.where(p_pk, Hash[assoc[:right_keys].zip(Sequel::split_keys(id))]).delete
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class StarToManyUnlinkMeta < StarToManyUnlinkMetaBase
|
90
|
+
meta_type :star_to_many_unlink
|
91
|
+
|
92
|
+
def pre_run
|
93
|
+
super
|
94
|
+
action.parent.parent.*.menu(:item_menu).option :confirm_unlink, icon: "minus", show: "action.selected_size() == 0", button_loc: false
|
95
|
+
end
|
96
|
+
|
97
|
+
def invoke handler
|
98
|
+
handler.permit id = handler.params[:id]
|
99
|
+
assoc = assets[:assoc]
|
100
|
+
case assoc[:type]
|
101
|
+
when :one_to_many
|
102
|
+
one_to_many_unlink_db(handler, [id])
|
103
|
+
when :many_to_many
|
104
|
+
handler.permit parent = handler.params[:parent_id]
|
105
|
+
many_to_many_unlink_db(parent, [id])
|
106
|
+
else unsupported_association
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class StarToManyBulkUnlinkMeta < StarToManyUnlinkMetaBase
|
112
|
+
meta_type :star_to_many_bulk_unlink
|
113
|
+
|
114
|
+
def pre_run
|
115
|
+
super
|
116
|
+
action.parent.parent.*.menu(:menu).option_after :default_order, :confirm_bulk_unlink, icon: "minus", show: "action.selected_size() > 0", button_loc: false
|
117
|
+
end
|
118
|
+
|
119
|
+
def invoke handler
|
120
|
+
ids = handler.param_to_json(:ids)
|
121
|
+
handler.permit ids.is_a?(Array)
|
122
|
+
assoc = assets[:assoc]
|
123
|
+
case assoc[:type]
|
124
|
+
when :one_to_many
|
125
|
+
one_to_many_unlink_db(handler, ids)
|
126
|
+
when :many_to_many
|
127
|
+
handler.permit parent = handler.params[:parent_id]
|
128
|
+
many_to_many_unlink_db(parent, ids)
|
129
|
+
else unsupported_association
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,284 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Engine2
|
4
|
+
class ListMeta < Meta
|
5
|
+
meta_type :list
|
6
|
+
include MetaListSupport, MetaQuerySupport
|
7
|
+
|
8
|
+
(DefaultFilters ||= {}).merge!(
|
9
|
+
string: lambda{|query, name, value, type_info, hash|
|
10
|
+
case type_info[:type]
|
11
|
+
when :many_to_one
|
12
|
+
query.where(name => value)
|
13
|
+
else
|
14
|
+
query.where(name.like("%#{value}%"))
|
15
|
+
end
|
16
|
+
},
|
17
|
+
date: lambda{|query, name, value, type_info, hash|
|
18
|
+
if value.is_a? Hash
|
19
|
+
from, to = value[:from], value[:to]
|
20
|
+
if from && to
|
21
|
+
query.where(name => from .. to)
|
22
|
+
elsif from
|
23
|
+
query.where(name >= Sequel.string_to_date(from))
|
24
|
+
elsif to
|
25
|
+
query.where(name <= Sequel.string_to_date(to))
|
26
|
+
else
|
27
|
+
query # ?
|
28
|
+
end
|
29
|
+
else
|
30
|
+
query.where(name => Sequel.string_to_date(value))
|
31
|
+
end
|
32
|
+
},
|
33
|
+
integer: lambda{|query, name, value, type_info, hash|
|
34
|
+
if value.is_a? Hash
|
35
|
+
from, to = value[:from], value[:to]
|
36
|
+
if from && to
|
37
|
+
query.where(name => from .. to)
|
38
|
+
else
|
39
|
+
query.where(from ? name >= from.to_i : name <= to.to_i)
|
40
|
+
end
|
41
|
+
elsif value.is_a? Integer
|
42
|
+
query.where(name => value)
|
43
|
+
elsif value.is_a? Array
|
44
|
+
if !value.empty?
|
45
|
+
case type_info[:type]
|
46
|
+
when :many_to_one
|
47
|
+
keys = type_info[:keys]
|
48
|
+
if keys.length == 1
|
49
|
+
query.where(name => value)
|
50
|
+
else
|
51
|
+
query.where(keys.map{|k| hash[k]}.transpose.map{|vals| Hash[keys.zip(vals)]}.inject{|q, c| q | c
|
52
|
+
})
|
53
|
+
end
|
54
|
+
when :list_select
|
55
|
+
query.where(name => value) # decode in sql query ?
|
56
|
+
when :integer
|
57
|
+
query
|
58
|
+
else
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
else
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
else
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
}
|
68
|
+
)
|
69
|
+
|
70
|
+
def post_run
|
71
|
+
query select(*assets[:model].columns.reject{|col| assets[:model].type_info[col][:length].to_i > 20}.take(10)) unless @query
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
75
|
+
def invoke handler
|
76
|
+
params = handler.params
|
77
|
+
model = assets[:model]
|
78
|
+
query = list_context(get_query, handler)
|
79
|
+
|
80
|
+
if search = params[:search]
|
81
|
+
query = list_search(query, handler, search)
|
82
|
+
end
|
83
|
+
|
84
|
+
count = query.count if lookup(:config, :use_count)
|
85
|
+
|
86
|
+
if order_str = params[:order]
|
87
|
+
order = order_str.to_sym
|
88
|
+
handler.permit lookup(:info, order, :sort)
|
89
|
+
|
90
|
+
if order_blk = (@orders && @orders[order]) || (dynamic? && (static.orders && static.orders[order]))
|
91
|
+
query = order_blk.(query, handler)
|
92
|
+
else
|
93
|
+
order = order.qualify(model.table_name) if model.type_info[order]
|
94
|
+
query = query.order(order)
|
95
|
+
end
|
96
|
+
|
97
|
+
query = query.reverse if params[:asc] == "true"
|
98
|
+
end
|
99
|
+
|
100
|
+
per_page = lookup(:config, :per_page)
|
101
|
+
page = params[:page].to_i
|
102
|
+
handler.permit page >= 0 && page < 1000
|
103
|
+
|
104
|
+
query = query.limit(per_page, page)
|
105
|
+
|
106
|
+
res = {entries: query.all}
|
107
|
+
res[:count] = count if count
|
108
|
+
res
|
109
|
+
end
|
110
|
+
|
111
|
+
def list_search query, handler, search
|
112
|
+
hash = JSON.parse(search, symbolize_names: true) rescue handler.halt_forbidden
|
113
|
+
model = assets[:model]
|
114
|
+
sfields = lookup(:search_fields)
|
115
|
+
handler.permit sfields
|
116
|
+
hash.each_pair do |name, value|
|
117
|
+
handler.permit sfields.include?(name)
|
118
|
+
|
119
|
+
type_info = get_type_info(name)
|
120
|
+
query = if filter = (@filters && @filters[name]) || (dynamic? && (static.filters && static.filters[name]))
|
121
|
+
filter.(query, hash, handler)
|
122
|
+
elsif filter = DefaultFilters[type_info[:otype]]
|
123
|
+
name = model.type_info[name] ? name.qualify(model.table_name) : Sequel.expr(name)
|
124
|
+
filter.(query, name, value, type_info, hash)
|
125
|
+
else
|
126
|
+
raise E2Error.new("Filter not found for field #{name} in model #{model}") unless filter
|
127
|
+
end
|
128
|
+
|
129
|
+
handler.permit query
|
130
|
+
end
|
131
|
+
query
|
132
|
+
end
|
133
|
+
|
134
|
+
def list_context query, handler
|
135
|
+
query
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Many to One
|
141
|
+
#
|
142
|
+
class ManyToOneListMeta < ListMeta
|
143
|
+
meta_type :many_to_one_list
|
144
|
+
|
145
|
+
def pre_run
|
146
|
+
super
|
147
|
+
config.merge!(selectable: false)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
#
|
152
|
+
# * to Many
|
153
|
+
#
|
154
|
+
class StarToManyListMeta < ListMeta
|
155
|
+
meta_type :star_to_many_list
|
156
|
+
def pre_run
|
157
|
+
super
|
158
|
+
panel_title "#{glyphicon('list')} #{LOCS[assets[:assoc][:name]]}"
|
159
|
+
end
|
160
|
+
|
161
|
+
# def decode_panel_title handler
|
162
|
+
# if handler.initial?
|
163
|
+
# # Hash[assets[:model].primary_keys.zip(split_keys(id))]]
|
164
|
+
# p action.parent.decode_entry.*.invoke_decode([[handler.params[:parent_id]]])
|
165
|
+
# panel_title "ADFASDF"
|
166
|
+
# end
|
167
|
+
# end
|
168
|
+
|
169
|
+
# def post_run
|
170
|
+
# super
|
171
|
+
# unless @request_meta_proc
|
172
|
+
# request{|h| decode_panel_title h}
|
173
|
+
# end
|
174
|
+
# end
|
175
|
+
|
176
|
+
def list_context query, handler
|
177
|
+
handler.permit parent = handler.params[:parent_id]
|
178
|
+
model = assets[:model]
|
179
|
+
assoc = assets[:assoc]
|
180
|
+
case assoc[:type]
|
181
|
+
when :one_to_many
|
182
|
+
keys = assoc[:keys]
|
183
|
+
condition = parent.empty? ? false : Hash[keys.map{|k| k.qualify(model.table_name)}.zip(split_keys(parent))]
|
184
|
+
if handler.params[:negate]
|
185
|
+
query = query.exclude(condition)
|
186
|
+
query = query.or(Hash[keys.zip([nil])]) if keys.all?{|k|model.db_schema[k][:allow_null] == true} # type_info[:required] ?
|
187
|
+
query
|
188
|
+
else
|
189
|
+
query.where(condition)
|
190
|
+
end
|
191
|
+
when :many_to_many
|
192
|
+
q_pk = model.primary_keys_qualified
|
193
|
+
j_table = assoc[:join_table]
|
194
|
+
l_keys = assoc[:left_keys].map{|k| k.qualify(j_table)}
|
195
|
+
r_keys = assoc[:right_keys].map{|k| k.qualify(j_table)}
|
196
|
+
r_keys_vals = Hash[r_keys.zip(q_pk)]
|
197
|
+
l_keys_vals = parent.empty? ? false : Hash[l_keys.zip(split_keys(parent))]
|
198
|
+
|
199
|
+
if handler.params[:negate]
|
200
|
+
query.exclude(model.db[j_table].select(nil).where(r_keys_vals, l_keys_vals).exists)
|
201
|
+
else
|
202
|
+
# query.qualify.join(j_table, [r_keys_vals, l_keys_vals])
|
203
|
+
query.qualify.left_join(j_table, r_keys_vals).filter(l_keys_vals)
|
204
|
+
end
|
205
|
+
else unsupported_association
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
class StarToManyLinkListMeta < StarToManyListMeta
|
211
|
+
meta_type :star_to_many_link_list
|
212
|
+
def pre_run
|
213
|
+
super
|
214
|
+
config.merge!(selectable: false)
|
215
|
+
panel_title LOCS[:link_title]
|
216
|
+
menu(:panel_menu).option_at 0, :link, icon: "ok", enabled: "action.selected_size() > 0"
|
217
|
+
action.parent.*.menu(:menu).option_at 0, :link_list, icon: "paperclip", button_loc: false
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# *_to_many_field
|
222
|
+
class StarToManyFieldMeta < StarToManyListMeta
|
223
|
+
meta_type :star_to_many_field
|
224
|
+
|
225
|
+
def pre_run
|
226
|
+
super
|
227
|
+
modal_action false
|
228
|
+
panel_panel_template false
|
229
|
+
# panel_template nil
|
230
|
+
end
|
231
|
+
|
232
|
+
def list_context query, handler
|
233
|
+
unlinked = handler.param_to_json(:unlinked)
|
234
|
+
linked = handler.param_to_json(:linked)
|
235
|
+
query = super(query, handler)
|
236
|
+
model = assets[:model]
|
237
|
+
pks = model.primary_keys_qualified
|
238
|
+
|
239
|
+
if handler.params[:negate]
|
240
|
+
query = unlinked.map{|ln| pks.zip(split_keys(ln))}.inject(query){|q, c| q.or c}
|
241
|
+
# query = query.or *unlinked.map{|unl| Hash[model.primary_keys.zip(split_keys(unl))]}.inject{|q, c| q | c}
|
242
|
+
query = query.where *linked.map{|ln| pks.zip(split_keys(ln)).sql_negate}
|
243
|
+
|
244
|
+
else
|
245
|
+
query = query.where *unlinked.map{|unl| pks.zip(split_keys(unl)).sql_negate}
|
246
|
+
# query = query.or *linked.map{|ln| model.primary_keys.zip(split_keys(ln))}
|
247
|
+
# query = query.or *linked.map{|ln| Hash[model.primary_keys.zip(split_keys(ln))]}.inject{|q, c| q | c}
|
248
|
+
case assets[:assoc][:type]
|
249
|
+
when :one_to_many
|
250
|
+
query = linked.map{|ln| pks.zip(split_keys(ln))}.inject(query){|q, c| q.or c}
|
251
|
+
when :many_to_many
|
252
|
+
query = linked.map{|ln| pks.zip(split_keys(ln))}.inject(query){|q, c| q.or c}.distinct
|
253
|
+
else unsupported_association
|
254
|
+
end unless linked.empty?
|
255
|
+
end
|
256
|
+
|
257
|
+
query
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
class StarToManyFieldUnlinkMeta < Meta
|
262
|
+
meta_type :star_to_many_field_unlink
|
263
|
+
|
264
|
+
def pre_run
|
265
|
+
super
|
266
|
+
action.parent.parent.*.menu(:item_menu).option :confirm_unlink, icon: "minus", show: "action.selected_size() == 0", button_loc: false
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
class StarToManyFieldLinkListMeta < StarToManyFieldMeta
|
271
|
+
meta_type :star_to_many_field_link_list
|
272
|
+
|
273
|
+
def pre_run
|
274
|
+
super
|
275
|
+
config.merge!(selectable: false)
|
276
|
+
modal_action true
|
277
|
+
panel_panel_template 'scaffold/list'
|
278
|
+
panel_title LOCS[:link_title]
|
279
|
+
menu(:panel_menu).option_at 0, :link, icon: "ok", enabled: "action.selected_size() > 0"
|
280
|
+
action.parent.*.menu(:menu).option_at 0, :link_list, icon: "paperclip", button_loc: false
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Engine2
|
4
|
+
|
5
|
+
class SaveMeta < Meta
|
6
|
+
include MetaApproveSupport
|
7
|
+
http_method :post
|
8
|
+
|
9
|
+
def validate_and_approve handler, record, json
|
10
|
+
record.skip_save_refresh = true
|
11
|
+
record.raise_on_save_failure = false
|
12
|
+
model = assets[:model]
|
13
|
+
assoc = assets[:assoc]
|
14
|
+
mtm_insert = record.new? && assoc && assoc[:type] == :many_to_many
|
15
|
+
|
16
|
+
save = lambda do|c|
|
17
|
+
if super(handler, record, json)
|
18
|
+
result = record.save(transaction: false, validate: false)
|
19
|
+
if result && mtm_insert
|
20
|
+
handler.permit parent_id = json[:parent_id]
|
21
|
+
model.db[assoc[:join_table]].insert(assoc[:left_keys] + assoc[:right_keys], split_keys(parent_id) + record.primary_key_values)
|
22
|
+
end
|
23
|
+
result
|
24
|
+
end
|
25
|
+
end
|
26
|
+
(model.validation_in_transaction || mtm_insert) ? model.db.transaction(&save) : save.(nil)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class InsertMeta < SaveMeta
|
31
|
+
meta_type :save
|
32
|
+
def allocate_record handler, json
|
33
|
+
record = super(handler, json)
|
34
|
+
record.instance_variable_set(:"@new", true)
|
35
|
+
model = assets[:model]
|
36
|
+
model.primary_keys.each{|k|record.values.delete k} unless model.natural_key
|
37
|
+
handler.permit !record.has_primary_key? unless model.natural_key
|
38
|
+
record
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class UpdateMeta < SaveMeta
|
43
|
+
meta_type :save
|
44
|
+
def allocate_record handler, json
|
45
|
+
record = super(handler, json)
|
46
|
+
model = assets[:model]
|
47
|
+
handler.permit record.has_primary_key? unless model.natural_key
|
48
|
+
record
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module TimeStampMeta
|
53
|
+
def before_approve handler, record
|
54
|
+
super
|
55
|
+
puts "before approve"
|
56
|
+
end
|
57
|
+
|
58
|
+
def after_approve handler, record
|
59
|
+
super
|
60
|
+
puts "after approve"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|