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,110 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Engine2
|
4
|
+
class DecodeMeta < Meta
|
5
|
+
include MetaAPISupport, MetaModelSupport, MetaQuerySupport
|
6
|
+
|
7
|
+
def decode *fields, &blk
|
8
|
+
query select(*fields), &blk
|
9
|
+
@meta[:decode_fields] = fields
|
10
|
+
end
|
11
|
+
|
12
|
+
def separator sep
|
13
|
+
@meta[:separator] = sep
|
14
|
+
end
|
15
|
+
|
16
|
+
def show_max_selected max
|
17
|
+
@meta[:show_max_selected] = max
|
18
|
+
end
|
19
|
+
|
20
|
+
def post_process
|
21
|
+
if fields = @meta[:fields]
|
22
|
+
fields = fields - static.get[:fields] if dynamic?
|
23
|
+
# no decorate here
|
24
|
+
fields.each do |name|
|
25
|
+
type_info = assets[:model].type_info[name] # foreign keys ?
|
26
|
+
proc = ListRendererPostProcessors[type_info[:type]] # like... checkboxes, list_selects
|
27
|
+
proc.(self, name, type_info) if proc
|
28
|
+
end
|
29
|
+
end
|
30
|
+
# no super
|
31
|
+
end
|
32
|
+
|
33
|
+
def pre_run
|
34
|
+
super
|
35
|
+
if assoc = assets[:assoc]
|
36
|
+
decode = assoc[:model].type_info[assoc[:keys].first][:decode]
|
37
|
+
if decode[:search][:multiple]
|
38
|
+
show_max_selected 3
|
39
|
+
@meta[:decode_selected] = LOCS[:decode_selected]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def post_run
|
45
|
+
query select(*assets[:model].primary_keys) unless @query
|
46
|
+
@meta[:separator] = '/' unless @meta[:separator]
|
47
|
+
super
|
48
|
+
@meta[:primary_fields] = assets[:model].primary_keys
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
class DecodeListMeta < DecodeMeta
|
54
|
+
meta_type :decode_list
|
55
|
+
|
56
|
+
def invoke handler
|
57
|
+
{entries: get_query.limit(200).all}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class TypeAheadMeta < DecodeMeta
|
62
|
+
meta_type :typeahead
|
63
|
+
|
64
|
+
def pre_run
|
65
|
+
super
|
66
|
+
limit 10
|
67
|
+
end
|
68
|
+
|
69
|
+
def limit lmt
|
70
|
+
@meta[:limit] = lmt
|
71
|
+
end
|
72
|
+
|
73
|
+
def invoke handler
|
74
|
+
if query = handler.params[:query]
|
75
|
+
condition = (@meta[:decode_fields] || @meta[:fields]).map{|f|f.like("%#{query}%")}.inject{|q, f| q | f}
|
76
|
+
{entries: get_query.where(condition).limit(@meta[:limit]).all}
|
77
|
+
else
|
78
|
+
handler.permit id = handler.params[:id]
|
79
|
+
record = get_query[Hash[assets[:model].primary_keys.zip(split_keys(id))]]
|
80
|
+
# handler.halt_not_found(LOCS[:no_entry]) unless record
|
81
|
+
{entry: record}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class DecodeEntryMeta < DecodeMeta
|
87
|
+
meta_type :decode_entry
|
88
|
+
|
89
|
+
def invoke handler
|
90
|
+
{entries: invoke_decode(handler, handler.param_to_json(:ids))}
|
91
|
+
end
|
92
|
+
|
93
|
+
def invoke_decode handler, ids
|
94
|
+
records = get_query.where(ids.map{|keys| Hash[assets[:model].primary_keys.zip(keys)]}.inject{|q, c| q | c}).all
|
95
|
+
# handler.halt_not_found(LOCS[:no_entry]) if records.empty?
|
96
|
+
records
|
97
|
+
end
|
98
|
+
|
99
|
+
def post_run
|
100
|
+
super
|
101
|
+
if assoc = assets[:assoc]
|
102
|
+
decode = assoc[:model].type_info[assoc[:keys].first][:decode]
|
103
|
+
|
104
|
+
if decode[:search][:multiple] && action.parent.parent.*.is_a?(ListMeta)
|
105
|
+
action.list.*.menu(:panel_menu).option_at 0, :choose, icon: :ok # , disabled: "action.selected_size() == 0"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Engine2
|
4
|
+
class DeleteMetaBase < Meta
|
5
|
+
include MetaModelSupport
|
6
|
+
|
7
|
+
def invoke_delete_db handler, ids
|
8
|
+
begin
|
9
|
+
model = assets[:model]
|
10
|
+
model.db.transaction do
|
11
|
+
ids.each do |id|
|
12
|
+
keys = split_keys(id)
|
13
|
+
restrict = model.association_reflections.select do |name, rel|
|
14
|
+
case rel[:type]
|
15
|
+
when :one_to_many
|
16
|
+
!model.db[name].where(Hash[rel[:keys].zip(keys)]).empty?
|
17
|
+
when :many_to_many
|
18
|
+
!model.db[rel[:join_table]].where(Hash[rel[:left_keys].zip(keys)]).empty?
|
19
|
+
when :many_to_one
|
20
|
+
when :one_to_one
|
21
|
+
else
|
22
|
+
unsupported_association rel[:type]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
raise Sequel::DestroyFailed.new("Blokujące relacje: #{restrict.map{|name, rel| name}.join(', ')}" ) unless restrict.empty?
|
26
|
+
|
27
|
+
rec = model.call(Hash[model.primary_keys.zip(keys)])
|
28
|
+
rec.destroy(transaction: false)
|
29
|
+
# model.where(model.primary_keys_hash(keys)).delete # model.dataset[model.primary_key => id].delete
|
30
|
+
end
|
31
|
+
end
|
32
|
+
{}
|
33
|
+
rescue Sequel::NoExistingObject
|
34
|
+
handler.halt_not_found LOCS[:no_entry]
|
35
|
+
rescue Sequel::DestroyFailed => failure
|
36
|
+
handler.halt_forbidden failure.error.to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class DeleteMeta < DeleteMetaBase
|
43
|
+
http_method :delete
|
44
|
+
meta_type :delete
|
45
|
+
|
46
|
+
def pre_run
|
47
|
+
super
|
48
|
+
action.parent.parent.*.menu(:item_menu).option :confirm_delete, icon: "trash", show: "action.selected_size() == 0", button_loc: false
|
49
|
+
end
|
50
|
+
|
51
|
+
def invoke handler
|
52
|
+
handler.permit id = handler.params[:id]
|
53
|
+
invoke_delete_db(handler, [id])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class BulkDeleteMeta < DeleteMetaBase
|
58
|
+
http_method :delete
|
59
|
+
meta_type :bulk_delete
|
60
|
+
|
61
|
+
def pre_run
|
62
|
+
super
|
63
|
+
action.parent.parent.*.menu(:menu).option_after :default_order, :confirm_bulk_delete, icon: "trash", show: "action.selected_size() > 0"
|
64
|
+
end
|
65
|
+
|
66
|
+
def invoke handler
|
67
|
+
ids = handler.param_to_json(:ids)
|
68
|
+
handler.permit ids.is_a?(Array)
|
69
|
+
invoke_delete_db(handler, ids)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Engine2
|
4
|
+
class FormMeta < Meta
|
5
|
+
include MetaAPISupport, MetaModelSupport, MetaQuerySupport, MetaTabSupport, MetaPanelSupport, MetaMenuSupport, MetaAngularSupport, MetaOnChangeSupport
|
6
|
+
|
7
|
+
def field_template template
|
8
|
+
panel[:field_template] = template
|
9
|
+
end
|
10
|
+
|
11
|
+
def pre_run
|
12
|
+
super
|
13
|
+
panel_template 'scaffold/form'
|
14
|
+
field_template 'scaffold/fields'
|
15
|
+
panel_class 'modal-large'
|
16
|
+
|
17
|
+
menu :panel_menu do
|
18
|
+
option :approve, icon: "ok", disabled: 'action.action_pending' # text: true,
|
19
|
+
option :cancel, icon: "remove" # text: true,
|
20
|
+
end
|
21
|
+
# modal_action false
|
22
|
+
end
|
23
|
+
|
24
|
+
def record handler, record
|
25
|
+
end
|
26
|
+
|
27
|
+
def post_process
|
28
|
+
if fields = @meta[:fields]
|
29
|
+
fields = fields - static.get[:fields] if dynamic?
|
30
|
+
|
31
|
+
decorate(fields)
|
32
|
+
|
33
|
+
fields.each do |name|
|
34
|
+
# type_info = model.type_info.fetch(name)
|
35
|
+
type_info = get_type_info(name)
|
36
|
+
|
37
|
+
info[name][:render] ||= begin
|
38
|
+
renderer = DefaultFormRenderers[type_info[:type]] # .merge(default: true)
|
39
|
+
raise E2Error.new("No form renderer found for field '#{type_info[:name]}' of type '#{type_info[:type]}'") unless renderer
|
40
|
+
renderer.(self, type_info)
|
41
|
+
end
|
42
|
+
|
43
|
+
proc = FormRendererPostProcessors[type_info[:type]]
|
44
|
+
proc.(self, name, type_info) if proc
|
45
|
+
end
|
46
|
+
|
47
|
+
assoc = assets[:assoc]
|
48
|
+
if assoc && assoc[:type] == :one_to_many
|
49
|
+
# fields.select{|f| assoc[:keys].include? f}.each do |key|
|
50
|
+
# # hide_fields(key) if self[:info, key, :hidden] == nil
|
51
|
+
# info! key, disabled: true
|
52
|
+
# end
|
53
|
+
assoc[:keys].each do |key|
|
54
|
+
info! key, disabled: true if fields.include? key
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
super
|
60
|
+
end
|
61
|
+
|
62
|
+
def post_run
|
63
|
+
super
|
64
|
+
@meta[:primary_fields] = assets[:model].primary_keys
|
65
|
+
end
|
66
|
+
|
67
|
+
def template
|
68
|
+
Templates
|
69
|
+
end
|
70
|
+
|
71
|
+
def hr_after field, message = '-'
|
72
|
+
info! field, hr: message
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class CreateMeta < FormMeta
|
77
|
+
meta_type :create
|
78
|
+
|
79
|
+
def pre_run
|
80
|
+
super
|
81
|
+
panel_title LOCS[:create_title]
|
82
|
+
action.parent.*.menu(:menu).option_at 0, action.name, icon: "plus-sign", button_loc: false
|
83
|
+
|
84
|
+
hide_pk unless assets[:model].natural_key
|
85
|
+
end
|
86
|
+
|
87
|
+
def record handler, record
|
88
|
+
create_record(handler, record)
|
89
|
+
end
|
90
|
+
|
91
|
+
def create_record handler, record
|
92
|
+
end
|
93
|
+
|
94
|
+
def invoke handler
|
95
|
+
record = {}
|
96
|
+
if assoc = assets[:assoc]
|
97
|
+
case assoc[:type]
|
98
|
+
when :one_to_many
|
99
|
+
handler.permit parent = handler.params[:parent_id]
|
100
|
+
assoc[:keys].zip(split_keys(parent)).each{|key, val| record[key] = val}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
static.record(handler, record)
|
104
|
+
{record: record, new: true}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class ModifyMeta < FormMeta
|
109
|
+
meta_type :modify
|
110
|
+
|
111
|
+
def pre_run
|
112
|
+
super
|
113
|
+
panel_title LOCS[:modify_title]
|
114
|
+
action.parent.*.menu(:item_menu).option action.name, icon: "pencil", button_loc: false
|
115
|
+
end
|
116
|
+
|
117
|
+
def record handler, record
|
118
|
+
modify_record(handler, record)
|
119
|
+
end
|
120
|
+
|
121
|
+
def modify_record handler, record
|
122
|
+
end
|
123
|
+
|
124
|
+
def invoke handler
|
125
|
+
handler.permit id = handler.params[:id]
|
126
|
+
record = get_query[assets[:model].primary_keys_hash_qualified(split_keys(id))]
|
127
|
+
|
128
|
+
if record
|
129
|
+
static.record(handler, record)
|
130
|
+
{record: record}
|
131
|
+
else
|
132
|
+
handler.halt_not_found LOCS[:no_entry]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def post_run
|
137
|
+
super
|
138
|
+
assets[:model].primary_keys.each do |key| # pre_run ?
|
139
|
+
info! key, disabled: true
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
@@ -0,0 +1,292 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Engine2
|
4
|
+
SCHEMES::define_scheme :infra! do |user_info_model = UserInfo|
|
5
|
+
define_action :infra! do
|
6
|
+
self.* do
|
7
|
+
extend MetaPanelSupport, MetaMenuSupport
|
8
|
+
panel_panel_template false
|
9
|
+
panel_template 'infra/index'
|
10
|
+
menu :menu do
|
11
|
+
properties group_class: "btn-group-sm"
|
12
|
+
option :inspect_modal, icon: :wrench, button_loc: false # , show: "action.logged_on"
|
13
|
+
|
14
|
+
option :logout_form, icon: :"log-out" # , show: "action.logged_on"
|
15
|
+
option :login_form, icon: :"log-in" # , show: "!action.logged_on"
|
16
|
+
end
|
17
|
+
|
18
|
+
@meta_type = :infra
|
19
|
+
|
20
|
+
def invoke handler
|
21
|
+
user = handler.user
|
22
|
+
{user: user ? user.to_hash : nil}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
define_action :login_form, LoginFormMeta, model: user_info_model do
|
27
|
+
access!{|h|!h.logged_in?}
|
28
|
+
define_action :login, LoginMeta
|
29
|
+
end
|
30
|
+
|
31
|
+
define_action :logout_form, LogoutFormMeta do
|
32
|
+
access! &:logged_in?
|
33
|
+
define_action :logout, LogoutMeta
|
34
|
+
end
|
35
|
+
|
36
|
+
define_action :inspect_modal do
|
37
|
+
access! &:logged_in?
|
38
|
+
# access!{|h|h.user[:name] == 'admin'}
|
39
|
+
self.* do
|
40
|
+
extend MetaPanelSupport, MetaMenuSupport
|
41
|
+
modal_action
|
42
|
+
panel_template 'infra/inspect'
|
43
|
+
panel_title "Inspect"
|
44
|
+
panel_class "modal-huge"
|
45
|
+
menu(:panel_menu).option :cancel, icon: "remove"
|
46
|
+
|
47
|
+
# def invoke handler;{};end
|
48
|
+
end
|
49
|
+
define_action :inspect do
|
50
|
+
self.* do
|
51
|
+
@meta_type = :inspect
|
52
|
+
end
|
53
|
+
|
54
|
+
define_action :models do
|
55
|
+
def (self.*).invoke handler
|
56
|
+
{models: Sequel::DATABASES.map{|db| {name: db.uri, models: db.models.keys} }}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
define_action :model_info do
|
61
|
+
def (self.*).invoke handler
|
62
|
+
db_name = handler.params[:db]
|
63
|
+
handler.permit db = Sequel::DATABASES.find{|d|d.uri == db_name || (d.uri && d.uri.start_with?(db_name))}
|
64
|
+
handler.permit model = db.models[handler.params[:model].to_sym]
|
65
|
+
{
|
66
|
+
model: {
|
67
|
+
info: {
|
68
|
+
name: model.to_s,
|
69
|
+
table: model.table_name
|
70
|
+
},
|
71
|
+
assoc: model.association_reflections,
|
72
|
+
schema: model.db_schema,
|
73
|
+
type_info: model.type_info
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
SCHEMES::define_scheme :menu! do
|
84
|
+
define_action :menu!, MenuMeta do
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class FileStoreMeta < Meta
|
89
|
+
meta_type :file_store
|
90
|
+
|
91
|
+
attr_accessor :model, :field
|
92
|
+
|
93
|
+
def invoke handler
|
94
|
+
handler.permit owner = handler.params[:owner]
|
95
|
+
{files: E2Files.db[:files].select(:id, :name, :mime, :uploaded).where(owner: owner, model: model.name.to_s, field: field.to_s).all}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
module BlobSupportMeta
|
101
|
+
def serve_blob handler, entry, inf
|
102
|
+
handler.permit entry
|
103
|
+
handler.attachment entry[inf[:name_field]]
|
104
|
+
handler.content_type (entry[inf[:mime_field]].to_s.empty? ? "application/octet-stream" : entry[inf[:mime_field]])
|
105
|
+
entry[inf[:bytes_field]].getBinaryStream().to_io.read
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class DownloadFileStoreMeta < Meta
|
110
|
+
meta_type :download
|
111
|
+
|
112
|
+
def invoke handler
|
113
|
+
handler.permit id = handler.params[:id]
|
114
|
+
entry = E2Files.db[:files].select(:name, :mime)[id: id]
|
115
|
+
handler.permit entry
|
116
|
+
handler.attachment entry[:name]
|
117
|
+
handler.content_type (entry[:mime].to_s.empty? ? "application/octet-stream" : entry[:mime])
|
118
|
+
info = action.parent.*.model.type_info[action.parent.*.field]
|
119
|
+
open("#{info[:store][:files]}/#{entry[:name]}_#{id}", 'rb'){|f|f.read}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class UploadFileStoreMeta < Meta
|
124
|
+
http_method :post
|
125
|
+
meta_type :upload
|
126
|
+
|
127
|
+
def invoke handler
|
128
|
+
file = handler.params[:file]
|
129
|
+
temp = file[:tempfile]
|
130
|
+
temp.close
|
131
|
+
rackname = File.basename(temp.path)
|
132
|
+
info = action.parent.*.model.type_info[action.parent.*.field]
|
133
|
+
File.rename(temp.path, "#{info[:store][:upload]}/#{rackname}")
|
134
|
+
{rackname: rackname}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class BlobStoreMeta < Meta
|
139
|
+
meta_type :blob_store
|
140
|
+
|
141
|
+
attr_accessor :model, :field
|
142
|
+
|
143
|
+
def invoke handler
|
144
|
+
handler.permit id = handler.params[:owner]
|
145
|
+
inf = model.type_info[field]
|
146
|
+
result = model.naked.select(inf[:name_field], Sequel.char_length(inf[:bytes_field]).as(:length)).where(model.primary_keys_hash(split_keys(id))).first
|
147
|
+
handler.permit result
|
148
|
+
{file_name: result[inf[:name_field]], blob_length: result[:length]}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class DownloadBlobStoreMeta < Meta
|
153
|
+
include BlobSupportMeta
|
154
|
+
meta_type :download_blob
|
155
|
+
|
156
|
+
def invoke handler
|
157
|
+
model = action.parent.*.model
|
158
|
+
inf = model.type_info[action.parent.*.field]
|
159
|
+
handler.permit id = handler.params[:id]
|
160
|
+
|
161
|
+
entry = model.naked.select(inf[:bytes_field], inf[:name_field], inf[:mime_field]).where(model.primary_keys_hash(split_keys(id))).first
|
162
|
+
serve_blob(handler, entry, inf)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class UploadBlobStoreMeta < Meta
|
167
|
+
http_method :post
|
168
|
+
meta_type :upload_blob
|
169
|
+
|
170
|
+
def invoke handler
|
171
|
+
file = handler.params[:file]
|
172
|
+
temp = file[:tempfile]
|
173
|
+
temp.close
|
174
|
+
rackname = File.basename(temp.path)
|
175
|
+
info = action.parent.*.model.type_info[action.parent.*.field]
|
176
|
+
File.rename(temp.path, "#{info[:store][:upload]}/#{rackname}")
|
177
|
+
{rackname: rackname}
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class ForeignBlobStoreMeta < Meta
|
182
|
+
meta_type :blob_store
|
183
|
+
|
184
|
+
attr_accessor :model, :field
|
185
|
+
|
186
|
+
def invoke handler
|
187
|
+
handler.permit id = handler.params[:owner]
|
188
|
+
|
189
|
+
inf = model.type_info[field]
|
190
|
+
assoc = model.association_reflections[inf[:assoc_name]]
|
191
|
+
blob_model = Object.const_get(assoc[:class_name])
|
192
|
+
|
193
|
+
rec = model.naked.select(assoc[:key]).where(model.primary_keys_hash(split_keys(id))).first
|
194
|
+
handler.permit rec
|
195
|
+
result = blob_model.naked.select(inf[:name_field], Sequel.char_length(inf[:bytes_field]).as(:length)).where(blob_model.primary_key => rec[assoc[:key]]).first
|
196
|
+
|
197
|
+
# handler.permit result
|
198
|
+
{file_name: result ? result[inf[:name_field]] : :empty, blob_length: result ? result[:length] : 0}
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class DownloadForeignBlobStoreMeta < Meta
|
203
|
+
include BlobSupportMeta
|
204
|
+
meta_type :download_blob
|
205
|
+
|
206
|
+
def invoke handler
|
207
|
+
model = action.parent.*.model
|
208
|
+
inf = model.type_info[action.parent.*.field]
|
209
|
+
assoc = model.association_reflections[inf[:assoc_name]]
|
210
|
+
blob_model = Object.const_get(assoc[:class_name])
|
211
|
+
handler.permit id = handler.params[:id]
|
212
|
+
rec = model.naked.select(assoc[:key]).where(model.primary_keys_hash(split_keys(id))).first
|
213
|
+
handler.permit rec
|
214
|
+
|
215
|
+
entry = blob_model.naked.select(inf[:bytes_field], inf[:name_field], inf[:mime_field]).where(blob_model.primary_key => rec[assoc[:key]]).first
|
216
|
+
serve_blob(handler, entry, inf)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# class UploadForeignBlobStoreMeta < Meta
|
221
|
+
# http_method :post
|
222
|
+
# meta_type :upload_blob
|
223
|
+
|
224
|
+
# def invoke handler
|
225
|
+
# file = handler.params[:file]
|
226
|
+
# temp = file[:tempfile]
|
227
|
+
# temp.close
|
228
|
+
# rackname = File.basename(temp.path)
|
229
|
+
# File.rename(temp.path, "#{UPLOAD_DIR}/#{rackname}")
|
230
|
+
# {rackname: rackname}
|
231
|
+
# end
|
232
|
+
# end
|
233
|
+
|
234
|
+
class LoginFormMeta < FormMeta
|
235
|
+
meta_type :login_form
|
236
|
+
|
237
|
+
def pre_run
|
238
|
+
super
|
239
|
+
panel_class 'modal-default'
|
240
|
+
panel_title LOCS[:login_title]
|
241
|
+
info! :name, loc: LOCS[:user_name]
|
242
|
+
menu(:panel_menu).modify_option :approve, name: :login, icon: :"log-in"
|
243
|
+
end
|
244
|
+
|
245
|
+
def invoke handler
|
246
|
+
{record: {}, new: true}
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
class LoginMeta < Meta
|
251
|
+
include MetaApproveSupport
|
252
|
+
http_method :post
|
253
|
+
meta_type :login
|
254
|
+
|
255
|
+
def after_approve handler, record
|
256
|
+
handler.session[:user] = record
|
257
|
+
end
|
258
|
+
|
259
|
+
def record handler, record
|
260
|
+
{errors: nil, user: handler.user.to_hash}
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
class LogoutFormMeta < Meta
|
265
|
+
include MetaPanelSupport, MetaMenuSupport
|
266
|
+
meta_type :logout_form
|
267
|
+
def pre_run
|
268
|
+
super
|
269
|
+
panel_template 'scaffold/message'
|
270
|
+
panel_title LOCS[:logout_title]
|
271
|
+
panel_class 'modal-default'
|
272
|
+
menu :panel_menu do
|
273
|
+
option :logout, icon: "ok", loc: LOCS[:ok]
|
274
|
+
option :cancel, icon: "remove"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def invoke handler
|
279
|
+
{message: LOCS[:logout_message]}
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
class LogoutMeta < Meta
|
284
|
+
meta_type :logout
|
285
|
+
|
286
|
+
def invoke handler
|
287
|
+
handler.session.clear
|
288
|
+
# handler.session[:logged_in] = false
|
289
|
+
{}
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|