admin_assistant 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|