lib/engine2/meta.rb in engine2-1.0.2 vs lib/engine2/meta.rb in engine2-1.0.3
- old
+ new
@@ -24,14 +24,10 @@
@action = action
@assets = assets
@static = static
end
- # def self.method_added name
- # puts "ADDED #{name}"
- # end
-
def http_method
@http_method # || (raise E2Error.new("No http method for meta #{self.class}"))
end
def meta_type
@@ -45,26 +41,18 @@
def invoke! handler
if rmp = @request_meta_proc
meta = self.class.new(action, assets, self)
meta.instance_exec(handler, *meta.request_meta_proc_params(handler), &rmp)
meta.post_process
-
- {response: meta.invoke(handler), meta: meta.get}
+ response = meta.invoke(handler)
+ response[:meta] = meta.get
+ response
else
- response = invoke(handler)
- if response.is_a?(Hash)
- {response: response}
- else
- response
- end
+ invoke(handler)
end
end
- def response args
- (@meta[:response] ||= {}).merge!(args)
- end
-
def get
@meta
end
def dynamic?
@@ -140,10 +128,18 @@
class DummyMeta < Meta
meta_type :dummy
end
+ class RootMeta < Meta
+ def initialize *args
+ super
+ @meta[:environment] = Handler::environment
+ @meta[:application] = Engine2::app_name
+ end
+ end
+
module MetaAPISupport
def reload_routes!
@meta[:reload_routes] = true
end
@@ -156,20 +152,16 @@
end
def info! *fields, options
raise E2Error.new("No fields given to info") if fields.empty?
fields.each do |field|
- if options
- (info[field] ||= {}).merge! options # rmerge ?
- else
- info[field] = false
- end
+ (info[field] ||= {}).merge! options # rmerge ?
end
end
def loc! hash
- hash.each{|k, v| info! k, loc: v}
+ (@meta[:loc] ||= {}).merge! hash
end
def decorate list
list.each do |f|
m = (info[f] ||= {})
@@ -200,10 +192,14 @@
@menus[menu_name] ||= ActionMenuBuilder.new(:root)
@menus[menu_name].instance_eval(&blk) if blk
@menus[menu_name]
end
+ def menu? menu_name
+ @menus && @menus[menu_name]
+ end
+
def post_process
super
if @menus && !@menus.empty?
@meta[:menus] = {}
@menus.each_pair do |name, menu|
@@ -354,10 +350,14 @@
else
@query
end
end
+ def find_record handler, id
+ get_query[assets[:model].primary_keys_hash_qualified(split_keys(id))]
+ end
+
def select *args, &blk
assets[:model].select(*args, &blk).ensure_primary_key.setup! (@meta[:fields] = [])
end
end
@@ -422,11 +422,11 @@
super
if @meta[:panel]
panel_panel_template 'menu_m' unless panel[:panel_template] == false
# modal_action false if panel[:panel_template] == false
panel_class '' unless panel[:class]
- footer true unless panel[:footer] == false
+ panel_footer true if panel[:footer] != false && menu?(:panel_menu)
end
end
def panel
@meta[:panel] ||= {}
@@ -450,11 +450,11 @@
def panel_title tle
panel[:title] = tle
end
- def footer ftr
+ def panel_footer ftr
panel[:footer] = ftr
end
end
class MenuMeta < Meta
@@ -468,18 +468,22 @@
class ConfirmMeta < Meta
include MetaPanelSupport, MetaMenuSupport
meta_type :confirm
+ def message msg
+ @meta[:message] = msg
+ end
+
def pre_run
super
panel_template 'scaffold/message'
panel_title LOCS[:confirmation]
panel_class 'modal-default'
menu :panel_menu do
- option :approve, icon: "ok", loc: LOCS[:ok], disabled: 'action.action_pending'
+ option :approve, icon: "ok", loc: LOCS[:ok], disabled: 'action.action_pending()'
option :cancel, icon: "remove"
end
end
def invoke handler
@@ -542,19 +546,18 @@
def pre_run
super
config.merge!(per_page: 10, use_count: false, show_item_menu: true, selectable: true) # search_active: false,
- # modal_action self.class != ListMeta
panel_template 'scaffold/list'
panel_panel_template 'panels/menu_m' unless action.parent.*.assets[:model]
search_template 'scaffold/search'
panel_title "#{:list.icon} #{LOCS[assets[:model].name.to_sym]}"
- menu(:panel_menu).option :cancel, icon: "remove"
+ loc! LOCS[:list_locs]
menu :menu do
properties break: 2, group_class: "btn-group-xs"
- option :search_toggle, icon: "search", show: "action.meta.search_fields", class: "action.ui_state.search_active && 'active'", button_loc: false
+ option :search_toggle, icon: "search", show: "action.meta.search_fields", active: "action.ui_state.search_active", button_loc: false
# divider
option :refresh, icon: "refresh", button_loc: false
option :default_order, icon: "signal", button_loc: false
divider
option :debug_info, icon: "list-alt" do
@@ -570,11 +573,11 @@
end
def select_toggle_menu
m = menu :menu
unless m.option_index(:select_toggle, false)
- m.option_after :default_order, :select_toggle, icon: "check", enabled: "action.meta.config.selectable", button_loc: false
+ m.option_after :default_order, :select_toggle, icon: "check", enabled: "action.meta.config.selectable", active: "action.selection", button_loc: false
end
end
def post_run
unless panel[:class]
@@ -723,11 +726,11 @@
end
def invoke handler
json = handler.post_to_json
record = allocate_record(handler, json)
- validate_and_approve(handler, record, json) ? static.record(handler, record) : {record: record.to_hash, errors: record.errors}
+ validate_and_approve(handler, record, json) ? static.record(handler, record) : {record!: record.to_hash, errors!: record.errors}
end
def validate name, &blk
(@validations ||= {})[name] = blk
end
@@ -745,10 +748,158 @@
super
validate_fields *action.parent.*.get[:fields] unless validate_fields
end
end
+ module MetaFormSupport
+ include MetaModelSupport, MetaAPISupport, MetaTabSupport, MetaPanelSupport, MetaMenuSupport, MetaAngularSupport, MetaOnChangeSupport
+
+ def field_template template
+ panel[:field_template] = template
+ end
+
+ def pre_run
+ super
+ panel_template 'scaffold/form'
+ field_template 'scaffold/fields'
+ panel_class 'modal-large'
+
+ menu :panel_menu do
+ option :approve, icon: "ok", disabled: 'action.action_pending()' # text: true,
+ option :cancel, icon: "remove" # text: true,
+ end
+ # modal_action false
+ end
+
+ def record handler, record
+ end
+
+ def post_process
+ if fields = @meta[:fields]
+ fields = fields - static.get[:fields] if dynamic?
+
+ decorate(fields)
+
+ fields.each do |name|
+ # type_info = model.type_info.fetch(name)
+ type_info = get_type_info(name)
+
+ info[name][:render] ||= begin
+ renderer = DefaultFormRenderers[type_info[:type]] # .merge(default: true)
+ raise E2Error.new("No form renderer found for field '#{type_info[:name]}' of type '#{type_info[:type]}'") unless renderer
+ renderer.(self, type_info)
+ end
+
+ proc = FormRendererPostProcessors[type_info[:type]]
+ proc.(self, name, type_info) if proc
+ end
+
+ assoc = assets[:assoc]
+ if assoc && assoc[:type] == :one_to_many
+ # fields.select{|f| assoc[:keys].include? f}.each do |key|
+ # # hide_fields(key) if self[:info, key, :hidden] == nil
+ # info! key, disabled: true
+ # end
+ assoc[:keys].each do |key|
+ info! key, disabled: true if fields.include? key
+ end
+ end
+ end
+
+ super
+ end
+
+ def post_run
+ super
+ @meta[:primary_fields] = assets[:model].primary_keys
+ end
+
+ def template
+ Templates
+ end
+
+ def hr_after field, message = '-'
+ info! field, hr: message
+ end
+ end
+
+ module MetaCreateSupport
+ include MetaFormSupport
+
+ def self.included meta
+ meta.meta_type :create
+ end
+
+ def pre_run
+ super
+ panel_title LOCS[:create_title]
+ action.parent.*.menu(:menu).option_at 0, action.name, icon: "plus-sign", button_loc: false
+
+ hide_pk unless assets[:model].natural_key
+ end
+
+ def record handler, record
+ create_record(handler, record)
+ end
+
+ def create_record handler, record
+ end
+
+ def invoke handler
+ record = {}
+ if assoc = assets[:assoc]
+ case assoc[:type]
+ when :one_to_many
+ handler.permit parent = handler.params[:parent_id]
+ assoc[:keys].zip(split_keys(parent)).each{|key, val| record[key] = val}
+ end
+ end
+ static.record(handler, record)
+ {record: record, new: true}
+ end
+ end
+
+ module MetaModifySupport
+ include MetaFormSupport
+
+ def self.included meta
+ meta.meta_type :modify
+ end
+
+ def pre_run
+ super
+ panel_title LOCS[:modify_title]
+ action.parent.*.menu(:item_menu).option action.name, icon: "pencil", button_loc: false
+ end
+
+ def record handler, record
+ modify_record(handler, record)
+ end
+
+ def modify_record handler, record
+ end
+
+ def invoke handler
+ handler.permit id = handler.params[:id]
+ record = find_record(handler, id)
+
+ if record
+ static.record(handler, record)
+ {record: record}
+ else
+ handler.halt_not_found LOCS[:no_entry]
+ end
+ end
+
+ def post_run
+ super
+ assets[:model].primary_keys.each do |key| # pre_run ?
+ info! key, disabled: true
+ end
+ end
+ end
+
module MetaViewSupport
include MetaModelSupport, MetaAPISupport, MetaTabSupport, MetaPanelSupport, MetaMenuSupport
def self.included meta
meta.meta_type :view
@@ -761,10 +912,24 @@
menu(:panel_menu).option :cancel, icon: "remove"
action.parent.*.menu(:item_menu).option action.name, icon: "file", button_loc: false
end
+ def record handler, record
+ end
+
+ def invoke handler
+ handler.permit id = handler.params[:id]
+ record = find_record(handler, id)
+ if record
+ static.record(handler, record)
+ {record: record}
+ else
+ handler.halt_not_found LOCS[:no_entry]
+ end
+ end
+
def post_process
if fields = @meta[:fields]
fields = fields - static.get[:fields] if dynamic?
decorate(fields)
@@ -848,11 +1013,10 @@
many_to_one: lambda{|meta, field, info|
field_info = meta.info[field]
field_info[:assoc] = :"#{info[:assoc_name]}!"
field_info[:fields] = info[:keys]
field_info[:type] = info[:otype]
- # field_info[:table_loc] = LOCS[info[:assoc_name]]
(info[:keys] - [field]).each do |of|
f_info = meta.info.fetch(of)
f_info[:hidden] = true
f_info[:type] = meta.assets[:model].type_info[of].fetch(:otype)
@@ -917,11 +1081,10 @@
field_info = meta.info[field]
field_info[:assoc] = :"#{info[:assoc_name]}!"
field_info[:fields] = keys
field_info[:type] = info[:otype]
- # field_info[:table_loc] = LOCS[info[:assoc_name]]
(keys - [field]).each do |of|
f_info = meta.info[of]
raise E2Error.new("Missing searchable field: '#{of}' in model '#{meta.assets[:model]}'") unless f_info
f_info[:hidden_search] = true
@@ -970,10 +1133,10 @@
max_length = info[:list].max_by{|a|a.last.length}.last.length
Templates.list_select(max_length, optional: !info[:required])
end
},
star_to_many_field: lambda{|meta, info| Templates.scaffold},
- many_to_one: lambda{|meta, info| # Templates.scaffold_picker
+ many_to_one: lambda{|meta, info|
tmpl_type = info[:decode][:form]
case
when tmpl_type[:scaffold]; Templates.scaffold_picker
when tmpl_type[:list]; Templates.bsselect_picker
when tmpl_type[:typeahead];Templates.typeahead_picker