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.
Files changed (49) hide show
  1. data/README +3 -28
  2. data/Rakefile +18 -10
  3. data/init.rb +1 -0
  4. data/install.rb +5 -1
  5. data/lib/admin_assistant/active_record_column.rb +211 -0
  6. data/lib/admin_assistant/association_target.rb +35 -0
  7. data/lib/admin_assistant/belongs_to_column.rb +186 -0
  8. data/lib/admin_assistant/builder.rb +222 -35
  9. data/lib/admin_assistant/column.rb +266 -297
  10. data/lib/admin_assistant/default_search_column.rb +41 -0
  11. data/lib/admin_assistant/file_column_column.rb +73 -0
  12. data/lib/admin_assistant/form_view.rb +7 -68
  13. data/lib/admin_assistant/helper.rb +4 -2
  14. data/lib/admin_assistant/index.rb +101 -81
  15. data/lib/admin_assistant/paperclip_column.rb +45 -0
  16. data/lib/admin_assistant/polymorphic_belongs_to_column.rb +102 -0
  17. data/lib/admin_assistant/request/autocomplete.rb +47 -0
  18. data/lib/admin_assistant/request/base.rb +176 -0
  19. data/lib/admin_assistant/request/create.rb +27 -0
  20. data/lib/admin_assistant/request/destroy.rb +15 -0
  21. data/lib/admin_assistant/request/edit.rb +11 -0
  22. data/lib/admin_assistant/request/index.rb +26 -0
  23. data/lib/admin_assistant/request/new.rb +19 -0
  24. data/lib/admin_assistant/request/show.rb +24 -0
  25. data/lib/admin_assistant/request/update.rb +44 -0
  26. data/lib/admin_assistant/search.rb +82 -0
  27. data/lib/admin_assistant/show_view.rb +20 -0
  28. data/lib/admin_assistant/virtual_column.rb +61 -0
  29. data/lib/admin_assistant.rb +190 -85
  30. data/lib/javascripts/admin_assistant.js +253 -0
  31. data/lib/stylesheets/activescaffold.css +219 -0
  32. data/lib/stylesheets/default.css +119 -0
  33. data/lib/views/_polymorphic_field_search.html.erb +89 -0
  34. data/lib/views/_restricted_autocompleter.html.erb +53 -0
  35. data/lib/views/autocomplete.html.erb +11 -0
  36. data/lib/views/form.html.erb +6 -3
  37. data/lib/views/index.html.erb +53 -46
  38. data/lib/views/show.html.erb +19 -0
  39. data/vendor/ar_query/MIT-LICENSE +20 -0
  40. data/vendor/ar_query/README +0 -0
  41. data/vendor/ar_query/init.rb +1 -0
  42. data/vendor/ar_query/install.rb +1 -0
  43. data/vendor/ar_query/lib/ar_query.rb +137 -0
  44. data/vendor/ar_query/spec/ar_query_spec.rb +253 -0
  45. data/vendor/ar_query/tasks/ar_query_tasks.rake +0 -0
  46. data/vendor/ar_query/uninstall.rb +1 -0
  47. metadata +39 -16
  48. data/lib/admin_assistant/request.rb +0 -183
  49. 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,11 @@
1
+ class AdminAssistant
2
+ module Request
3
+ class Edit < Base
4
+ def call
5
+ @record = model_class.find @controller.params[:id]
6
+ @controller.instance_variable_set :@record, @record
7
+ render_template_file 'form'
8
+ end
9
+ end
10
+ end
11
+ 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