Skip to content
This repository has been archived by the owner on Nov 17, 2017. It is now read-only.
/ auto_admin Public archive

Commit

Permalink
Initial import, from 0.0 release tarballs.
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewd committed Jul 15, 2006
0 parents commit 56c57dc
Show file tree
Hide file tree
Showing 65 changed files with 3,274 additions and 0 deletions.
20 changes: 20 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright (c) 2006 Matthew Draper

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
377 changes: 377 additions & 0 deletions README

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions init.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) 2006 Matthew Draper
# Released under the MIT License. See the LICENSE file for more details.

class ActionController::Routing::RouteSet
alias draw_without_admin draw
def draw_with_admin
draw_without_admin do |map|
map.connect 'admin', :controller => 'auto_admin', :action => 'index'
map.connect 'admin/-/:action/:id', :controller => 'auto_admin', :action => 'index',
:requirements => { :model => nil }
map.connect 'admin/asset/*path', :controller => 'auto_admin', :action => 'asset'

map.connect 'admin/:model/:action', :controller => 'auto_admin', :action => 'list',
:requirements => { :action => /[^0-9].*/, :id => nil }
map.connect 'admin/:model/:id/:action', :controller => 'auto_admin', :action => 'edit',
:requirements => { :id => /\d+/ }
yield map
end
end
alias draw draw_with_admin
end

class ::Object
def to_label
return label if respond_to? :label
return name if respond_to? :name
return to_s if respond_to? :to_s
inspect
end
end
class ::TrueClass; def to_label; 'Yes'; end; end
class ::FalseClass; def to_label; 'No'; end; end
class ::NilClass; def to_label; '(none)'; end; end

4 changes: 4 additions & 0 deletions lib/auto_admin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

require 'auto_admin_filter_sets'
require 'auto_admin_configuration'

306 changes: 306 additions & 0 deletions lib/auto_admin_configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
require 'auto_admin_simple_theme'

module AutoAdmin
def self.config
yield AutoAdminConfiguration
end
module AutoAdminConfiguration
DefaultTheme = :django
def self.theme; Object.const_get("AutoAdmin#{theme_name.to_s.camelize}Theme"); end
def self.theme_name; @@theme ||= DefaultTheme; end
def self.theme=(theme_name)
@@theme = theme_name.to_sym
end
def self.form_processor; theme::FormProcessor; end
def self.form_builder; theme::FormBuilder; end
def self.table_builder; theme::TableBuilder; end
def self.view_directory; theme.view_directory; end
def self.asset_root; theme.asset_root; end
def self.helpers; theme.respond_to?( :helpers ) ? [theme.helpers].flatten : []; end

def self.set_site_info full_url, site_name, admin_site_title='Site Administration'
::AutoAdminHelper.site = ::AutoAdminHelper::Site.new full_url, site_name, admin_site_title
end
def self.primary_objects; @@primary_objects ||= []; end
def self.primary_objects= new_value; @@primary_objects = new_value; end
def self.model name
Object.const_get( name.to_s.camelcase )
end
def self.grouped_objects
objects = primary_objects.uniq.map { |po| model(po) }
groups = objects.map { |o| o.object_group }.uniq.sort
groups.each do |group|
group_objects = objects.find_all { |o| o.object_group == group }.sort_by { |o| o.name }
yield group, group_objects
end
end
def self.append_features base
super
base.extend ClassMethods
end
module ClassMethods
def self.defaulted_accessor name, default_value
class_eval <<EVAL
def #{name}; @#{name} ||= (respond_to?(:default_#{name}) ? default_#{name} : nil) || #{default_value}; end
def #{name}= new_value; @#{name} = new_value; end
EVAL
end
def self.array_accessor *names
names.each {|name| defaulted_accessor name, '[]' }
end
def self.hash_accessor *names
names.each {|name| defaulted_accessor name, '{}' }
end
array_accessor :columns_for_search, :columns_for_filter
hash_accessor :labels_for_columns, :custom_filter_defaults
def filter_defaults
f = {}
columns_for_filter.each { |c| f[c.to_s] = '*' }
custom_filter_defaults.each { |k,v| f[k.to_s] = v.to_s }
f
end
def default_columns_for_list
columns = content_columns.select {|c| c.type != :binary }.map {|c| c.name}
#reflect_on_all_associations.select {|a| a.macro == :belongs_to }.each do |assoc|
# columns << assoc.name
#end
columns
end
def sort_by column, reverse=false; @sort_column = column.to_s; @sort_reverse = reverse; end
def search_by *columns; extend Searchable; @columns_for_search = columns; end
def filter_by *columns; @columns_for_filter = ensure_columns_are_filterable!(columns); end
def ensure_columns_are_filterable! columns
columns.each do |col|
raise "Unable to filter #{self} on column '#{col}'" unless filter_type( col )
end
end
def default_filter filters; custom_filter_defaults.update filters.stringify_keys; end
def list_columns(*columns, &proc)
if block_given? || !columns.empty?
@list_fieldset = ListFieldset.new(self, columns, proc)
else
@list_fieldset || ListFieldset.new(self, default_columns_for_list)
end
end
def column_labels labels; labels_for_columns.update labels.stringify_keys; end
def column_label column; labels_for_columns[column.to_s] || default_column_label( column.to_s ); end
def default_column_label column
label = column.to_s.humanize
label = "Date #{label.downcase}" if label.gsub!(/ on$| at$/, '')
label
end

def find_column name; name &&= name.to_s.sub(/\?$/, ''); columns.find { |c| name == c.name }; end

def filter_conditions filter_hash
statement_parts = []
parameters = []
merged_filters = filter_defaults.stringify_keys.merge((filter_hash || {}).stringify_keys)
filters.each do |filter|
option_sql = filter.sql( merged_filters[filter.name] )
unless option_sql.empty?
statement_parts << option_sql.shift
parameters.push *option_sql
end
end
[ statement_parts.join( ' AND '), *parameters ] unless statement_parts.empty?
end

def filter_option_sql column_name, option_name
filter_instance(column_name).sql(option_name)
end

def filter_options_for column_name, custom_options, &block
(@custom_filter_options ||= {})[column_name.to_sym] = AutoAdmin::CustomFilterSet.new( column_name, custom_options, &block )
end
def filters
columns_for_filter.map { |col| filter_instance( col ) }
end
def filter_instance column_name
column_name = column_name.to_sym
return @custom_filter_options[column_name] if @custom_filter_options && @custom_filter_options.has_key?( column_name )

klass = case type = filter_type( column_name )
when :belongs_to: AutoAdmin::AssociationFilterSet
when :has_one: AutoAdmin::AssociationFilterSet
when :datetime: AutoAdmin::DateFilterSet
else
const = type.to_s.camelcase + 'FilterSet'
if AutoAdmin.const_defined?( const )
AutoAdmin.const_get( const )
else
AutoAdmin::EmptyFilterSet
end
end

klass.new( self, reflect_on_association( column_name ) || find_column( column_name ) ) {|col| find_column(col) }
end
def filter_type column_name
column_name = column_name.to_sym
return :custom if @custom_filter_options && @custom_filter_options.has_key?( column_name )

column = find_column( column_name )
assoc = reflect_on_association( column_name )
return ( assoc && assoc.macro ) || ( column && column.type )
end

def searchable?; respond_to? :append_search_condition!; end
def sortable_by? column; find_column column; end
def default_sort_info; find_column( 'name' ) && { :column => 'name', :reverse => false }; end
def sort_column; defined?( @sort_column ) ? @sort_column : (default_sort_info[:column] rescue nil); end
def sort_reverse; defined?( @sort_column ) ? @sort_reverse : (default_sort_info[:reverse] rescue nil); end

array_accessor :admin_fieldsets
def default_admin_fieldsets
[InputFieldset.new( self, '', default_columns_for_edit )]
end
def active_admin_fieldsets
sets = admin_fieldsets
sets = default_admin_fieldsets + sets unless sets.find {|s| s.fieldset_type == :input }
sets
end
def default_columns_for_edit
columns = content_columns.map {|c| c.name}
reflect_on_all_associations.select {|a| [:belongs_to, :has_and_belongs_to_many].include?(a.macro) }.each do |assoc|
columns << assoc.name.to_s
end
columns
end
def admin_fieldset label='', *columns, &proc
set = InputFieldset.new( self, label, columns.map {|c| c.to_s }, proc )
(@admin_fieldsets ||= []) << set
end
def admin_child_table label, collection, options={}, &proc
(@admin_fieldsets ||= []) << TableFieldset.new( self, label, collection, proc, options )
end
def admin_child_form collection, options={}, &proc
(@admin_fieldsets ||= []) << ChildInputFieldset.new( self, collection, proc, options )
end

def object_group new_group=nil
@object_group = new_group if new_group
@object_group || ''
end

class ListFieldset
attr_accessor :object, :fields, :options, :proc
def initialize object, fields=[], proc=nil
@options = fields.last.is_a?(Hash) ? fields.pop : {}
@object, @fields, @proc = object, fields, proc
end
def build builder
builder.fieldset( :table ) do
fields.each {|f| builder.static_text f } if fields
proc.call( builder ) if proc
end
end
end
class InputFieldset
attr_accessor :object, :name, :fields, :options, :proc
def initialize object, name, fields=[], proc=nil
@options = fields.last.is_a?(Hash) ? fields.pop : {}
@object, @name, @fields, @proc = object, name, fields, proc
end
def build builder
builder.fieldset( :fields, name != '' ? name : nil ) do
fields.each {|f| builder.auto_field f } if fields
proc.call( builder ) if proc
end
end
def fieldset_type; :input; end
end
class ChildInputFieldset
attr_accessor :object, :field, :proc, :options
DEFAULT_CHILD_OPTIONS = { :read_only => true }.freeze
def initialize object, field, proc, options
@object, @field, @proc, @options = object, field, proc, DEFAULT_CHILD_OPTIONS.merge(options)
end
def build_object(builder, obj, idx, caption)
builder.inner_fields_for( field.to_s + '_' + idx, obj ) do |inner|
inner.fieldset( :fields, caption ) do
yield inner if block_given?
proc.call( inner ) if proc
end
end
end
def build builder, children=nil
children ||= builder.object.send( field )
idx = -1
children.each_with_index do |row, idx|
build_object(builder, row, idx, row.to_label) do |inner|
inner.hidden_field :id
end
end
if children.respond_to? :build
1.upto blank_records do |n|
idx += 1
build_object(builder, children.build, idx,
"#{row.class.name.underscore.humanize.downcase} ##{n}")
end
end
end
def fieldset_type; :child_input; end
def blank_records; options[:read_only] ? 0 : options[:blank_records] || 3; end
end
class TableFieldset < ChildInputFieldset
attr_accessor :name
def initialize object, name, field, proc, options
@name = name
super object, field, proc, options
end
def fieldset_type; :tabular; end

def build_object(builder, obj, idx, caption)
builder.with_object(obj) do
builder.fieldset( :fields, caption ) do
yield builder if block_given?
proc.call( builder ) if proc
end
end
end
def build builder
children = builder.object.send( field )
builder.fieldset( :table, name ) do
model = object.reflect_on_association( field ).klass
builder.table_fields_for( field, nil, :model => model ) do |inner|
inner.outer do
inner.prologue do
build_object(inner, nil, nil, nil)
end
super inner, children
inner.epilogue do
end
end
end
end
end
end

module Searchable
def append_search_condition!(query, options={})
unless query.empty?
conditions = options[:conditions] || []
conditions = [conditions] unless conditions.is_a? Array
new_condition = '(' + columns_for_search.map { |col| "#{col} LIKE ?" }.join( ' OR ' ) + ')'
if conditions.size > 0
conditions[0] = "(#{conditions[0]}) AND (#{new_condition})"
else
conditions[0] = new_condition
end
conditions.push *( [ "%#{query}%" ] * columns_for_search.size )
options[:conditions] = conditions
end
options
end
def search many, query, options={}
options = options.dup
append_search_condition! query, options
find many, options
end
end
end
::ActiveRecord::Base.send :include, self
end
end


Loading

0 comments on commit 56c57dc

Please sign in to comment.