module Lolita
module Configuration
class List < Lolita::Configuration::Base
include Observable
include Lolita::Builder
attr_reader :initialized_attributes,:page_criteria
attr_writer :title
lolita_accessor :per_page, :pagination_method, :actions
def initialize(dbp,*args,&block)
set_and_validate_dbp(dbp)
set_list_attributes do
set_attributes(*args)
self.instance_eval(&block) if block_given?
end
end
def title(new_title = nil)
if new_title
@title = new_title
end
Lolita::Utils.dynamic_string(@title, :default => dbp.klass.lolita_model_name.human(:count => 2))
end
def action name, options = {}, &block
@actions << decide_and_create_action(name, options, &block)
@actions.flatten!
end
# Allow to crate nested list for list
def list(*args, &block)
if args && args.any? || block_given?
association = dbi.associations[args[0].to_s.to_sym]
association_dbi = association && Lolita::DBI::Base.create(association.klass)
raise Lolita::UnknownDBPError.new("No DBI specified for list sublist") unless association_dbi
Lolita::LazyLoader.lazy_load(self,:@list,Lolita::Configuration::NestedList,association_dbi, self, :association_name => association.name,&block)
else
@list
end
end
# For details see Lolita::Configuration::Search
def search *args, &block
if (args && args.any?) || block_given?
@search = Lolita::Configuration::Search.new(self.dbi,*args,&block)
add_observer(@search)
end
@search
end
# Return page for list display. Method requires two arguments:
# * current_page - number of current page
# * request (optional) - request that is passed to adapter that passes this to model when #pagination_method is defined
def paginate(current_page, request = nil)
changed
@page_criteria = dbi.paginate(current_page,@per_page,:request => request, :pagination_method => @pagination_method)
notify_observers(:paginate,self,request)
@page_criteria
end
# Set columns. Allowed classes are Lolita::Configuration::Columns or
# Array.
def columns=(possible_columns)
if possible_columns.is_a?(Lolita::Configuration::Columns)
@columns = possible_columns
@columns.parent = self
elsif possible_columns.respond_to?(:each)
possible_columns.each{|possible_column|
column(possible_column)
}
else
raise ArgumentError.new("Accepts only Enumerable or Lolita::Configuration::Columns.")
end
end
# Define columns for list. On first read if there is no columns they will be created.
def columns(*args,&block)
if (args && args.any?) || block_given? || !@columns
self.columns = Lolita::Configuration::Columns.new(dbi,*args,&block)
end
@columns
end
# Block setter for columns
def column(*args,&block)
columns.column(*args, &block)
end
# checks if filter defined
def filter?
@filter.is_a?(Lolita::Configuration::Filter)
end
# Create or return filter
def filter(*args,&block)
if args && args.any? || block_given?
@filter = Lolita::Configuration::Filter.new(dbi,*args,&block)
add_observer(@filter)
end
@filter
end
def by_path(path)
path = path.dup
object = self
while path.any?
part = path.pop.match(/(l|c)_(\w+)/)
object = if part[1] == "l"
object.list
else
object.columns.by_name(part[2]).list
end
end
object
end
private
def set_list_attributes
init_default_attributes
yield if block_given?
create_default_actions
end
def init_default_attributes
initialize_actions
@per_page = Lolita.application.per_page || 10
end
def create_default_actions
if !skip_actions? && ( default_actions? || actions_empty?)
initialize_actions
@actions << add_edit_action
@actions << add_destroy_action
end
end
def initialize_actions
@actions = [] unless @actions.respond_to?(:each)
end
def default_actions?
actions.to_s.to_sym == :default
end
def included_default_actions?
actions.include?(:default)
end
def actions_empty?
(@actions.respond_to?(:each) && @actions.empty?)
end
def skip_actions?
actions.to_s.to_sym == :none
end
def decide_and_create_action(name, options ={}, &block)
if name.to_s == 'default'
[add_edit_action,add_destroy_action]
else
create_action(name,options,&block)
end
end
def create_action name, options = {}, &block
Lolita::Configuration::Action.new(@dbi,name,options,&block)
end
def add_edit_action
unless actions.detect{|existing_action| existing_action.name == :edit}
create_action(:edit, &edit_action_block)
end
end
def add_destroy_action
unless actions.detect{|existing_action| existing_action.name == :destroy}
create_action(:destroy, &destroy_action_block)
end
end
def edit_action_block
Proc.new do
title Proc.new{::I18n.t("lolita.shared.edit")}
url Proc.new{|view,record| view.send(:edit_lolita_resource_path, :id => record.id)}
end
end
def destroy_action_block
Proc.new do
title Proc.new{::I18n.t("lolita.shared.delete")}
url Proc.new{|view,record| view.send(:lolita_resource_path,:id => record.id)}
html method: :delete, data: { confirm: Proc.new{::I18n.t("lolita.list.confirm")} }
end
end
end
end
end