admin_assistant 2.0.0.pre1 → 2.0.0.pre2
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/Rakefile +7 -5
- data/VERSION +1 -1
- data/admin_assistant.gemspec +11 -7
- data/config/routes.rb +16 -0
- data/lib/admin_assistant/belongs_to_column.rb +1 -1
- data/lib/admin_assistant/column.rb +9 -18
- data/lib/admin_assistant/date_time_range_end_point_selector.rb +3 -2
- data/lib/admin_assistant/form_view.rb +18 -9
- data/lib/admin_assistant/index.rb +4 -7
- data/lib/admin_assistant/init.rb +14 -0
- data/lib/admin_assistant/model.rb +72 -0
- data/lib/admin_assistant/request/base.rb +2 -2
- data/lib/admin_assistant/route.rb +50 -0
- data/lib/admin_assistant/virtual_column.rb +3 -3
- data/lib/admin_assistant.rb +23 -101
- data/lib/stylesheets/default.css +1 -1
- data/lib/views/_polymorphic_field_search.html.erb +3 -3
- data/lib/views/_token_input.html.erb +1 -1
- data/lib/views/form.html.erb +2 -2
- data/lib/views/index.html.erb +11 -9
- data/lib/views/multi_form.html.erb +2 -2
- metadata +24 -7
- data/init.rb +0 -1
- data/install.rb +0 -21
- data/lib/admin_assistant/file_column_column.rb +0 -73
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ require 'rake/rdoctask'
|
|
5
5
|
require 'spec/rake/spectask'
|
6
6
|
|
7
7
|
desc 'Default: run all specs across all supported Rails gem versions.'
|
8
|
-
task :default => :
|
8
|
+
task :default => :test
|
9
9
|
|
10
10
|
# run with rake publish
|
11
11
|
Grancher::Task.new do |g|
|
@@ -25,8 +25,8 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
25
25
|
end
|
26
26
|
|
27
27
|
desc 'Run all specs across all supported Rails gem versions.'
|
28
|
-
task :
|
29
|
-
supported_versions = %w(
|
28
|
+
task :test do
|
29
|
+
supported_versions = %w(3.0.6)
|
30
30
|
locally_installed_versions =
|
31
31
|
`gem list --local rails`.split(/\n/).
|
32
32
|
detect { |l| l=~ /^rails / }.strip.
|
@@ -35,7 +35,7 @@ task :spec do
|
|
35
35
|
if !missing.empty?
|
36
36
|
puts "Missing Rails versions #{missing.join(',')}; please install and then re-run tests"
|
37
37
|
else
|
38
|
-
cmd = "cd
|
38
|
+
cmd = "cd rails_3_test && " + (
|
39
39
|
supported_versions.map { |version|
|
40
40
|
"echo '===== Testing #{version} =====' && RAILS_GEM_VERSION=#{version} rake"
|
41
41
|
}.join(" && ")
|
@@ -54,8 +54,10 @@ begin
|
|
54
54
|
gem.email = "sera@fhwang.net"
|
55
55
|
gem.homepage = "http://github.com/fhwang/admin_assistant"
|
56
56
|
gem.authors = ["Francis Hwang"]
|
57
|
-
gem.add_dependency "will_paginate"
|
57
|
+
gem.add_dependency "will_paginate", "~> 3.0.pre2"
|
58
|
+
gem.add_dependency "dynamic_form"
|
58
59
|
gem.files.exclude "rails_2_test"
|
60
|
+
gem.files.exclude "rails_3_test"
|
59
61
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
60
62
|
end
|
61
63
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.0.
|
1
|
+
2.0.0.pre2
|
data/admin_assistant.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{admin_assistant}
|
8
|
-
s.version = "2.0.0.
|
8
|
+
s.version = "2.0.0.pre2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Francis Hwang"]
|
@@ -21,9 +21,8 @@ Gem::Specification.new do |s|
|
|
21
21
|
"Rakefile",
|
22
22
|
"VERSION",
|
23
23
|
"admin_assistant.gemspec",
|
24
|
+
"config/routes.rb",
|
24
25
|
"doc/img/blog_posts-index.png",
|
25
|
-
"init.rb",
|
26
|
-
"install.rb",
|
27
26
|
"lib/admin_assistant.rb",
|
28
27
|
"lib/admin_assistant/active_record_column.rb",
|
29
28
|
"lib/admin_assistant/association_target.rb",
|
@@ -32,11 +31,12 @@ Gem::Specification.new do |s|
|
|
32
31
|
"lib/admin_assistant/column.rb",
|
33
32
|
"lib/admin_assistant/date_time_range_end_point_selector.rb",
|
34
33
|
"lib/admin_assistant/default_search_column.rb",
|
35
|
-
"lib/admin_assistant/file_column_column.rb",
|
36
34
|
"lib/admin_assistant/form_view.rb",
|
37
35
|
"lib/admin_assistant/has_many_column.rb",
|
38
36
|
"lib/admin_assistant/helper.rb",
|
39
37
|
"lib/admin_assistant/index.rb",
|
38
|
+
"lib/admin_assistant/init.rb",
|
39
|
+
"lib/admin_assistant/model.rb",
|
40
40
|
"lib/admin_assistant/paperclip_column.rb",
|
41
41
|
"lib/admin_assistant/polymorphic_belongs_to_column.rb",
|
42
42
|
"lib/admin_assistant/request/autocomplete.rb",
|
@@ -48,6 +48,7 @@ Gem::Specification.new do |s|
|
|
48
48
|
"lib/admin_assistant/request/new.rb",
|
49
49
|
"lib/admin_assistant/request/show.rb",
|
50
50
|
"lib/admin_assistant/request/update.rb",
|
51
|
+
"lib/admin_assistant/route.rb",
|
51
52
|
"lib/admin_assistant/search.rb",
|
52
53
|
"lib/admin_assistant/show_view.rb",
|
53
54
|
"lib/admin_assistant/virtual_column.rb",
|
@@ -144,12 +145,15 @@ Gem::Specification.new do |s|
|
|
144
145
|
s.specification_version = 3
|
145
146
|
|
146
147
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
147
|
-
s.add_runtime_dependency(%q<will_paginate>, ["
|
148
|
+
s.add_runtime_dependency(%q<will_paginate>, ["~> 3.0.pre2"])
|
149
|
+
s.add_runtime_dependency(%q<dynamic_form>, [">= 0"])
|
148
150
|
else
|
149
|
-
s.add_dependency(%q<will_paginate>, ["
|
151
|
+
s.add_dependency(%q<will_paginate>, ["~> 3.0.pre2"])
|
152
|
+
s.add_dependency(%q<dynamic_form>, [">= 0"])
|
150
153
|
end
|
151
154
|
else
|
152
|
-
s.add_dependency(%q<will_paginate>, ["
|
155
|
+
s.add_dependency(%q<will_paginate>, ["~> 3.0.pre2"])
|
156
|
+
s.add_dependency(%q<dynamic_form>, [">= 0"])
|
153
157
|
end
|
154
158
|
end
|
155
159
|
|
data/config/routes.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# In development mode, we need to ensure that all controllers are loaded,
|
2
|
+
# because that's how AdminAssistant knows what routes to create
|
3
|
+
unless Rails.configuration.cache_classes
|
4
|
+
Find.find("#{Rails.root}/app/controllers") do |path|
|
5
|
+
if path =~ /\.rb$/
|
6
|
+
require path
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Rails.application.routes.draw do
|
12
|
+
AdminAssistant.routes.each do |route|
|
13
|
+
route.add(binding)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
@@ -37,7 +37,9 @@ class AdminAssistant
|
|
37
37
|
else
|
38
38
|
helper_method = "after_#{name}_input"
|
39
39
|
if @action_view.respond_to?(helper_method)
|
40
|
-
@action_view.
|
40
|
+
@action_view.raw(
|
41
|
+
@action_view.send(helper_method, rails_form.object)
|
42
|
+
)
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
@@ -47,7 +49,7 @@ class AdminAssistant
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def errors(record)
|
50
|
-
record.errors
|
52
|
+
record.errors[name]
|
51
53
|
end
|
52
54
|
|
53
55
|
def html(rails_form)
|
@@ -218,7 +220,7 @@ class AdminAssistant
|
|
218
220
|
opt << ">#{text}</option>"
|
219
221
|
}.join("\n")
|
220
222
|
@action_view.select_tag(
|
221
|
-
"search[#{name}(comparator)]", option_tags
|
223
|
+
"search[#{name}(comparator)]", @action_view.raw(option_tags)
|
222
224
|
)
|
223
225
|
end
|
224
226
|
|
@@ -338,15 +340,8 @@ class AdminAssistant
|
|
338
340
|
end
|
339
341
|
|
340
342
|
def check_box_and_hidden_tags(input_name, value)
|
341
|
-
|
342
|
-
|
343
|
-
if RAILS_GEM_VERSION =~ /^2.3/
|
344
|
-
@action_view.send(:hidden_field_tag, input_name, '0', :id => "#{input_name}_hidden") +
|
345
|
-
@action_view.send(:check_box_tag, input_name, '1', value)
|
346
|
-
else
|
347
|
-
@action_view.send(:check_box_tag, input_name, '1', value) +
|
348
|
-
@action_view.send(:hidden_field_tag, input_name, '0', :id => "#{input_name}_hidden")
|
349
|
-
end
|
343
|
+
@action_view.send(:hidden_field_tag, input_name, '0', :id => "#{input_name}_hidden") +
|
344
|
+
@action_view.send(:check_box_tag, input_name, '1', value)
|
350
345
|
end
|
351
346
|
|
352
347
|
def controller
|
@@ -355,17 +350,13 @@ class AdminAssistant
|
|
355
350
|
|
356
351
|
def custom_template_file_path(slug)
|
357
352
|
File.join(
|
358
|
-
|
353
|
+
Rails.root, 'app/views', controller.controller_path,
|
359
354
|
"#{slug}.html.erb"
|
360
355
|
)
|
361
356
|
end
|
362
357
|
|
363
358
|
def file_option_for_custom_template_render(slug)
|
364
|
-
|
365
|
-
File.join(controller.controller_path, "#{slug}.html.erb")
|
366
|
-
else
|
367
|
-
custom_template_file_path slug
|
368
|
-
end
|
359
|
+
custom_template_file_path slug
|
369
360
|
end
|
370
361
|
|
371
362
|
def label
|
@@ -2,8 +2,9 @@ class AdminAssistant
|
|
2
2
|
# Copied (and then streamlined) from Rails 2.3.5 in an effort to provide
|
3
3
|
# consistent functionality all the way back to Rails 2.1.0
|
4
4
|
class DateTimeRangeEndPointSelector
|
5
|
+
include ActionView::Helpers::RawOutputHelper
|
5
6
|
include ActionView::Helpers::TagHelper
|
6
|
-
|
7
|
+
|
7
8
|
DEFAULT_PREFIX = 'date'.freeze unless const_defined?('DEFAULT_PREFIX')
|
8
9
|
POSITION = {
|
9
10
|
:year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6
|
@@ -259,7 +260,7 @@ class AdminAssistant
|
|
259
260
|
select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt]
|
260
261
|
select_html << select_options_as_html.to_s
|
261
262
|
|
262
|
-
content_tag(:select, select_html, select_options) + "\n"
|
263
|
+
content_tag(:select, raw(select_html), select_options) + "\n"
|
263
264
|
end
|
264
265
|
|
265
266
|
# Builds a prompt option tag with supplied options or from default options
|
@@ -43,8 +43,7 @@ class AdminAssistant
|
|
43
43
|
|
44
44
|
def form_for_args
|
45
45
|
args = {:url => {:action => action, :id => @record.id}}
|
46
|
-
|
47
|
-
@admin_assistant.file_columns.empty?
|
46
|
+
if !@admin_assistant.paperclip_attachments.empty?
|
48
47
|
args[:html] = {:multipart => true}
|
49
48
|
end
|
50
49
|
args
|
@@ -87,14 +86,13 @@ class AdminAssistant
|
|
87
86
|
end
|
88
87
|
|
89
88
|
def form_for_args
|
89
|
+
opts = {
|
90
|
+
:builder => AdminAssistant::MultiFormView::Builder,
|
91
|
+
:sub_form_views => @sub_form_views, :url => {:action => action}
|
92
|
+
}
|
90
93
|
[
|
91
|
-
@records
|
92
|
-
@records
|
93
|
-
{
|
94
|
-
:url => {:action => action},
|
95
|
-
:builder => AdminAssistant::MultiFormView::Builder,
|
96
|
-
:sub_form_views => @sub_form_views
|
97
|
-
}
|
94
|
+
RecordsForForm.new(@records),
|
95
|
+
opts.merge(:as => @records.first.class.name.underscore.to_sym)
|
98
96
|
]
|
99
97
|
end
|
100
98
|
|
@@ -163,5 +161,16 @@ class AdminAssistant
|
|
163
161
|
end
|
164
162
|
end
|
165
163
|
end
|
164
|
+
|
165
|
+
# Passing an array as the object to form_for confuses it, so we hide that
|
166
|
+
# this is an array with a DelegateClass.
|
167
|
+
class RecordsForForm < DelegateClass(Array)
|
168
|
+
def initialize(records)
|
169
|
+
super(records)
|
170
|
+
end
|
171
|
+
|
172
|
+
def id
|
173
|
+
end
|
174
|
+
end
|
166
175
|
end
|
167
176
|
end
|
@@ -193,12 +193,7 @@ class AdminAssistant
|
|
193
193
|
slug = "_after_index_header.html.erb"
|
194
194
|
abs_template_file = File.join( Rails.root, 'app/views', @admin_assistant.controller_class.controller_path, slug )
|
195
195
|
if File.exist?(abs_template_file)
|
196
|
-
|
197
|
-
File.join(@admin_assistant.controller_class.controller_path, slug)
|
198
|
-
else
|
199
|
-
abs_template_file
|
200
|
-
end
|
201
|
-
@action_view.render :file => template
|
196
|
+
@action_view.render :file => abs_template_file
|
202
197
|
end
|
203
198
|
end
|
204
199
|
|
@@ -260,7 +255,9 @@ class AdminAssistant
|
|
260
255
|
else
|
261
256
|
"New #{@admin_assistant.model_class_name}"
|
262
257
|
end
|
263
|
-
@action_view.link_to
|
258
|
+
@action_view.link_to(
|
259
|
+
new_link_name, @admin_assistant.url_params(:new)
|
260
|
+
)
|
264
261
|
end
|
265
262
|
|
266
263
|
def right_column?
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
class AdminAssistant
|
5
|
+
def self.init
|
6
|
+
gem_root = File.dirname(__FILE__) + "/../.."
|
7
|
+
%w(stylesheets javascripts images).each do |asset_type|
|
8
|
+
asset_dir = "#{Rails.root}/public/#{asset_type}/admin_assistant"
|
9
|
+
FileUtils.mkdir(asset_dir) unless File.exist?(asset_dir)
|
10
|
+
FileUtils.cp_r(Dir.glob("#{gem_root}/lib/#{asset_type}/*"), asset_dir)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
class Model
|
3
|
+
def initialize(ar_model)
|
4
|
+
@ar_model = ar_model
|
5
|
+
end
|
6
|
+
|
7
|
+
def accessors
|
8
|
+
@ar_model.instance_methods.
|
9
|
+
select { |m| m =~ /=$/ }.
|
10
|
+
map { |m| m.gsub(/=/, '')}.
|
11
|
+
select { |m| @ar_model.instance_methods.include?(m) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def belongs_to_associations
|
15
|
+
@ar_model.reflect_on_all_associations.select { |assoc|
|
16
|
+
assoc.macro == :belongs_to
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def belongs_to_assoc(association_name)
|
21
|
+
belongs_to_associations.detect { |assoc|
|
22
|
+
assoc.name.to_s == association_name.to_s
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def belongs_to_assoc_by_foreign_key(foreign_key)
|
27
|
+
belongs_to_associations.detect { |assoc|
|
28
|
+
assoc.association_foreign_key == foreign_key
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def belongs_to_assoc_by_polymorphic_type(name)
|
33
|
+
if name =~ /^(.*)_type/
|
34
|
+
belongs_to_associations.detect { |assoc|
|
35
|
+
assoc.options[:polymorphic] && $1 == assoc.name.to_s
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def default_column_names
|
41
|
+
@ar_model.columns.reject { |ar_column|
|
42
|
+
%w(id created_at updated_at).include?(ar_column.name)
|
43
|
+
}.map { |ar_column| ar_column.name }
|
44
|
+
end
|
45
|
+
|
46
|
+
def has_many_assoc(association_name)
|
47
|
+
@ar_model.reflect_on_all_associations.select { |assoc|
|
48
|
+
assoc.macro == :has_many
|
49
|
+
}.detect { |assoc|
|
50
|
+
assoc.name.to_s == association_name.to_s
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def paperclip_attachments
|
55
|
+
pa = []
|
56
|
+
if @ar_model.respond_to?(:attachment_definitions)
|
57
|
+
if @ar_model.attachment_definitions
|
58
|
+
pa = @ar_model.attachment_definitions.map { |name, definition|
|
59
|
+
name
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
pa
|
64
|
+
end
|
65
|
+
|
66
|
+
def searchable_columns
|
67
|
+
@ar_model.columns.select { |column|
|
68
|
+
[:string, :text].include?(column.type)
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -24,14 +24,14 @@ class AdminAssistant
|
|
24
24
|
|
25
25
|
def after_template_file(template_name)
|
26
26
|
File.join(
|
27
|
-
|
27
|
+
Rails.root, 'app/views/', @controller.controller_path,
|
28
28
|
"_after_#{template_name}.html.erb"
|
29
29
|
)
|
30
30
|
end
|
31
31
|
|
32
32
|
def before_template_file(template_name)
|
33
33
|
File.join(
|
34
|
-
|
34
|
+
Rails.root, 'app/views/', @controller.controller_path,
|
35
35
|
"_before_#{template_name}.html.erb"
|
36
36
|
)
|
37
37
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class AdminAssistant
|
2
|
+
class Route
|
3
|
+
attr_reader :admin_assistant
|
4
|
+
|
5
|
+
def initialize(admin_assistant)
|
6
|
+
@admin_assistant = admin_assistant
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(binding)
|
10
|
+
route_str = "resources(:#{resource})"
|
11
|
+
unless autocomplete_actions.empty?
|
12
|
+
route_str << " do "
|
13
|
+
autocomplete_actions.each do |action|
|
14
|
+
route_str << " get :#{action}, :on => :collection;"
|
15
|
+
end
|
16
|
+
route_str << " end "
|
17
|
+
end
|
18
|
+
if namespace
|
19
|
+
route_str = "namespace(:#{namespace}) do " + route_str + " end"
|
20
|
+
end
|
21
|
+
eval(route_str, binding)
|
22
|
+
end
|
23
|
+
|
24
|
+
def autocomplete_actions
|
25
|
+
admin_assistant.autocomplete_actions
|
26
|
+
end
|
27
|
+
|
28
|
+
def controller
|
29
|
+
admin_assistant.controller_class
|
30
|
+
end
|
31
|
+
|
32
|
+
def namespace
|
33
|
+
name = controller.name.gsub(/Controller$/, '').underscore
|
34
|
+
if name =~ %r|(.*)/(.*)|
|
35
|
+
$1.to_sym
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def resource
|
40
|
+
name = controller.name.gsub(/Controller$/, '').underscore
|
41
|
+
if name =~ %r|(.*)/(.*)|
|
42
|
+
$2.to_sym
|
43
|
+
else
|
44
|
+
name.to_sym
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
@@ -51,14 +51,14 @@ class AdminAssistant
|
|
51
51
|
@action_view.send("#{input}_tag", input_name, string(object))
|
52
52
|
end
|
53
53
|
if has_matching_errors?(object)
|
54
|
-
html = "<div class=\"
|
54
|
+
html = "<div class=\"field_with_errors\">#{html}</div>"
|
55
55
|
end
|
56
56
|
html
|
57
57
|
end
|
58
58
|
|
59
59
|
def has_matching_errors?(record)
|
60
|
-
record.respond_to?(:errors) && record.errors.respond_to?(:
|
61
|
-
record.errors
|
60
|
+
record.respond_to?(:errors) && record.errors.respond_to?(:[]) &&
|
61
|
+
record.errors[name]
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
data/lib/admin_assistant.rb
CHANGED
@@ -1,17 +1,24 @@
|
|
1
1
|
$: << File.join(File.dirname(__FILE__), '../vendor/ar_query/lib')
|
2
|
+
require 'dynamic_form'
|
3
|
+
require 'will_paginate'
|
4
|
+
|
2
5
|
require 'find'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
files = %w(
|
7
|
+
column virtual_column active_record_column association_target
|
8
|
+
belongs_to_column builder date_time_range_end_point_selector
|
9
|
+
default_search_column form_view has_many_column helper index init model
|
10
|
+
paperclip_column polymorphic_belongs_to_column request/base
|
11
|
+
request/autocomplete request/create request/destroy request/edit
|
12
|
+
request/index request/new request/show request/update route search show_view
|
13
|
+
)
|
14
|
+
files.each do |file|
|
15
|
+
require "#{File.dirname(__FILE__)}/admin_assistant/#{file}"
|
9
16
|
end
|
10
|
-
require 'will_paginate'
|
11
17
|
|
12
18
|
class AdminAssistant
|
13
|
-
cattr_accessor :request_start_time
|
14
|
-
|
19
|
+
cattr_accessor :request_start_time, :routes
|
20
|
+
self.routes = []
|
21
|
+
|
15
22
|
def self.profile(msg)
|
16
23
|
if self.request_start_time
|
17
24
|
Rails.logger.info "#{msg}: #{Time.now - self.request_start_time}"
|
@@ -81,9 +88,7 @@ class AdminAssistant
|
|
81
88
|
end
|
82
89
|
|
83
90
|
def column(name)
|
84
|
-
if @model.
|
85
|
-
FileColumnColumn.new name
|
86
|
-
elsif @model.paperclip_attachments.include?(name)
|
91
|
+
if @model.paperclip_attachments.include?(name)
|
87
92
|
PaperclipColumn.new name
|
88
93
|
elsif (belongs_to_assoc = @model.belongs_to_assoc(name) or
|
89
94
|
belongs_to_assoc = @model.belongs_to_assoc_by_foreign_key(name))
|
@@ -136,10 +141,6 @@ class AdminAssistant
|
|
136
141
|
@model.default_column_names
|
137
142
|
end
|
138
143
|
|
139
|
-
def file_columns
|
140
|
-
@model.file_columns
|
141
|
-
end
|
142
|
-
|
143
144
|
def method_missing(meth, *args)
|
144
145
|
if crudful_request_methods.include?(meth) and args.size == 1
|
145
146
|
self.class.request_start_time = Time.now if ENV['PROFILE_LOGGING']
|
@@ -200,98 +201,19 @@ class AdminAssistant
|
|
200
201
|
self.class.admin_assistant.send(action, self)
|
201
202
|
end
|
202
203
|
end
|
204
|
+
AdminAssistant.routes << Route.new(self.admin_assistant)
|
203
205
|
rescue ActiveRecord::StatementInvalid
|
204
206
|
Rails.logger.info "Skipping admin_assistant_for for #{self.name} because the table doesn't exist in the DB. Hopefully that's because you're deploying with a migration."
|
205
207
|
end
|
206
208
|
end
|
207
209
|
end
|
208
|
-
|
209
|
-
class
|
210
|
-
|
211
|
-
|
212
|
-
end
|
213
|
-
|
214
|
-
def accessors
|
215
|
-
@ar_model.instance_methods.
|
216
|
-
select { |m| m =~ /=$/ }.
|
217
|
-
map { |m| m.gsub(/=/, '')}.
|
218
|
-
select { |m| @ar_model.instance_methods.include?(m) }
|
219
|
-
end
|
220
|
-
|
221
|
-
def belongs_to_associations
|
222
|
-
@ar_model.reflect_on_all_associations.select { |assoc|
|
223
|
-
assoc.macro == :belongs_to
|
224
|
-
}
|
225
|
-
end
|
226
|
-
|
227
|
-
def belongs_to_assoc(association_name)
|
228
|
-
belongs_to_associations.detect { |assoc|
|
229
|
-
assoc.name.to_s == association_name.to_s
|
230
|
-
}
|
231
|
-
end
|
232
|
-
|
233
|
-
def belongs_to_assoc_by_foreign_key(foreign_key)
|
234
|
-
belongs_to_associations.detect { |assoc|
|
235
|
-
assoc.association_foreign_key == foreign_key
|
236
|
-
}
|
237
|
-
end
|
238
|
-
|
239
|
-
def belongs_to_assoc_by_polymorphic_type(name)
|
240
|
-
if name =~ /^(.*)_type/
|
241
|
-
belongs_to_associations.detect { |assoc|
|
242
|
-
assoc.options[:polymorphic] && $1 == assoc.name.to_s
|
243
|
-
}
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
def default_column_names
|
248
|
-
@ar_model.columns.reject { |ar_column|
|
249
|
-
%w(id created_at updated_at).include?(ar_column.name)
|
250
|
-
}.map { |ar_column| ar_column.name }
|
251
|
-
end
|
252
|
-
|
253
|
-
def file_columns
|
254
|
-
unless @file_columns
|
255
|
-
@file_columns = []
|
256
|
-
if @ar_model.respond_to?(:file_column)
|
257
|
-
names_to_check = @ar_model.columns.map(&:name).concat(accessors).uniq
|
258
|
-
@file_columns = names_to_check.select { |name|
|
259
|
-
%w( relative_path dir relative_dir temp ).all? { |suffix|
|
260
|
-
@ar_model.method_defined? "#{name}_#{suffix}".to_sym
|
261
|
-
}
|
262
|
-
}
|
263
|
-
end
|
264
|
-
end
|
265
|
-
@file_columns
|
266
|
-
end
|
267
|
-
|
268
|
-
def has_many_assoc(association_name)
|
269
|
-
@ar_model.reflect_on_all_associations.select { |assoc|
|
270
|
-
assoc.macro == :has_many
|
271
|
-
}.detect { |assoc|
|
272
|
-
assoc.name.to_s == association_name.to_s
|
273
|
-
}
|
274
|
-
end
|
275
|
-
|
276
|
-
def paperclip_attachments
|
277
|
-
pa = []
|
278
|
-
if @ar_model.respond_to?(:attachment_definitions)
|
279
|
-
if @ar_model.attachment_definitions
|
280
|
-
pa = @ar_model.attachment_definitions.map { |name, definition|
|
281
|
-
name
|
282
|
-
}
|
283
|
-
end
|
284
|
-
end
|
285
|
-
pa
|
286
|
-
end
|
287
|
-
|
288
|
-
def searchable_columns
|
289
|
-
@ar_model.columns.select { |column|
|
290
|
-
[:string, :text].include?(column.type)
|
291
|
-
}
|
210
|
+
|
211
|
+
class Engine < ::Rails::Engine
|
212
|
+
initializer "admin_assistant.init" do
|
213
|
+
AdminAssistant.init
|
292
214
|
end
|
293
215
|
end
|
294
216
|
end
|
295
|
-
|
217
|
+
|
296
218
|
ActionController::Base.send :include, AdminAssistant::ControllerMethods
|
297
219
|
|
data/lib/stylesheets/default.css
CHANGED
@@ -49,12 +49,12 @@ end
|
|
49
49
|
<%
|
50
50
|
option_tags = "<option value=''></option>"
|
51
51
|
option_tags << options_for_select(
|
52
|
-
|
53
|
-
|
52
|
+
association_target.options_for_select,
|
53
|
+
(associated.id if associated.class == polymorphic_type)
|
54
54
|
)
|
55
55
|
%>
|
56
56
|
<%= select_tag(
|
57
|
-
"#{column.name}_#{name}_id", option_tags,
|
57
|
+
"#{column.name}_#{name}_id", raw(option_tags),
|
58
58
|
'data-behavior' => 'select',
|
59
59
|
'data-value-type' => polymorphic_type.name
|
60
60
|
) %>
|
@@ -19,7 +19,7 @@ end
|
|
19
19
|
<script type="text/javascript">
|
20
20
|
$(document).ready(function() {
|
21
21
|
$("#<%= text_field_id %>").tokenInput(
|
22
|
-
"<%= token_url %>", <%= token_input_options.to_json %>
|
22
|
+
"<%= raw(token_url) %>", <%= raw(token_input_options.to_json) %>
|
23
23
|
);
|
24
24
|
});
|
25
25
|
</script>
|
data/lib/views/form.html.erb
CHANGED
@@ -14,7 +14,7 @@ form_view = AdminAssistant::FormView.new(@record, @admin_assistant, self)
|
|
14
14
|
<% if !@record.errors.empty? %>
|
15
15
|
<%= error_messages_for 'record' %>
|
16
16
|
<% end %>
|
17
|
-
|
17
|
+
<%= form_for(@record, form_view.form_for_args) do |rails_form| %>
|
18
18
|
<% if @origin %>
|
19
19
|
<%= hidden_field_tag 'origin', @origin %>
|
20
20
|
<% end %>
|
@@ -25,7 +25,7 @@ form_view = AdminAssistant::FormView.new(@record, @admin_assistant, self)
|
|
25
25
|
<% if column.description %>
|
26
26
|
<p class="description"><%= h(column.description) %></p>
|
27
27
|
<% end %>
|
28
|
-
<%= column.html(rails_form) %>
|
28
|
+
<%= raw(column.html(rails_form)) %>
|
29
29
|
</div>
|
30
30
|
<% end %>
|
31
31
|
<div>
|
data/lib/views/index.html.erb
CHANGED
@@ -18,9 +18,9 @@
|
|
18
18
|
<%= index_view.render_after_index_header %>
|
19
19
|
</div>
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
:url => {:action => 'index'},
|
21
|
+
<%= form_for(
|
22
|
+
@index.search,
|
23
|
+
:as => :search, :url => {:action => 'index'},
|
24
24
|
:html => {:id => 'search_form', :style => 'display:none', :method => 'get'}
|
25
25
|
) do |form| %>
|
26
26
|
<% @index.hidden_fields_for_search_form.each do |name, value| -%>
|
@@ -37,7 +37,7 @@
|
|
37
37
|
) %>
|
38
38
|
<% end %>
|
39
39
|
<% column_views.each do |column_view| %>
|
40
|
-
<%= column_view.html(form) %>
|
40
|
+
<%= raw(column_view.html(form)) %>
|
41
41
|
<% end %>
|
42
42
|
<%= submit_tag('Search') %>
|
43
43
|
<%=
|
@@ -59,7 +59,7 @@
|
|
59
59
|
<tr>
|
60
60
|
<% index_view.columns.each do |column| %>
|
61
61
|
<% th_class = column.header_css_class %>
|
62
|
-
<th<%= " class=\"#{th_class}\"" if th_class %>><%=
|
62
|
+
<th<%= raw(" class=\"#{th_class}\"") if th_class %>><%=
|
63
63
|
if column.sort_possible?(@index.records.total_entries)
|
64
64
|
link_to(h(column.label), column.next_sort_params)
|
65
65
|
else
|
@@ -77,12 +77,14 @@
|
|
77
77
|
%>_<%= record.id %>">
|
78
78
|
<% index_view.columns.each do |column| %>
|
79
79
|
<% td_class = column.td_css_classes(column, record) %>
|
80
|
-
<td<%= " class=\"#{td_class}\"" unless td_class.blank? %>><%=
|
81
|
-
column.html(record)
|
80
|
+
<td<%= raw(" class=\"#{td_class}\"") unless td_class.blank? %>><%=
|
81
|
+
raw(column.html(record))
|
82
82
|
%></td>
|
83
83
|
<% end %>
|
84
84
|
<% if index_view.right_column? %>
|
85
|
-
<td class="actions"
|
85
|
+
<td class="actions">
|
86
|
+
<%= raw(index_view.right_column_links(record)) %>
|
87
|
+
</td>
|
86
88
|
<% end %>
|
87
89
|
</tr>
|
88
90
|
<% end %>
|
@@ -95,7 +97,7 @@
|
|
95
97
|
<%= will_paginate @index.records, :container => false %>
|
96
98
|
</div>
|
97
99
|
<% if @index.records.total_pages > 10 %>
|
98
|
-
|
100
|
+
<%= form_tag({:action => 'index'}, :method => 'get') do %>
|
99
101
|
<%= text_field_tag('page', nil, :size => 2) %>
|
100
102
|
<%= submit_tag('Jump') %>
|
101
103
|
<% end %>
|
@@ -12,7 +12,7 @@ multi_form_view = AdminAssistant::MultiFormView.new(
|
|
12
12
|
<%= link_to('Back to index', :action => 'index') %>
|
13
13
|
</div>
|
14
14
|
</div>
|
15
|
-
|
15
|
+
<%= form_for(*multi_form_view.form_for_args) do |rails_form| %>
|
16
16
|
<% if @origin %>
|
17
17
|
<%= hidden_field_tag 'origin', @origin %>
|
18
18
|
<% end %>
|
@@ -53,7 +53,7 @@ multi_form_view = AdminAssistant::MultiFormView.new(
|
|
53
53
|
<% end %>
|
54
54
|
<tr>
|
55
55
|
<% sub_form_view.columns.each do |column| %>
|
56
|
-
<td<%= " class='
|
56
|
+
<td<%= " class='field_with_errors'" if column.errors(record) %>>
|
57
57
|
<%= column.html(rails_sub_form) %>
|
58
58
|
</td>
|
59
59
|
<% end %>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: admin_assistant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: -
|
4
|
+
hash: -1876988223
|
5
5
|
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
9
|
- 0
|
10
|
-
-
|
11
|
-
version: 2.0.0.
|
10
|
+
- pre2
|
11
|
+
version: 2.0.0.pre2
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Francis Hwang
|
@@ -23,6 +23,22 @@ dependencies:
|
|
23
23
|
name: will_paginate
|
24
24
|
prerelease: false
|
25
25
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: -1876988247
|
31
|
+
segments:
|
32
|
+
- 3
|
33
|
+
- 0
|
34
|
+
- pre2
|
35
|
+
version: 3.0.pre2
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: dynamic_form
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
26
42
|
none: false
|
27
43
|
requirements:
|
28
44
|
- - ">="
|
@@ -32,7 +48,7 @@ dependencies:
|
|
32
48
|
- 0
|
33
49
|
version: "0"
|
34
50
|
type: :runtime
|
35
|
-
version_requirements: *
|
51
|
+
version_requirements: *id002
|
36
52
|
description: admin_assistant is a Rails plugin that automates a lot of features typically needed in admin interfaces.
|
37
53
|
email: sera@fhwang.net
|
38
54
|
executables: []
|
@@ -47,9 +63,8 @@ files:
|
|
47
63
|
- Rakefile
|
48
64
|
- VERSION
|
49
65
|
- admin_assistant.gemspec
|
66
|
+
- config/routes.rb
|
50
67
|
- doc/img/blog_posts-index.png
|
51
|
-
- init.rb
|
52
|
-
- install.rb
|
53
68
|
- lib/admin_assistant.rb
|
54
69
|
- lib/admin_assistant/active_record_column.rb
|
55
70
|
- lib/admin_assistant/association_target.rb
|
@@ -58,11 +73,12 @@ files:
|
|
58
73
|
- lib/admin_assistant/column.rb
|
59
74
|
- lib/admin_assistant/date_time_range_end_point_selector.rb
|
60
75
|
- lib/admin_assistant/default_search_column.rb
|
61
|
-
- lib/admin_assistant/file_column_column.rb
|
62
76
|
- lib/admin_assistant/form_view.rb
|
63
77
|
- lib/admin_assistant/has_many_column.rb
|
64
78
|
- lib/admin_assistant/helper.rb
|
65
79
|
- lib/admin_assistant/index.rb
|
80
|
+
- lib/admin_assistant/init.rb
|
81
|
+
- lib/admin_assistant/model.rb
|
66
82
|
- lib/admin_assistant/paperclip_column.rb
|
67
83
|
- lib/admin_assistant/polymorphic_belongs_to_column.rb
|
68
84
|
- lib/admin_assistant/request/autocomplete.rb
|
@@ -74,6 +90,7 @@ files:
|
|
74
90
|
- lib/admin_assistant/request/new.rb
|
75
91
|
- lib/admin_assistant/request/show.rb
|
76
92
|
- lib/admin_assistant/request/update.rb
|
93
|
+
- lib/admin_assistant/route.rb
|
77
94
|
- lib/admin_assistant/search.rb
|
78
95
|
- lib/admin_assistant/show_view.rb
|
79
96
|
- lib/admin_assistant/virtual_column.rb
|
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/lib/admin_assistant"
|
data/install.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'pathname'
|
3
|
-
|
4
|
-
outer = File.dirname(__FILE__)
|
5
|
-
|
6
|
-
# Delete rails_2_test and various doc directories, unless you're actually
|
7
|
-
# developing admin_assistant itself
|
8
|
-
test_rails_app = Pathname.new("#{outer}/rails_2_test").realpath.to_s
|
9
|
-
unless RAILS_ROOT == test_rails_app
|
10
|
-
%w(doc rails_2_test website).each do |dir|
|
11
|
-
FileUtils.rm_rf "#{outer}/#{dir}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# Copy over static assets
|
16
|
-
%w(stylesheets javascripts images).each do |asset_type|
|
17
|
-
asset_dir = "#{Rails.root}/public/#{asset_type}/admin_assistant"
|
18
|
-
FileUtils.mkdir(asset_dir) unless File.exist?(asset_dir)
|
19
|
-
FileUtils.cp_r(Dir.glob("#{outer}/lib/#{asset_type}/*"), asset_dir)
|
20
|
-
end
|
21
|
-
|
@@ -1,73 +0,0 @@
|
|
1
|
-
class AdminAssistant
|
2
|
-
class FileColumnColumn < Column
|
3
|
-
attr_reader :name
|
4
|
-
|
5
|
-
def initialize(name)
|
6
|
-
@name = name.to_s
|
7
|
-
end
|
8
|
-
|
9
|
-
def contains?(column_name)
|
10
|
-
column_name.to_s == @name
|
11
|
-
end
|
12
|
-
|
13
|
-
class View < AdminAssistant::Column::View
|
14
|
-
def file_exists?(record)
|
15
|
-
if @file_exists_method
|
16
|
-
@file_exists_method.call record
|
17
|
-
else
|
18
|
-
!source_for_image_tag(record).nil?
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def image_html(record)
|
23
|
-
@action_view.image_tag(
|
24
|
-
source_for_image_tag(record), :size => @image_size
|
25
|
-
)
|
26
|
-
end
|
27
|
-
|
28
|
-
def source_for_image_tag(record)
|
29
|
-
if @file_url_method
|
30
|
-
@file_url_method.call record
|
31
|
-
else
|
32
|
-
@action_view.instance_variable_set :@record, record
|
33
|
-
@action_view.url_for_file_column 'record', @column.name
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class FormView < View
|
39
|
-
include AdminAssistant::Column::FormViewMethods
|
40
|
-
|
41
|
-
def default_html(form)
|
42
|
-
if file_exists?(form.object)
|
43
|
-
check_box_tag = @action_view.check_box_tag(
|
44
|
-
"#{form.object.class.name.underscore}[#{name}(destroy)]"
|
45
|
-
)
|
46
|
-
<<-HTML
|
47
|
-
<p>Current image:<br />#{image_html(form.object)}</p>
|
48
|
-
<p>Remove: #{check_box_tag}</p>
|
49
|
-
<p>Update: #{form.file_field(name)}</p>
|
50
|
-
HTML
|
51
|
-
else
|
52
|
-
"<p>Add: #{form.file_field(name)}</p>"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
class IndexView < View
|
58
|
-
include AdminAssistant::Column::IndexViewMethods
|
59
|
-
|
60
|
-
def unconfigured_html(record)
|
61
|
-
image_html(record) if file_exists?(record)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
class ShowView < View
|
66
|
-
include AdminAssistant::Column::ShowViewMethods
|
67
|
-
|
68
|
-
def html(record)
|
69
|
-
image_html(record) if file_exists?(record)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|