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