require 'active_support/core_ext'
require 'netzke/core_ext'
require 'netzke/javascript'
require 'netzke/stylesheets'
require 'netzke/services'
require 'netzke/composition'
require 'netzke/configuration'
require 'netzke/persistence'
require 'netzke/embedding'
require 'netzke/actions'
require 'netzke/session'
module Netzke
# = Base
# Base class for every Netzke component
#
# To instantiate a component in the controller:
#
# netzke :component_name, configuration_hash
#
# == Configuration
# * :class_name - name of the component class in the scope of the Netzke module, e.g. "FormPanel".
# When a component is defined in the controller and this option is omitted, component class is deferred from the component's
# name. E.g.:
#
# netzke :grid_panel, :model => "User"
#
# In this case :class_name is assumed to be "GridPanel"
#
# * :persistent_config - if set to true, the component will use persistent storage to store its state;
# for instance, Netzke::GridPanel stores there its columns state (width, visibility, order, headers, etc).
# A component may or may not provide interface to its persistent settings. GridPanel and FormPanel from netzke-basepack
# are examples of components that by default do.
#
# Examples of configuration:
#
# netzke :books,
# :class_name => "GridPanel",
# :model => "Book", # GridPanel specific option
# :persistent_config => false, # don't use persistent config for this instance
# :icon_cls => 'icon-grid',
# :title => "My books"
#
# netzke :form_panel,
# :model => "User" # FormPanel specific option
class Base
class_attribute :default_instance_config
self.default_instance_config = {}
include Session
include Persistence
include Configuration
include Javascript
include Services
include Composition
include Stylesheets
include Embedding
include Actions
attr_accessor :parent, :name, :global_id #, :permissions, :session
# Component initialization process
# * the config hash is available to the component after the "super" call in the initializer
# * override/add new default configuration options into the "default_config" method
# (the config hash is not yet available)
def initialize(conf = {}, parent = nil)
@passed_config = conf # configuration passed at the moment of instantiation
@passed_config.deep_freeze
@parent = parent
@name = conf[:name].nil? ? short_component_class_name.underscore : conf[:name].to_s
@global_id = parent.nil? ? @name : "#{parent.global_id}__#{@name}"
@flash = []
# initialize @components and @items
normalize_components_in_items
# auto_collect_actions_from_config_and_js_properties
end
# Short component class name, e.g.:
# Netzke::Module::SomeComponent => Module::SomeComponent
def self.short_component_class_name
self.name.sub(/^Netzke::/, "")
end
# Component class, given its name
def self.constantize_class_name(class_name)
"#{class_name}".constantize rescue "Netzke::#{class_name}".constantize
end
def constantize_class_name(class_name)
self.class.constantize_class_name(class_name)
end
# Instance of component by config
def self.instance_by_config(config)
constantize_class_name(config[:class_name]).new(config)
end
def logger
if defined?(Rails)
Rails.logger
else
require 'logger'
Logger.new(STDOUT)
end
end
# 'Netzke::Grid' => 'Grid'
def short_component_class_name
self.class.short_component_class_name
end
def flash(flash_hash)
level = flash_hash.keys.first
raise "Unknown message level for flash" unless %(notice warning error).include?(level.to_s)
@flash << {:level => level, :msg => flash_hash[level]}
end
def self.read_clean_inheritable_hash(attr_name)
res = read_inheritable_attribute(attr_name) || {}
# We don't want here any values from the superclass (which is the consequence of using inheritable attributes).
res == self.superclass.read_inheritable_attribute(attr_name) ? {} : res
end
# override this method to do stuff at the moment of loading by some parent
def before_load
# component_session.clear - we don't do it anymore
end
# Dependencies
def self.class_ancestors
if self == Netzke::Base
[]
else
superclass.class_ancestors + [self]
end
end
end
end