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
@@ -0,0 +1,189 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Engine2
|
5
|
+
class ArrayListAction < Action
|
6
|
+
action_type :list
|
7
|
+
include ActionListSupport
|
8
|
+
|
9
|
+
(DefaultFilters ||= {}).merge!(
|
10
|
+
exact: lambda{|entries, name, value, type_info, hash|
|
11
|
+
entries.select{|e|e[name] == value}
|
12
|
+
},
|
13
|
+
string: lambda{|entries, name, value, type_info, hash|
|
14
|
+
if type_info[:type] == :list_select
|
15
|
+
if type_info[:multiselect]
|
16
|
+
entries.select{|e|value.include?(e[name].to_s)}
|
17
|
+
else
|
18
|
+
entries.select{|e|e[name].to_s == value}
|
19
|
+
end
|
20
|
+
else
|
21
|
+
entries.select{|e|e[name].to_s[value]}
|
22
|
+
end
|
23
|
+
|
24
|
+
},
|
25
|
+
boolean: lambda{|*args| DefaultFilters[:exact].(*args)},
|
26
|
+
integer: lambda{|entries, name, value, type_info, hash|
|
27
|
+
if value.is_a? Hash
|
28
|
+
from, to = value[:from], value[:to]
|
29
|
+
if from && to
|
30
|
+
entries.select{|e|e[name] >= from.to_i && e[name] <= to.to_i}
|
31
|
+
else
|
32
|
+
entries.select{|e| from ? e[name] >= from.to_i : e[name] <= to.to_i}
|
33
|
+
end
|
34
|
+
elsif value.is_a? Integer
|
35
|
+
entries.select{|e|e[name] == value.to_i}
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
}
|
40
|
+
)
|
41
|
+
|
42
|
+
def data_source handler
|
43
|
+
[]
|
44
|
+
end
|
45
|
+
|
46
|
+
def page_frame handler, entries
|
47
|
+
entries
|
48
|
+
end
|
49
|
+
|
50
|
+
def invoke handler
|
51
|
+
params = handler.params
|
52
|
+
# if params[:initial] || params[:refresh]
|
53
|
+
entries = data_source(handler)
|
54
|
+
|
55
|
+
per_page = lookup(:config, :per_page)
|
56
|
+
page = params[:page].to_i
|
57
|
+
handler.permit page >= 0 && page < 1000
|
58
|
+
|
59
|
+
if order_str = params[:order]
|
60
|
+
order = order_str.to_sym
|
61
|
+
handler.permit lookup(:fields, order, :sort)
|
62
|
+
entries = entries.sort_by{|e|e[order].to_s}
|
63
|
+
entries = entries.reverse if params[:asc] == "true"
|
64
|
+
end
|
65
|
+
|
66
|
+
if search = params[:search]
|
67
|
+
entries = list_search(entries, handler, search)
|
68
|
+
end
|
69
|
+
|
70
|
+
{entries: page_frame(handler, entries[page, per_page]), count: entries.size}
|
71
|
+
end
|
72
|
+
|
73
|
+
def list_search entries, handler, search
|
74
|
+
hash = JSON.parse(search, symbolize_names: true) rescue handler.halt_forbidden
|
75
|
+
model = assets[:model]
|
76
|
+
sfields = lookup(:search_field_list)
|
77
|
+
handler.permit sfields
|
78
|
+
hash.each_pair do |name, value|
|
79
|
+
handler.permit sfields.include?(name)
|
80
|
+
|
81
|
+
type_info = model.find_type_info(name)
|
82
|
+
entries = if filter = (@filters && @filters[name]) || (dynamic? && (static.filters && static.filters[name]))
|
83
|
+
filter.(handler, entries, hash)
|
84
|
+
elsif filter = DefaultFilters[type_info[:otype]]
|
85
|
+
filter.(entries, name, value, type_info, hash)
|
86
|
+
else
|
87
|
+
raise E2Error.new("Filter not found for field '#{name}' in model '#{model}'") unless filter
|
88
|
+
end
|
89
|
+
|
90
|
+
handler.permit entries
|
91
|
+
end
|
92
|
+
|
93
|
+
entries
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class ArrayViewAction < Action
|
98
|
+
include ActionViewSupport
|
99
|
+
|
100
|
+
def find_record handler, id
|
101
|
+
node.parent.*.data_source(handler)[id.to_i]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class ArrayFormAction < Action
|
106
|
+
end
|
107
|
+
|
108
|
+
class ArrayCreateAction < ArrayFormAction
|
109
|
+
include ActionCreateSupport
|
110
|
+
end
|
111
|
+
|
112
|
+
class ArrayModifyAction < ArrayFormAction
|
113
|
+
include ActionModifySupport
|
114
|
+
|
115
|
+
def find_record handler, id
|
116
|
+
node.parent.*.data_source(handler)[id.to_i]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class ArrayDeleteAction < Action
|
121
|
+
include ActionDeleteSupport
|
122
|
+
|
123
|
+
def invoke handler
|
124
|
+
handler.permit id = handler.params[:id]
|
125
|
+
node.parent.parent.*.data_source(handler).delete_at(id.to_i)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class ArraySaveAction < Action
|
130
|
+
include ActionApproveSupport
|
131
|
+
end
|
132
|
+
|
133
|
+
class ArrayInsertAction < ArraySaveAction
|
134
|
+
include ActionInsertSupport
|
135
|
+
action_type :approve
|
136
|
+
|
137
|
+
def after_approve handler, record
|
138
|
+
# handler.permit id = record[:id]
|
139
|
+
# ds = node.parent.parent.*.data_source(handler)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class ArrayUpdateAction < ArraySaveAction
|
144
|
+
include ActionUpdateSupport
|
145
|
+
action_type :approve
|
146
|
+
|
147
|
+
def after_approve handler, record
|
148
|
+
handler.permit id = record[:id]
|
149
|
+
node.parent.parent.*.data_source(handler)[id].merge!(record.values)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class Schemes
|
154
|
+
ARRAY_CRUD ||= {array_create: true, array_view: true, array_modify: true, array_delete: true}.freeze
|
155
|
+
ARRAY_VIEW ||= {array_view: true}
|
156
|
+
end
|
157
|
+
|
158
|
+
SCHEMES.instance_eval do
|
159
|
+
define_scheme :array_view do |name = :view|
|
160
|
+
define_node name, ArrayViewAction
|
161
|
+
end
|
162
|
+
|
163
|
+
define_scheme :array_modify do |name = :modify|
|
164
|
+
define_node name, ArrayModifyAction do
|
165
|
+
define_node :approve, ArrayUpdateAction
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
define_scheme :array_create do |name = :create|
|
170
|
+
define_node name, ArrayCreateAction do
|
171
|
+
define_node :approve, ArrayInsertAction
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
define_scheme :array_delete do
|
176
|
+
run_scheme :confirm, :delete, ArrayDeleteAction,
|
177
|
+
message: LOCS[:delete_question], title: LOCS[:confirm_delete_title]
|
178
|
+
end
|
179
|
+
|
180
|
+
define_scheme :array do |name, model, options|
|
181
|
+
options ||= Schemes::ARRAY_CRUD
|
182
|
+
define_node name, ArrayListAction, model: model do
|
183
|
+
options.each{|k, v| run_scheme(k) if v}
|
184
|
+
|
185
|
+
define_node_bundle :form, :create, :modify if options[:array_create] && options[:array_modify]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Engine2
|
4
|
-
class
|
5
|
-
include
|
5
|
+
class DecodeAction < Action
|
6
|
+
include ActionAPISupport, ActionModelSupport, ActionQuerySupport
|
6
7
|
|
7
8
|
def decode *fields, &blk
|
8
9
|
query select(*fields), &blk
|
@@ -18,8 +19,8 @@ module Engine2
|
|
18
19
|
end
|
19
20
|
|
20
21
|
def post_process
|
21
|
-
if fields = @meta[:
|
22
|
-
fields = fields - static.
|
22
|
+
if fields = @meta[:field_list]
|
23
|
+
fields = fields - static.meta[:field_list] if dynamic?
|
23
24
|
# no decorate here
|
24
25
|
fields.each do |name|
|
25
26
|
type_info = assets[:model].type_info[name] # foreign keys ?
|
@@ -42,7 +43,7 @@ module Engine2
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def post_run
|
45
|
-
|
46
|
+
decode(*assets[:model].primary_keys) unless @query
|
46
47
|
@meta[:separator] = '/' unless @meta[:separator]
|
47
48
|
super
|
48
49
|
@meta[:primary_fields] = assets[:model].primary_keys
|
@@ -50,48 +51,78 @@ module Engine2
|
|
50
51
|
|
51
52
|
end
|
52
53
|
|
53
|
-
class
|
54
|
-
|
54
|
+
class DecodeListAction < DecodeAction
|
55
|
+
action_type :decode_list
|
55
56
|
|
56
57
|
def invoke handler
|
57
|
-
{entries: get_query.limit(200).
|
58
|
+
{entries: get_query.limit(200).load_all}
|
59
|
+
end
|
60
|
+
|
61
|
+
def order *fields
|
62
|
+
@query = get_query.order *fields
|
58
63
|
end
|
59
64
|
end
|
60
65
|
|
61
|
-
class
|
62
|
-
|
66
|
+
class TypeAheadAction < DecodeAction
|
67
|
+
action_type :typeahead
|
63
68
|
|
64
69
|
def pre_run
|
65
70
|
super
|
66
|
-
limit 10
|
71
|
+
@limit = 10
|
67
72
|
end
|
68
73
|
|
69
74
|
def limit lmt
|
70
|
-
@
|
75
|
+
@limit = lmt
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_limit
|
79
|
+
@limit
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_case_insensitive
|
83
|
+
@case_insensitive
|
84
|
+
end
|
85
|
+
|
86
|
+
def case_insensitive
|
87
|
+
@case_insensitive = true
|
88
|
+
end
|
89
|
+
|
90
|
+
def order *fields
|
91
|
+
@query = get_query.order *fields
|
71
92
|
end
|
72
93
|
|
73
94
|
def invoke handler
|
95
|
+
model = assets[:model]
|
74
96
|
if query = handler.params[:query]
|
75
|
-
|
76
|
-
|
97
|
+
fields = @meta[:decode_fields] || static.meta[:decode_fields]
|
98
|
+
|
99
|
+
entries = if query.to_s.empty?
|
100
|
+
get_query
|
101
|
+
else
|
102
|
+
table_name = model.table_name
|
103
|
+
condition = fields.map{|f|table_name.q(f).like("%#{query}%", case_insensitive: @case_insensitive || static.get_case_insensitive)}.reduce{|q, f| q | f}
|
104
|
+
get_query.where(condition)
|
105
|
+
end.limit(@limit || static.get_limit).load_all
|
106
|
+
|
107
|
+
{entries: entries}
|
77
108
|
else
|
78
109
|
handler.permit id = handler.params[:id]
|
79
|
-
record = get_query
|
110
|
+
record = get_query.unordered.load Hash[model.primary_keys_qualified.zip(split_keys(id))]
|
80
111
|
# handler.halt_not_found(LOCS[:no_entry]) unless record
|
81
112
|
{entry: record}
|
82
113
|
end
|
83
114
|
end
|
84
115
|
end
|
85
116
|
|
86
|
-
class
|
87
|
-
|
117
|
+
class DecodeEntryAction < DecodeAction
|
118
|
+
action_type :decode_entry
|
88
119
|
|
89
120
|
def invoke handler
|
90
121
|
{entries: invoke_decode(handler, handler.param_to_json(:ids))}
|
91
122
|
end
|
92
123
|
|
93
124
|
def invoke_decode handler, ids
|
94
|
-
records = get_query.where(ids.map{|keys| Hash[assets[:model].primary_keys.zip(keys)]}.
|
125
|
+
records = get_query.where(ids.map{|keys| Hash[assets[:model].primary_keys.zip(keys)]}.reduce{|q, c| q | c}).load_all
|
95
126
|
# handler.halt_not_found(LOCS[:no_entry]) if records.empty?
|
96
127
|
records
|
97
128
|
end
|
@@ -101,9 +132,9 @@ module Engine2
|
|
101
132
|
if assoc = assets[:assoc]
|
102
133
|
decode = assoc[:model].type_info[assoc[:keys].first][:decode]
|
103
134
|
|
104
|
-
if decode[:search][:multiple] &&
|
105
|
-
|
106
|
-
|
135
|
+
if decode[:search][:multiple] && node.parent.parent.*.is_a?(ListAction)
|
136
|
+
node.list.*.menu(:panel_menu).option :choose, icon: :ok #, disabled: "action.selected_size() == 0"
|
137
|
+
node.list.*.menu(:panel_menu).option :cancel, icon: "remove"
|
107
138
|
end
|
108
139
|
end
|
109
140
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Engine2
|
5
|
+
class DeleteActionBase < Action
|
6
|
+
def invoke_delete_db handler, ids, from_assoc = nil
|
7
|
+
model = assets[:model]
|
8
|
+
model.db.transaction do
|
9
|
+
ids.each do |id|
|
10
|
+
keys = split_keys(id)
|
11
|
+
|
12
|
+
model.association_reflections.each do |name, assoc|
|
13
|
+
ds = case assoc[:type]
|
14
|
+
when :one_to_one
|
15
|
+
when :one_to_many
|
16
|
+
model.db[assoc.associated_class.table_name].where(Hash[assoc[:keys].zip(keys)])
|
17
|
+
when :many_to_many
|
18
|
+
model.db[assoc[:join_table]].where(Hash[assoc[:left_keys].zip(keys)])
|
19
|
+
when :many_to_one
|
20
|
+
nil
|
21
|
+
else
|
22
|
+
unsupported_association assoc[:type]
|
23
|
+
end
|
24
|
+
|
25
|
+
if assoc[:delete] == :cascade || from_assoc == assoc.associated_class.table_name
|
26
|
+
ds.delete
|
27
|
+
else
|
28
|
+
raise Sequel::DestroyFailed.new("#{LOCS[:delete_restricted]}: #{name}") unless ds.empty?
|
29
|
+
end if ds
|
30
|
+
end
|
31
|
+
|
32
|
+
rec = model.call(Hash[model.primary_keys.zip(keys)])
|
33
|
+
rec.destroy(transaction: false)
|
34
|
+
# model.where(model.primary_keys_hash(keys)).delete # model.dataset[model.primary_key => id].delete
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
rescue Sequel::NoExistingObject
|
39
|
+
handler.halt_not_found LOCS[:no_entry]
|
40
|
+
rescue Sequel::DestroyFailed => failure
|
41
|
+
handler.halt_forbidden failure.error.to_s
|
42
|
+
{}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class DeleteAction < DeleteActionBase
|
47
|
+
include ActionDeleteSupport
|
48
|
+
|
49
|
+
def invoke handler
|
50
|
+
handler.permit id = handler.params[:id]
|
51
|
+
invoke_delete_db(handler, [id])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class BulkDeleteAction < DeleteActionBase
|
56
|
+
include ActionBulkDeleteSupport
|
57
|
+
|
58
|
+
def invoke handler
|
59
|
+
ids = handler.param_to_json(:ids)
|
60
|
+
handler.permit ids.is_a?(Array)
|
61
|
+
invoke_delete_db(handler, ids)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Engine2
|
5
|
+
class FormAction < Action
|
6
|
+
include ActionQuerySupport
|
7
|
+
end
|
8
|
+
|
9
|
+
class CreateAction < FormAction
|
10
|
+
include ActionCreateSupport
|
11
|
+
end
|
12
|
+
|
13
|
+
class ModifyAction < FormAction
|
14
|
+
include ActionModifySupport
|
15
|
+
end
|
16
|
+
end
|
@@ -1,61 +1,43 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Engine2
|
4
|
-
SCHEMES::define_scheme :
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
loc! logged_on: LOCS[:logged_on]
|
11
|
-
menu :menu do
|
12
|
-
properties group_class: "btn-group-sm"
|
13
|
-
option :inspect_modal, icon: :wrench, button_loc: false # , show: "action.logged_on"
|
14
|
-
|
15
|
-
option :logout_form, icon: :"log-out" # , show: "action.logged_on"
|
16
|
-
option :login_form, icon: :"log-in", disabled: 'action.action_pending()' # , show: "!action.logged_on"
|
17
|
-
end
|
18
|
-
|
19
|
-
@meta_type = :infra
|
20
|
-
|
21
|
-
define_invoke do |handler|
|
22
|
-
user = handler.user
|
23
|
-
{user: user ? user.to_hash : nil}
|
24
|
-
end
|
25
|
-
end
|
5
|
+
SCHEMES::define_scheme :login! do |user_info_model = UserInfo|
|
6
|
+
define_node :login_form, LoginFormAction, model: user_info_model do
|
7
|
+
access!{|h|!h.logged_in?}
|
8
|
+
define_node :login, LoginAction
|
9
|
+
end
|
10
|
+
end
|
26
11
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
12
|
+
SCHEMES::define_scheme :logout! do
|
13
|
+
define_node :logout_form, LogoutFormAction do
|
14
|
+
access! &:logged_in?
|
15
|
+
define_node :logout, LogoutAction
|
16
|
+
end
|
17
|
+
end
|
31
18
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
19
|
+
SCHEMES::define_scheme :infra! do |user_info_model = UserInfo|
|
20
|
+
run_scheme :login!, user_info_model
|
21
|
+
define_node :infra!, InfraAction do
|
22
|
+
run_scheme :login!, user_info_model
|
23
|
+
run_scheme :logout!
|
36
24
|
|
37
|
-
|
25
|
+
define_node :inspect_modal, InspectModalAction do
|
38
26
|
access! &:logged_in?
|
39
|
-
#
|
40
|
-
self.* do
|
41
|
-
extend MetaPanelSupport, MetaMenuSupport
|
42
|
-
modal_action
|
43
|
-
panel_template 'infra/inspect'
|
44
|
-
panel_title "#{:wrench.icon} Inspect"
|
45
|
-
panel_class "modal-huge"
|
46
|
-
panel[:backdrop] = true
|
47
|
-
menu(:panel_menu).option :cancel, icon: "remove"
|
48
|
-
end
|
49
|
-
define_action :inspect do
|
27
|
+
define_node :"inspect_#{SETTINGS[:name]}", WebSocketAction.inherit do
|
50
28
|
self.* do
|
51
|
-
@
|
29
|
+
@action_type = :inspect
|
30
|
+
|
31
|
+
ws_message do |msg, ws|
|
32
|
+
ws.send! number: msg[:number].to_i + 1
|
33
|
+
end
|
52
34
|
end
|
53
35
|
|
54
|
-
|
36
|
+
define_invoke :models do |handler|
|
55
37
|
{models: Sequel::DATABASES.map{|db| {name: db.uri, models: db.models.keys} }}
|
56
38
|
end
|
57
39
|
|
58
|
-
|
40
|
+
define_invoke :model_info do |handler|
|
59
41
|
db_name = handler.params[:db]
|
60
42
|
handler.permit db = Sequel::DATABASES.find{|d|d.uri == db_name || (d.uri && d.uri.start_with?(db_name))}
|
61
43
|
handler.permit model = db.models[handler.params[:model].to_sym]
|
@@ -71,18 +53,22 @@ module Engine2
|
|
71
53
|
}
|
72
54
|
}
|
73
55
|
end
|
56
|
+
|
57
|
+
define_invoke :environment do |handler|
|
58
|
+
{environment: handler.env}
|
59
|
+
end
|
74
60
|
end
|
75
61
|
end
|
76
62
|
end
|
77
63
|
end
|
78
64
|
|
79
65
|
SCHEMES::define_scheme :menu! do
|
80
|
-
|
66
|
+
define_node :menu!, MenuAction do
|
81
67
|
end
|
82
68
|
end
|
83
69
|
|
84
|
-
class
|
85
|
-
|
70
|
+
class FileStoreAction < Action
|
71
|
+
action_type :file_store
|
86
72
|
|
87
73
|
attr_accessor :model, :field
|
88
74
|
|
@@ -93,7 +79,7 @@ module Engine2
|
|
93
79
|
end
|
94
80
|
|
95
81
|
|
96
|
-
module
|
82
|
+
module BlobSupportAction
|
97
83
|
def serve_blob handler, entry, inf
|
98
84
|
handler.permit entry
|
99
85
|
handler.attachment entry[inf[:name_field]]
|
@@ -102,8 +88,8 @@ module Engine2
|
|
102
88
|
end
|
103
89
|
end
|
104
90
|
|
105
|
-
class
|
106
|
-
|
91
|
+
class DownloadFileStoreAction < Action
|
92
|
+
action_type :download
|
107
93
|
|
108
94
|
def invoke handler
|
109
95
|
handler.permit id = handler.params[:id]
|
@@ -111,28 +97,29 @@ module Engine2
|
|
111
97
|
handler.permit entry
|
112
98
|
handler.attachment entry[:name]
|
113
99
|
handler.content_type (entry[:mime].to_s.empty? ? "application/octet-stream" : entry[:mime])
|
114
|
-
info =
|
100
|
+
info = node.parent.*.model.type_info[node.parent.*.field]
|
115
101
|
open("#{info[:store][:files]}/#{entry[:name]}_#{id}", 'rb'){|f|f.read}
|
116
102
|
end
|
117
103
|
end
|
118
104
|
|
119
|
-
class
|
105
|
+
class UploadFileStoreAction < Action
|
120
106
|
http_method :post
|
121
|
-
|
107
|
+
action_type :upload
|
122
108
|
|
123
109
|
def invoke handler
|
124
110
|
file = handler.params[:file]
|
125
111
|
temp = file[:tempfile]
|
126
112
|
temp.close
|
127
113
|
rackname = File.basename(temp.path)
|
128
|
-
info =
|
129
|
-
File.rename(temp.path, "#{info[:store][:upload]}/#{rackname}")
|
114
|
+
info = node.parent.*.model.type_info[node.parent.*.field]
|
115
|
+
FileUtils.cp(temp.path, "#{info[:store][:upload]}/#{rackname}") # File.rename(temp.path, "#{info[:store][:upload]}/#{rackname}")
|
116
|
+
FileUtils.rm(temp.path)
|
130
117
|
{rackname: rackname}
|
131
118
|
end
|
132
119
|
end
|
133
120
|
|
134
|
-
class
|
135
|
-
|
121
|
+
class BlobStoreAction < Action
|
122
|
+
action_type :blob_store
|
136
123
|
|
137
124
|
attr_accessor :model, :field
|
138
125
|
|
@@ -145,13 +132,13 @@ module Engine2
|
|
145
132
|
end
|
146
133
|
end
|
147
134
|
|
148
|
-
class
|
149
|
-
include
|
150
|
-
|
135
|
+
class DownloadBlobStoreAction < Action
|
136
|
+
include BlobSupportAction
|
137
|
+
action_type :download_blob
|
151
138
|
|
152
139
|
def invoke handler
|
153
|
-
model =
|
154
|
-
inf = model.type_info[
|
140
|
+
model = node.parent.*.model
|
141
|
+
inf = model.type_info[node.parent.*.field]
|
155
142
|
handler.permit id = handler.params[:id]
|
156
143
|
|
157
144
|
entry = model.naked.select(inf[:bytes_field], inf[:name_field], inf[:mime_field]).where(model.primary_keys_hash(split_keys(id))).first
|
@@ -159,23 +146,23 @@ module Engine2
|
|
159
146
|
end
|
160
147
|
end
|
161
148
|
|
162
|
-
class
|
149
|
+
class UploadBlobStoreAction < Action
|
163
150
|
http_method :post
|
164
|
-
|
151
|
+
action_type :upload_blob
|
165
152
|
|
166
153
|
def invoke handler
|
167
154
|
file = handler.params[:file]
|
168
155
|
temp = file[:tempfile]
|
169
156
|
temp.close
|
170
157
|
rackname = File.basename(temp.path)
|
171
|
-
info =
|
158
|
+
info = node.parent.*.model.type_info[node.parent.*.field]
|
172
159
|
File.rename(temp.path, "#{info[:store][:upload]}/#{rackname}")
|
173
160
|
{rackname: rackname}
|
174
161
|
end
|
175
162
|
end
|
176
163
|
|
177
|
-
class
|
178
|
-
|
164
|
+
class ForeignBlobStoreAction < Action
|
165
|
+
action_type :blob_store
|
179
166
|
|
180
167
|
attr_accessor :model, :field
|
181
168
|
|
@@ -195,13 +182,13 @@ module Engine2
|
|
195
182
|
end
|
196
183
|
end
|
197
184
|
|
198
|
-
class
|
199
|
-
include
|
200
|
-
|
185
|
+
class DownloadForeignBlobStoreAction < Action
|
186
|
+
include BlobSupportAction
|
187
|
+
action_type :download_blob
|
201
188
|
|
202
189
|
def invoke handler
|
203
|
-
model =
|
204
|
-
inf = model.type_info[
|
190
|
+
model = node.parent.*.model
|
191
|
+
inf = model.type_info[node.parent.*.field]
|
205
192
|
assoc = model.association_reflections[inf[:assoc_name]]
|
206
193
|
blob_model = assoc.associated_class
|
207
194
|
handler.permit id = handler.params[:id]
|
@@ -213,9 +200,9 @@ module Engine2
|
|
213
200
|
end
|
214
201
|
end
|
215
202
|
|
216
|
-
# class
|
203
|
+
# class UploadForeignBlobStoreAction < Action
|
217
204
|
# http_method :post
|
218
|
-
#
|
205
|
+
# action_type :upload_blob
|
219
206
|
|
220
207
|
# def invoke handler
|
221
208
|
# file = handler.params[:file]
|
@@ -227,17 +214,63 @@ module Engine2
|
|
227
214
|
# end
|
228
215
|
# end
|
229
216
|
|
230
|
-
class
|
231
|
-
include
|
232
|
-
|
217
|
+
class InfraAction < Action
|
218
|
+
include ActionPanelSupport, ActionMenuSupport, ActionAPISupport
|
219
|
+
action_type :infra
|
220
|
+
|
221
|
+
def pre_run
|
222
|
+
super
|
223
|
+
panel_panel_template false
|
224
|
+
panel_template 'infra/index'
|
225
|
+
loc! logged_on: LOCS[:logged_on]
|
226
|
+
menu :menu do
|
227
|
+
properties group_class: "btn-group-sm"
|
228
|
+
option :inspect_modal, icon: :wrench, button_loc: false # , show: "action.logged_on"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def invoke handler
|
233
|
+
user = handler.user
|
234
|
+
{user: user ? user.to_hash : nil}
|
235
|
+
end
|
236
|
+
|
237
|
+
def login_meta menu_properties = {show: 'false'}, &blk
|
238
|
+
node.login_form.* &blk
|
239
|
+
menu(:menu).modify_option :login_form, menu_properties
|
240
|
+
node.parent.login_form.* &blk
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class InspectModalAction < Action
|
245
|
+
include ActionPanelSupport, ActionMenuSupport
|
246
|
+
action_type :inline
|
247
|
+
|
248
|
+
def pre_run
|
249
|
+
super
|
250
|
+
modal_action
|
251
|
+
panel_template 'infra/inspect'
|
252
|
+
panel_title "#{:wrench.icon} Inspect"
|
253
|
+
panel_class "modal-huge"
|
254
|
+
panel[:backdrop] = true
|
255
|
+
menu(:panel_menu).option :close, icon: "remove"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class LoginFormAction < Action
|
260
|
+
include ActionFormSupport
|
261
|
+
action_type :login_form
|
233
262
|
|
234
263
|
def pre_run
|
235
264
|
super
|
236
265
|
panel_class 'modal-default'
|
237
266
|
panel_title LOCS[:login_title]
|
238
|
-
|
267
|
+
fields! :name, loc: LOCS[:user_name]
|
239
268
|
menu(:panel_menu).modify_option :approve, name: :login, icon: :"log-in"
|
240
|
-
@meta[:
|
269
|
+
@meta[:field_list] = [:name, :password]
|
270
|
+
parent_action = node.parent.*
|
271
|
+
if parent_action.is_a? ActionMenuSupport
|
272
|
+
parent_action.menu(:menu).option :login_form, icon: :"log-in", disabled: "action.action_pending()"
|
273
|
+
end
|
241
274
|
end
|
242
275
|
|
243
276
|
def invoke handler
|
@@ -245,11 +278,11 @@ module Engine2
|
|
245
278
|
end
|
246
279
|
end
|
247
280
|
|
248
|
-
class
|
249
|
-
include
|
250
|
-
|
281
|
+
class LoginAction < Action
|
282
|
+
include ActionApproveSupport
|
283
|
+
action_type :login
|
251
284
|
|
252
|
-
def validate_record handler, record
|
285
|
+
def validate_record handler, record, parent_id
|
253
286
|
super
|
254
287
|
record.values[:password] = nil
|
255
288
|
end
|
@@ -263,15 +296,16 @@ module Engine2
|
|
263
296
|
end
|
264
297
|
end
|
265
298
|
|
266
|
-
class
|
267
|
-
include
|
268
|
-
|
299
|
+
class LogoutFormAction < Action
|
300
|
+
include ActionPanelSupport, ActionMenuSupport
|
301
|
+
action_type :logout_form
|
269
302
|
def pre_run
|
270
303
|
super
|
271
304
|
panel_template 'scaffold/message'
|
272
305
|
panel_title LOCS[:logout_title]
|
273
306
|
panel_class 'modal-default'
|
274
307
|
@meta[:message] = LOCS[:logout_message]
|
308
|
+
node.parent.*.menu(:menu).option :logout_form, icon: :"log-out" # , show: "action.logged_on"
|
275
309
|
menu :panel_menu do
|
276
310
|
option :logout, icon: "ok", loc: LOCS[:ok]
|
277
311
|
option :cancel, icon: "remove"
|
@@ -279,8 +313,8 @@ module Engine2
|
|
279
313
|
end
|
280
314
|
end
|
281
315
|
|
282
|
-
class
|
283
|
-
|
316
|
+
class LogoutAction < Action
|
317
|
+
action_type :logout
|
284
318
|
|
285
319
|
def invoke handler
|
286
320
|
handler.session.clear
|