module Edgarj module Drawer # 'Mediator' to draw list and form of the model on the view. class Base attr_accessor :vc # * options # * list_drawer_options - options for Edgarj::ListDrawer::Normal # * draw_form_options - options for draw_form_options def initialize(view_context, params, page_info, model, options={}) @vc = view_context @params = params @page_info = page_info @model = model @options = options.dup end # level-1 methods which may be modified most frequently: # define model-wide default columns for view. # # If you need to customize, overwrite it at derived model class. # Example: # def columns # %w(id name email updated_at) # end # # === SEE ALSO # list_columns:: define list columns # form_columns:: define form columns # search_form_columns:: define search form columns def columns @model.columns.map{|c| c.name} end # This defines list columns. # You can overwrite this method at each model if it is different from # columns. Default is calling columns(). # # === SEE ALSO # columns:: define default columns # form_columns:: define form columns # search_form_columns:: define search form columns # def list_columns columns end # This defines form columns. # You can overwrite this method at each model if it is different from # columns. Default is calling columns(). # # === SEE ALSO # columns:: define default columns # list_columns:: define list columns # search_form_columns:: define search form columns # def form_columns columns end # This defines search-form columns. # You can overwrite this method at each model if it is different from # columns. Default is calling columns(). # # === SEE ALSO # columns:: define default columns # list_columns:: define list columns # form_columns:: define form columns # def search_form_columns columns end # level-2 methods which may be modified occasionally: # This defines popup path for the column on the model. # # Default returns parent model's popup-controller. # For example, book.author_id -> 'authors_popup' path # # You can overwrite this method at each model if it is different from # columns. # # @see popup_path_on_search popup path for the column on the model's search form def popup_path(col) parent_model = @model.belongs_to_AR(col) raise 'Parent is nil' if !parent_model popup_field = PopupHelper::PopupField.new_builder(@model.model_name.param_key, col.name) @vc.main_app.url_for( controller: parent_model.model_name.collection + '_popup', id_target: popup_field.id_target) end # This defines popup path for the search column on the model. # # Default returns parent model's popup-controller with id_target # on the search column. # # @see popup_path popup path for the column on the model itself def popup_path_on_search(col) parent_model = @model.belongs_to_AR(col) raise 'Parent is nil' if !parent_model popup_field = PopupHelper::PopupField.new_builder(Edgarj::SearchForm.model_name.param_key, col.name) @vc.main_app.url_for( controller: parent_model.model_name.collection + '_popup', id_target: popup_field.id_target) end # draw sort link on list column header # # === INPUTS # col:: column data # options:: options to url_for def draw_sort(col, options={}) label = @model.human_attribute_name(col.name) dir = 'asc' if @page_info.order_by == fullname(col) # toggle direction if @page_info.dir == 'asc' || @page_info.dir.blank? label += '▲' dir = 'desc' else label += '▼' end end @vc.link_to(label, { :controller => @params[:controller], :action => 'page_info_save', :id => @page_info.id, 'edgarj_page_info[order_by]' => fullname(col), 'edgarj_page_info[dir]' => dir }.merge(options), :remote => true, :method => :put) end # draw list column header for both usual list and popup list def draw_list_column_header(col, options={}) parent = @model.belongs_to_AR(col) if parent then @vc.draw_belongs_to_label_sub(@model, col.name, parent) else draw_sort(col, options) end end def list_drawer_class Edgarj::ListDrawer::Normal end def draw_list(list) line_color = 1 d = list_drawer_class.new( self, @options[:list_drawer_options] || {}) @vc.content_tag(:table, width: '100%', class: 'list') do @vc.content_tag(:tr) do ''.html_safe.tap do |result| for col in columns_for(list_columns) do result << @vc.content_tag(:th) do draw_list_column_header(col) end end end end + ''.html_safe.tap do |trs| for rec in list do line_color = 1 - line_color d.set_path(rec) trs << @vc.content_tag(:tr, class: "list_line#{line_color}") do ''.html_safe.tap do |cols| for col in columns_for(list_columns) do cols << d.draw_column(rec, col) end end end end end end end # return table_name + col.name def fullname(col) @model.table_name + '.' + col.name end # overwrite to replace form drawer for the model def form_drawer_class Edgarj::FormDrawer::Base end def draw_form(record) url_hash = { controller: @params[:controller], action: record.new_record? ? 'create' : 'update', } url_hash[:id] = record.id if record.persisted? @vc.draw_form_buttons(@options[:draw_form_options] || {}) + @vc.form_for(record, remote: true, url: url_hash, html: { id: '_edgarj_form', method: record.new_record? ? 'post' : 'put', multipart: true, #target: 'edgarj_form_frame' }) do |f| form_drawer_class.new(self, record, f).draw() + # to avoid submit on 1-textfield form when hit [ENTER] key ''.html_safe end end # return array of model columns (ActiveRecord::ConnectionAdapters::X_Column type). # # === INPUTS # column_name_list:: column name list def columns_for(column_name_list) [].tap do |result| for col_name in column_name_list do if (col = @model.columns_hash[col_name]) result << col end end end end # overwrite to replace form drawer for search def search_form_drawer_class Edgarj::FormDrawer::Search end def draw_search_form(record) @vc.form_for(record, url: {action: 'search'}, html: { id: '_edgarj_search_form', remote: true, method: :get}) do |f| f.fields_for(record._operator) do |o| search_form_drawer_class.new(self, record, f, o).draw() end + # to avoid submit on 1-textfield form when hit [ENTER] key ''.html_safe end end end end end