admin_assistant 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +3 -28
- data/Rakefile +18 -10
- data/init.rb +1 -0
- data/install.rb +5 -1
- data/lib/admin_assistant/active_record_column.rb +211 -0
- data/lib/admin_assistant/association_target.rb +35 -0
- data/lib/admin_assistant/belongs_to_column.rb +186 -0
- data/lib/admin_assistant/builder.rb +222 -35
- data/lib/admin_assistant/column.rb +266 -297
- data/lib/admin_assistant/default_search_column.rb +41 -0
- data/lib/admin_assistant/file_column_column.rb +73 -0
- data/lib/admin_assistant/form_view.rb +7 -68
- data/lib/admin_assistant/helper.rb +4 -2
- data/lib/admin_assistant/index.rb +101 -81
- data/lib/admin_assistant/paperclip_column.rb +45 -0
- data/lib/admin_assistant/polymorphic_belongs_to_column.rb +102 -0
- data/lib/admin_assistant/request/autocomplete.rb +47 -0
- data/lib/admin_assistant/request/base.rb +176 -0
- data/lib/admin_assistant/request/create.rb +27 -0
- data/lib/admin_assistant/request/destroy.rb +15 -0
- data/lib/admin_assistant/request/edit.rb +11 -0
- data/lib/admin_assistant/request/index.rb +26 -0
- data/lib/admin_assistant/request/new.rb +19 -0
- data/lib/admin_assistant/request/show.rb +24 -0
- data/lib/admin_assistant/request/update.rb +44 -0
- data/lib/admin_assistant/search.rb +82 -0
- data/lib/admin_assistant/show_view.rb +20 -0
- data/lib/admin_assistant/virtual_column.rb +61 -0
- data/lib/admin_assistant.rb +190 -85
- data/lib/javascripts/admin_assistant.js +253 -0
- data/lib/stylesheets/activescaffold.css +219 -0
- data/lib/stylesheets/default.css +119 -0
- data/lib/views/_polymorphic_field_search.html.erb +89 -0
- data/lib/views/_restricted_autocompleter.html.erb +53 -0
- data/lib/views/autocomplete.html.erb +11 -0
- data/lib/views/form.html.erb +6 -3
- data/lib/views/index.html.erb +53 -46
- data/lib/views/show.html.erb +19 -0
- data/vendor/ar_query/MIT-LICENSE +20 -0
- data/vendor/ar_query/README +0 -0
- data/vendor/ar_query/init.rb +1 -0
- data/vendor/ar_query/install.rb +1 -0
- data/vendor/ar_query/lib/ar_query.rb +137 -0
- data/vendor/ar_query/spec/ar_query_spec.rb +253 -0
- data/vendor/ar_query/tasks/ar_query_tasks.rake +0 -0
- data/vendor/ar_query/uninstall.rb +1 -0
- metadata +39 -16
- data/lib/admin_assistant/request.rb +0 -183
- data/lib/stylesheets/admin_assistant.css +0 -75
@@ -0,0 +1,176 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
module Request
|
3
|
+
class Base
|
4
|
+
def initialize(admin_assistant, controller)
|
5
|
+
@admin_assistant, @controller = admin_assistant, controller
|
6
|
+
end
|
7
|
+
|
8
|
+
def action
|
9
|
+
@controller.action_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def model_class
|
13
|
+
@admin_assistant.model_class
|
14
|
+
end
|
15
|
+
|
16
|
+
def model_class_symbol
|
17
|
+
model_class.name.underscore.to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
def params_for_save
|
21
|
+
ParamsForSave.new(@controller, @record, model_class_symbol)
|
22
|
+
end
|
23
|
+
|
24
|
+
def redirect_after_save
|
25
|
+
url_params = if @controller.respond_to?(:destination_after_save)
|
26
|
+
@controller.send(
|
27
|
+
:destination_after_save, @record, @controller.params
|
28
|
+
)
|
29
|
+
end
|
30
|
+
url_params ||= {:action => 'index'}
|
31
|
+
@controller.send :redirect_to, url_params
|
32
|
+
end
|
33
|
+
|
34
|
+
def after_template_file(template_name)
|
35
|
+
File.join(
|
36
|
+
RAILS_ROOT, 'app/views/', @controller.controller_path,
|
37
|
+
"_after_#{template_name}.html.erb"
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def before_template_file(template_name)
|
42
|
+
File.join(
|
43
|
+
RAILS_ROOT, 'app/views/', @controller.controller_path,
|
44
|
+
"_before_#{template_name}.html.erb"
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def render_template_file(template_name = action, opts_plus = {})
|
49
|
+
html = ''
|
50
|
+
html << render_to_string_if_exists(
|
51
|
+
before_template_file(template_name), opts_plus
|
52
|
+
)
|
53
|
+
html << render_to_string(
|
54
|
+
AdminAssistant.template_file(template_name), opts_plus
|
55
|
+
)
|
56
|
+
html << render_to_string_if_exists(
|
57
|
+
after_template_file(template_name), opts_plus
|
58
|
+
)
|
59
|
+
render_as_text_opts = {:text => html, :layout => true}.merge(opts_plus)
|
60
|
+
@controller.send :render, render_as_text_opts
|
61
|
+
end
|
62
|
+
|
63
|
+
def render_to_string(template_file, options_plus)
|
64
|
+
after_template_opts = {
|
65
|
+
:file => template_file, :layout => false
|
66
|
+
}.merge options_plus
|
67
|
+
@controller.send :render_to_string, after_template_opts
|
68
|
+
end
|
69
|
+
|
70
|
+
def render_to_string_if_exists(template_file, opts_plus)
|
71
|
+
if File.exist?(template_file)
|
72
|
+
render_to_string(template_file, opts_plus)
|
73
|
+
else
|
74
|
+
''
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def save
|
79
|
+
if @controller.respond_to?(:before_save)
|
80
|
+
@controller.send(:before_save, @record)
|
81
|
+
end
|
82
|
+
result = @record.save
|
83
|
+
if result && @controller.respond_to?(:after_save)
|
84
|
+
@controller.send(:after_save, @record)
|
85
|
+
end
|
86
|
+
result
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class ParamsForSave < Hash
|
91
|
+
def initialize(controller, record, model_class_symbol)
|
92
|
+
super()
|
93
|
+
@controller, @record, @model_class_symbol =
|
94
|
+
controller, record, model_class_symbol
|
95
|
+
build_from_split_params
|
96
|
+
destroy_params.each do |k,v|
|
97
|
+
if whole_params[k].blank?
|
98
|
+
self[k] = nil
|
99
|
+
mname = "destroy_#{k}_in_attributes"
|
100
|
+
if controller.respond_to?(mname)
|
101
|
+
controller.send(mname, self)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
build_from_whole_params
|
106
|
+
end
|
107
|
+
|
108
|
+
def build_from_split_params
|
109
|
+
bases = split_params.map { |k, v| k.gsub(/\([0-9]+i\)$/, '') }.uniq
|
110
|
+
bases.each do |b|
|
111
|
+
h = {}
|
112
|
+
split_params.each { |k, v|
|
113
|
+
h[k] = split_params.delete(k) if k =~ /#{b}\([0-9]+i\)$/
|
114
|
+
}
|
115
|
+
from_form_method = "#{b}_from_form".to_sym
|
116
|
+
if @controller.respond_to?(from_form_method)
|
117
|
+
self[b] = @controller.send(from_form_method, h)
|
118
|
+
elsif @record.respond_to?("#{b}=")
|
119
|
+
self.merge! h
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def build_from_whole_params
|
125
|
+
whole_params.each do |k, v|
|
126
|
+
from_form_method = "#{k}_from_form".to_sym
|
127
|
+
if @controller.respond_to?(from_form_method)
|
128
|
+
self[k] = @controller.send(from_form_method, v)
|
129
|
+
elsif @record.respond_to?("#{k}=")
|
130
|
+
unless destroy_params[k] && v.blank?
|
131
|
+
column = @record.class.columns.detect { |c| c.name == k }
|
132
|
+
if column && column.type == :boolean
|
133
|
+
if v == '1'
|
134
|
+
v = true
|
135
|
+
elsif v == '0'
|
136
|
+
v = false
|
137
|
+
else
|
138
|
+
v = nil
|
139
|
+
end
|
140
|
+
end
|
141
|
+
self[k] = v
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def destroy_params
|
148
|
+
dp = {}
|
149
|
+
@controller.params[@model_class_symbol].each do |k,v|
|
150
|
+
if k =~ %r|(.*)\(destroy\)|
|
151
|
+
dp[$1] = v
|
152
|
+
end
|
153
|
+
end
|
154
|
+
dp
|
155
|
+
end
|
156
|
+
|
157
|
+
def split_params
|
158
|
+
sp = {}
|
159
|
+
@controller.params[@model_class_symbol].each do |k,v|
|
160
|
+
sp[k] = v if k =~ /\([0-9]+i\)$/
|
161
|
+
end
|
162
|
+
sp
|
163
|
+
end
|
164
|
+
|
165
|
+
def whole_params
|
166
|
+
wp = {}
|
167
|
+
@controller.params[@model_class_symbol].each do |k,v|
|
168
|
+
unless k =~ /\([0-9]+i\)$/ || k =~ %r|(.*)\(destroy\)|
|
169
|
+
wp[k] = v
|
170
|
+
end
|
171
|
+
end
|
172
|
+
wp
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
module Request
|
3
|
+
class Create < Base
|
4
|
+
def call
|
5
|
+
@record = model_class.new
|
6
|
+
@record.attributes = params_for_save
|
7
|
+
if save
|
8
|
+
redirect_after_save
|
9
|
+
else
|
10
|
+
@controller.instance_variable_set :@record, @record
|
11
|
+
render_template_file 'form'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def save
|
16
|
+
if @controller.respond_to?(:before_create)
|
17
|
+
@controller.send(:before_create, @record)
|
18
|
+
end
|
19
|
+
result = super
|
20
|
+
if @controller.respond_to?(:after_create)
|
21
|
+
@controller.send(:after_create, @record)
|
22
|
+
end
|
23
|
+
result
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
module Request
|
3
|
+
class Destroy < Base
|
4
|
+
def call
|
5
|
+
@record = model_class.find @controller.params[:id]
|
6
|
+
if @admin_assistant.custom_destroy
|
7
|
+
@admin_assistant.custom_destroy.call @record
|
8
|
+
else
|
9
|
+
@record.destroy
|
10
|
+
end
|
11
|
+
@controller.send :render, :text => ''
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
module Request
|
3
|
+
class Index < Base
|
4
|
+
def call
|
5
|
+
controller_methods = {}
|
6
|
+
possible_methods = [
|
7
|
+
:conditions_for_index, :extra_right_column_links_for_index
|
8
|
+
]
|
9
|
+
possible_methods.each do |mname|
|
10
|
+
if @controller.respond_to?(mname)
|
11
|
+
controller_methods[mname] = @controller.method mname
|
12
|
+
end
|
13
|
+
end
|
14
|
+
index = AdminAssistant::Index.new(
|
15
|
+
@admin_assistant, @controller.params, controller_methods
|
16
|
+
)
|
17
|
+
@controller.instance_variable_set :@index, index
|
18
|
+
render_template_file
|
19
|
+
end
|
20
|
+
|
21
|
+
def columns
|
22
|
+
@admin_assistant.index_settings.columns
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
module Request
|
3
|
+
class New < Base
|
4
|
+
def call
|
5
|
+
@record = model_class.new
|
6
|
+
@admin_assistant.form_settings.columns_for_new.each do |column|
|
7
|
+
if block = @admin_assistant.form_settings[column].default
|
8
|
+
@record.send("#{column}=", block.call(@controller))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
if @controller.params[model_class_symbol]
|
12
|
+
@record.attributes = params_for_save
|
13
|
+
end
|
14
|
+
@controller.instance_variable_set :@record, @record
|
15
|
+
render_template_file 'form'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
module Request
|
3
|
+
class Show < Base
|
4
|
+
def call
|
5
|
+
@record = model_class.find @controller.params[:id]
|
6
|
+
@controller.instance_variable_set :@record, @record
|
7
|
+
@controller.send(
|
8
|
+
:render,
|
9
|
+
:file => AdminAssistant.template_file('show'), :layout => true,
|
10
|
+
:locals => {:request => self}
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def model_class_name(record)
|
15
|
+
if block = @admin_assistant.show_settings.model_class_name_block
|
16
|
+
block.call record
|
17
|
+
else
|
18
|
+
@admin_assistant.model_class_name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
module Request
|
3
|
+
class Update < Base
|
4
|
+
def call
|
5
|
+
@record = model_class.find @controller.params[:id]
|
6
|
+
@record.attributes = params_for_save
|
7
|
+
if save
|
8
|
+
if @controller.params[:from]
|
9
|
+
render_response_to_ajax_toggle
|
10
|
+
else
|
11
|
+
redirect_after_save
|
12
|
+
end
|
13
|
+
else
|
14
|
+
@controller.instance_variable_set :@record, @record
|
15
|
+
render_template_file 'form'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_response_to_ajax_toggle
|
20
|
+
@controller.params[:from] =~ /#{model_class.name.underscore}_\d+_(.*)/
|
21
|
+
field_name = $1
|
22
|
+
index = AdminAssistant::Index.new @admin_assistant
|
23
|
+
erb = <<-ERB
|
24
|
+
<%= index.view(self).columns.detect { |c| c.name == field_name }.
|
25
|
+
ajax_toggle_inner_html(record) %>
|
26
|
+
ERB
|
27
|
+
@controller.send(
|
28
|
+
:render,
|
29
|
+
:inline => erb,
|
30
|
+
:locals => {
|
31
|
+
:index => index, :field_name => field_name, :record => @record
|
32
|
+
}
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def save
|
37
|
+
if @controller.respond_to?(:before_update)
|
38
|
+
@controller.send(:before_update, @record)
|
39
|
+
end
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
class Search
|
3
|
+
attr_reader :params
|
4
|
+
|
5
|
+
def initialize(admin_assistant, params)
|
6
|
+
@admin_assistant, @params = admin_assistant, params
|
7
|
+
@params ||= {}
|
8
|
+
@attributes = HashWithIndifferentAccess.new
|
9
|
+
columns.each do |c|
|
10
|
+
c.verify_for_search
|
11
|
+
c.attributes_for_search_object(@params).each do |key, value|
|
12
|
+
@attributes[key] = value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](name)
|
18
|
+
@params[name]
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_to_query(ar_query)
|
22
|
+
unless @params.empty?
|
23
|
+
ar_query.add_condition do |cond|
|
24
|
+
if match_any_conditions?
|
25
|
+
cond.boolean_join = :or
|
26
|
+
end
|
27
|
+
columns.each do |column|
|
28
|
+
column.add_to_query_condition cond, self
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def columns
|
35
|
+
column_names = settings.column_names
|
36
|
+
if column_names.empty?
|
37
|
+
[DefaultSearchColumn.new(
|
38
|
+
@admin_assistant.model_class,
|
39
|
+
:fields_to_include => settings.default_search_includes
|
40
|
+
)]
|
41
|
+
else
|
42
|
+
column_names.map { |column_name|
|
43
|
+
@admin_assistant.column(column_name.to_s)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def column_views(action_view)
|
49
|
+
columns.map { |c|
|
50
|
+
c.search_view action_view, @admin_assistant, :search => self
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def id
|
55
|
+
@attributes[:id] if @attributes.has_key?(:id)
|
56
|
+
end
|
57
|
+
|
58
|
+
def match_all_conditions?
|
59
|
+
!match_any_conditions?
|
60
|
+
end
|
61
|
+
|
62
|
+
def match_any_conditions?
|
63
|
+
@params["(all_or_any)"] == 'any'
|
64
|
+
end
|
65
|
+
|
66
|
+
def method_missing(meth, *args)
|
67
|
+
if @attributes.has_key?(meth)
|
68
|
+
@attributes[meth]
|
69
|
+
else
|
70
|
+
super
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def model_class
|
75
|
+
@admin_assistant.model_class
|
76
|
+
end
|
77
|
+
|
78
|
+
def settings
|
79
|
+
@admin_assistant.search_settings
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
class ShowView
|
3
|
+
def initialize(record, admin_assistant, action_view)
|
4
|
+
@record, @admin_assistant, @action_view =
|
5
|
+
record, admin_assistant, action_view
|
6
|
+
end
|
7
|
+
|
8
|
+
def column_html(column)
|
9
|
+
column.html @record
|
10
|
+
end
|
11
|
+
|
12
|
+
def columns
|
13
|
+
column_names = @admin_assistant.show_settings.column_names ||
|
14
|
+
@admin_assistant.model_class.columns.map(&:name)
|
15
|
+
@admin_assistant.accumulate_columns(column_names).map { |c|
|
16
|
+
c.show_view @action_view, @admin_assistant
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
class VirtualColumn < Column
|
3
|
+
attr_reader :model_class, :name
|
4
|
+
|
5
|
+
def initialize(name, model_class, admin_assistant)
|
6
|
+
@name, @model_class = name.to_s, model_class
|
7
|
+
@search_settings = admin_assistant.search_settings[name]
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_to_query_condition(ar_query_condition, search)
|
11
|
+
if conditions = @search_settings.conditions.call(search.send(@name))
|
12
|
+
ar_query_condition.sqls << conditions
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def attributes_for_search_object(search_params)
|
17
|
+
value = if search_params[@name.to_s] == 'true'
|
18
|
+
true
|
19
|
+
elsif search_params[@name.to_s] == 'false'
|
20
|
+
false
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
{@name => value}
|
25
|
+
end
|
26
|
+
|
27
|
+
def contains?(column_name)
|
28
|
+
column_name.to_s == @name
|
29
|
+
end
|
30
|
+
|
31
|
+
def field_type
|
32
|
+
@search_settings.field_type
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify_for_search
|
36
|
+
unless @search_settings.conditions
|
37
|
+
raise "Virtual search column #{@name.to_sym.inspect} needs a conditions block"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class FormView < AdminAssistant::Column::View
|
42
|
+
include AdminAssistant::Column::FormViewMethods
|
43
|
+
|
44
|
+
def default_html(form)
|
45
|
+
input_name = "#{@column.model_class.name.underscore}[#{name}]"
|
46
|
+
if @input
|
47
|
+
if @input == :check_box
|
48
|
+
fv = value form.object
|
49
|
+
check_box_and_hidden_tags(input_name, fv)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
@action_view.send(:text_field_tag, input_name, string(form.object))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class SearchView < AdminAssistant::Column::View
|
58
|
+
include AdminAssistant::Column::SimpleColumnSearchViewMethods
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|