engine2 1.0.4 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|