merb-admin 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.markdown +58 -0
- data/Rakefile +64 -0
- data/app/controllers/application.rb +6 -0
- data/app/controllers/main.rb +145 -0
- data/app/helpers/application_helper.rb +64 -0
- data/app/helpers/main_helper.rb +122 -0
- data/app/views/layout/_message.html.erb +10 -0
- data/app/views/layout/dashboard.html.erb +34 -0
- data/app/views/layout/form.html.erb +48 -0
- data/app/views/layout/list.html.erb +42 -0
- data/app/views/main/_belongs_to.html.erb +29 -0
- data/app/views/main/_big_decimal.html.erb +12 -0
- data/app/views/main/_boolean.html.erb +7 -0
- data/app/views/main/_date.html.erb +12 -0
- data/app/views/main/_datetime.html.erb +12 -0
- data/app/views/main/_float.html.erb +12 -0
- data/app/views/main/_has_many.html.erb +16 -0
- data/app/views/main/_has_one.html.erb +30 -0
- data/app/views/main/_integer.html.erb +18 -0
- data/app/views/main/_properties.html.erb +18 -0
- data/app/views/main/_string.html.erb +12 -0
- data/app/views/main/_text.html.erb +11 -0
- data/app/views/main/_time.html.erb +12 -0
- data/app/views/main/_timestamp.html.erb +12 -0
- data/app/views/main/delete.html.erb +12 -0
- data/app/views/main/edit.html.erb +25 -0
- data/app/views/main/index.html.erb +22 -0
- data/app/views/main/list.html.erb +72 -0
- data/app/views/main/new.html.erb +22 -0
- data/lib/abstract_model.rb +67 -0
- data/lib/activerecord_support.rb +169 -0
- data/lib/datamapper_support.rb +157 -0
- data/lib/generic_support.rb +17 -0
- data/lib/merb-admin/merbtasks.rb +103 -0
- data/lib/merb-admin/slicetasks.rb +20 -0
- data/lib/merb-admin/spectasks.rb +53 -0
- data/lib/merb-admin.rb +99 -0
- data/public/images/arrow-down.gif +0 -0
- data/public/images/arrow-up.gif +0 -0
- data/public/images/changelist-bg.gif +0 -0
- data/public/images/changelist-bg_rtl.gif +0 -0
- data/public/images/chooser-bg.gif +0 -0
- data/public/images/chooser_stacked-bg.gif +0 -0
- data/public/images/default-bg-reverse.gif +0 -0
- data/public/images/default-bg.gif +0 -0
- data/public/images/deleted-overlay.gif +0 -0
- data/public/images/icon-no.gif +0 -0
- data/public/images/icon-unknown.gif +0 -0
- data/public/images/icon-yes.gif +0 -0
- data/public/images/icon_addlink.gif +0 -0
- data/public/images/icon_alert.gif +0 -0
- data/public/images/icon_calendar.gif +0 -0
- data/public/images/icon_changelink.gif +0 -0
- data/public/images/icon_clock.gif +0 -0
- data/public/images/icon_deletelink.gif +0 -0
- data/public/images/icon_error.gif +0 -0
- data/public/images/icon_searchbox.png +0 -0
- data/public/images/icon_success.gif +0 -0
- data/public/images/inline-delete-8bit.png +0 -0
- data/public/images/inline-delete.png +0 -0
- data/public/images/inline-restore-8bit.png +0 -0
- data/public/images/inline-restore.png +0 -0
- data/public/images/inline-splitter-bg.gif +0 -0
- data/public/images/nav-bg-grabber.gif +0 -0
- data/public/images/nav-bg-reverse.gif +0 -0
- data/public/images/nav-bg.gif +0 -0
- data/public/images/selector-add.gif +0 -0
- data/public/images/selector-addall.gif +0 -0
- data/public/images/selector-remove.gif +0 -0
- data/public/images/selector-removeall.gif +0 -0
- data/public/images/selector-search.gif +0 -0
- data/public/images/selector_stacked-add.gif +0 -0
- data/public/images/selector_stacked-remove.gif +0 -0
- data/public/images/tool-left.gif +0 -0
- data/public/images/tool-left_over.gif +0 -0
- data/public/images/tool-right.gif +0 -0
- data/public/images/tool-right_over.gif +0 -0
- data/public/images/tooltag-add.gif +0 -0
- data/public/images/tooltag-add_over.gif +0 -0
- data/public/images/tooltag-arrowright.gif +0 -0
- data/public/images/tooltag-arrowright_over.gif +0 -0
- data/public/javascripts/CollapsedFieldsets.js +85 -0
- data/public/javascripts/DateTimeShortcuts.js +255 -0
- data/public/javascripts/RelatedObjectLookups.js +96 -0
- data/public/javascripts/SelectBox.js +111 -0
- data/public/javascripts/SelectFilter2.js +113 -0
- data/public/javascripts/actions.js +39 -0
- data/public/javascripts/calendar.js +143 -0
- data/public/javascripts/core.js +176 -0
- data/public/javascripts/dateparse.js +233 -0
- data/public/javascripts/getElementsBySelector.js +167 -0
- data/public/javascripts/i18n.js +33 -0
- data/public/javascripts/master.js +0 -0
- data/public/javascripts/ordering.js +137 -0
- data/public/javascripts/timeparse.js +94 -0
- data/public/javascripts/urlify.js +140 -0
- data/public/stylesheets/base.css +746 -0
- data/public/stylesheets/changelists.css +269 -0
- data/public/stylesheets/dashboard.css +24 -0
- data/public/stylesheets/forms.css +327 -0
- data/public/stylesheets/global.css +142 -0
- data/public/stylesheets/ie.css +51 -0
- data/public/stylesheets/layout.css +29 -0
- data/public/stylesheets/login.css +54 -0
- data/public/stylesheets/master.css +2 -0
- data/public/stylesheets/null.css +1 -0
- data/public/stylesheets/patch-iewin.css +8 -0
- data/public/stylesheets/rtl.css +206 -0
- data/public/stylesheets/widgets.css +506 -0
- data/schema/migrations/001_create_divisions_migration.rb +15 -0
- data/schema/migrations/002_create_drafts_migration.rb +21 -0
- data/schema/migrations/003_create_leagues_migration.rb +13 -0
- data/schema/migrations/004_create_players_migration.rb +23 -0
- data/schema/migrations/005_create_teams_migration.rb +18 -0
- data/spec/controllers/main_spec.rb +25 -0
- data/spec/models/activerecord/division.rb +8 -0
- data/spec/models/activerecord/draft.rb +16 -0
- data/spec/models/activerecord/league.rb +6 -0
- data/spec/models/activerecord/player.rb +10 -0
- data/spec/models/activerecord/team.rb +11 -0
- data/spec/models/datamapper/division.rb +12 -0
- data/spec/models/datamapper/draft.rb +18 -0
- data/spec/models/datamapper/league.rb +11 -0
- data/spec/models/datamapper/player.rb +21 -0
- data/spec/models/datamapper/team.rb +15 -0
- data/spec/requests/main_spec.rb +475 -0
- data/spec/spec_helper.rb +112 -0
- metadata +209 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
module MerbAdmin
|
2
|
+
class AbstractModel
|
3
|
+
module DatamapperSupport
|
4
|
+
def count(options = {})
|
5
|
+
model.count(options)
|
6
|
+
end
|
7
|
+
|
8
|
+
def get(id)
|
9
|
+
model.get(id).extend(InstanceMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
def first(options = {})
|
13
|
+
model.first(options).extend(InstanceMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
def all(options = {})
|
17
|
+
model.all(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def all_in(ids, options = {})
|
21
|
+
options[:id] = ids
|
22
|
+
model.all(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def paginated(options = {})
|
26
|
+
page = options.delete(:page) || 1
|
27
|
+
per_page = options.delete(:per_page) || MerbAdmin[:per_page]
|
28
|
+
|
29
|
+
page_count = (count(options).to_f / per_page).ceil
|
30
|
+
|
31
|
+
options.merge!({
|
32
|
+
:limit => per_page,
|
33
|
+
:offset => (page - 1) * per_page
|
34
|
+
})
|
35
|
+
|
36
|
+
[page_count, all(options)]
|
37
|
+
end
|
38
|
+
|
39
|
+
def create(params = {})
|
40
|
+
model.create(params)
|
41
|
+
end
|
42
|
+
|
43
|
+
def new(params = {})
|
44
|
+
model.new(params).extend(InstanceMethods)
|
45
|
+
end
|
46
|
+
|
47
|
+
def destroy_all!
|
48
|
+
model.all.destroy!
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_many_associations
|
52
|
+
associations.select do |association|
|
53
|
+
association[:type] == :has_many
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def has_one_associations
|
58
|
+
associations.select do |association|
|
59
|
+
association[:type] == :has_one
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def belongs_to_associations
|
64
|
+
associations.select do |association|
|
65
|
+
association[:type] == :belongs_to
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def associations
|
70
|
+
model.relationships.to_a.map do |name, association|
|
71
|
+
{
|
72
|
+
:name => name,
|
73
|
+
:pretty_name => name.to_s.gsub('_', ' ').capitalize,
|
74
|
+
:type => association_type_lookup(association),
|
75
|
+
:parent_model => association.parent_model,
|
76
|
+
:parent_key => association.parent_key.map{|r| r.name},
|
77
|
+
:child_model => association.child_model,
|
78
|
+
:child_key => association.child_key.map{|r| r.name},
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def properties
|
84
|
+
model.properties.map do |property|
|
85
|
+
{
|
86
|
+
:name => property.name,
|
87
|
+
:pretty_name => property.name.to_s.gsub('_', ' ').capitalize,
|
88
|
+
:type => type_lookup(property),
|
89
|
+
:length => property.length,
|
90
|
+
:nullable? => property.nullable?,
|
91
|
+
:serial? => property.serial?,
|
92
|
+
:key? => property.key?,
|
93
|
+
:flag_map => property.type.respond_to?(:flag_map) ? property.type.flag_map : nil,
|
94
|
+
}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def association_type_lookup(association)
|
101
|
+
if self.model == association.parent_model
|
102
|
+
association.options[:max] > 1 ? :has_many : :has_one
|
103
|
+
elsif self.model == association.child_model
|
104
|
+
:belongs_to
|
105
|
+
else
|
106
|
+
raise "Unknown association type"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def type_lookup(property)
|
111
|
+
type = {
|
112
|
+
BigDecimal => :big_decimal,
|
113
|
+
DataMapper::Types::Boolean => :boolean,
|
114
|
+
DataMapper::Types::ParanoidBoolean => :boolean,
|
115
|
+
DataMapper::Types::ParanoidDateTime => :datetime,
|
116
|
+
DataMapper::Types::Serial => :integer,
|
117
|
+
DataMapper::Types::Text => :text,
|
118
|
+
Date => :date,
|
119
|
+
DateTime => :datetime,
|
120
|
+
Fixnum => :integer,
|
121
|
+
Float => :float,
|
122
|
+
Integer => :integer,
|
123
|
+
String => :string,
|
124
|
+
Time => :time,
|
125
|
+
}
|
126
|
+
type[property.type] || type[property.primitive]
|
127
|
+
end
|
128
|
+
|
129
|
+
module InstanceMethods
|
130
|
+
def id
|
131
|
+
super
|
132
|
+
end
|
133
|
+
|
134
|
+
def save
|
135
|
+
super
|
136
|
+
end
|
137
|
+
|
138
|
+
def destroy
|
139
|
+
super
|
140
|
+
end
|
141
|
+
|
142
|
+
def update_attributes(attributes)
|
143
|
+
super
|
144
|
+
end
|
145
|
+
|
146
|
+
def errors
|
147
|
+
super
|
148
|
+
end
|
149
|
+
|
150
|
+
def clear_association(association)
|
151
|
+
association.clear
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module MerbAdmin
|
2
|
+
class AbstractModel
|
3
|
+
module GenericSupport
|
4
|
+
def singular_name
|
5
|
+
model.to_s.snake_case.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def plural_name
|
9
|
+
model.to_s.snake_case.pluralize.to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
def pretty_name
|
13
|
+
model.to_s.snake_case.gsub('_', ' ').capitalize
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
namespace :slices do
|
2
|
+
namespace :"merb-admin" do
|
3
|
+
|
4
|
+
desc "Install MerbAdmin"
|
5
|
+
task :install => [:preflight, :setup_directories, :copy_assets, :migrate]
|
6
|
+
|
7
|
+
desc "Test for any dependencies"
|
8
|
+
task :preflight do # see slicetasks.rb
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Setup directories"
|
12
|
+
task :setup_directories do
|
13
|
+
puts "Creating directories for host application"
|
14
|
+
MerbAdmin.mirrored_components.each do |type|
|
15
|
+
if File.directory?(MerbAdmin.dir_for(type))
|
16
|
+
if !File.directory?(dst_path = MerbAdmin.app_dir_for(type))
|
17
|
+
relative_path = dst_path.relative_path_from(Merb.root)
|
18
|
+
puts "- creating directory :#{type} #{File.basename(Merb.root) / relative_path}"
|
19
|
+
mkdir_p(dst_path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# desc "Copy stub files to host application"
|
26
|
+
# task :stubs do
|
27
|
+
# puts "Copying stubs for MerbAdmin - resolves any collisions"
|
28
|
+
# copied, preserved = MerbAdmin.mirror_stubs!
|
29
|
+
# puts "- no files to copy" if copied.empty? && preserved.empty?
|
30
|
+
# copied.each { |f| puts "- copied #{f}" }
|
31
|
+
# preserved.each { |f| puts "! preserved override as #{f}" }
|
32
|
+
# end
|
33
|
+
|
34
|
+
# desc "Copy stub files and views to host application"
|
35
|
+
# task :patch => [ "stubs", "freeze:views" ]
|
36
|
+
|
37
|
+
desc "Copy public assets to host application"
|
38
|
+
task :copy_assets do
|
39
|
+
puts "Copying assets for MerbAdmin - resolves any collisions"
|
40
|
+
copied, preserved = MerbAdmin.mirror_public!
|
41
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
42
|
+
copied.each { |f| puts "- copied #{f}" }
|
43
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Migrate the database"
|
47
|
+
task :migrate do # see slicetasks.rb
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Freeze MerbAdmin into your app (only merb-admin/app)"
|
51
|
+
task :freeze => [ "freeze:app" ]
|
52
|
+
|
53
|
+
namespace :freeze do
|
54
|
+
|
55
|
+
# desc "Freezes MerbAdmin by installing the gem into application/gems"
|
56
|
+
# task :gem do
|
57
|
+
# ENV["GEM"] ||= "merb-admin"
|
58
|
+
# Rake::Task['slices:install_as_gem'].invoke
|
59
|
+
# end
|
60
|
+
|
61
|
+
desc "Freezes MerbAdmin by copying all files from merb-admin/app to your application"
|
62
|
+
task :app do
|
63
|
+
puts "Copying all merb-admin/app files to your application - resolves any collisions"
|
64
|
+
copied, preserved = MerbAdmin.mirror_app!
|
65
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
66
|
+
copied.each { |f| puts "- copied #{f}" }
|
67
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Freeze all views into your application for easy modification"
|
71
|
+
task :views do
|
72
|
+
puts "Copying all view templates to your application - resolves any collisions"
|
73
|
+
copied, preserved = MerbAdmin.mirror_files_for :view
|
74
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
75
|
+
copied.each { |f| puts "- copied #{f}" }
|
76
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "Freeze all models into your application for easy modification"
|
80
|
+
task :models do
|
81
|
+
puts "Copying all models to your application - resolves any collisions"
|
82
|
+
copied, preserved = MerbAdmin.mirror_files_for :model
|
83
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
84
|
+
copied.each { |f| puts "- copied #{f}" }
|
85
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
86
|
+
end
|
87
|
+
|
88
|
+
desc "Freezes MerbAdmin as a gem and copies over merb-admin/app"
|
89
|
+
task :app_with_gem => [:gem, :app]
|
90
|
+
|
91
|
+
desc "Freezes MerbAdmin by unpacking all files into your application"
|
92
|
+
task :unpack do
|
93
|
+
puts "Unpacking MerbAdmin files to your application - resolves any collisions"
|
94
|
+
copied, preserved = MerbAdmin.unpack_slice!
|
95
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
96
|
+
copied.each { |f| puts "- copied #{f}" }
|
97
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
namespace :slices do
|
2
|
+
namespace :"merb-admin" do
|
3
|
+
|
4
|
+
# add your own merb-admin tasks here
|
5
|
+
|
6
|
+
# # Uncomment the following lines and edit the pre defined tasks
|
7
|
+
#
|
8
|
+
# # implement this to test for structural/code dependencies
|
9
|
+
# # like certain directories or availability of other files
|
10
|
+
# desc "Test for any dependencies"
|
11
|
+
# task :preflight do
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # implement this to perform any database related setup steps
|
15
|
+
# desc "Migrate the database"
|
16
|
+
# task :migrate do
|
17
|
+
# end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
namespace :slices do
|
2
|
+
namespace :"merb-admin" do
|
3
|
+
|
4
|
+
desc "Run slice specs within the host application context"
|
5
|
+
task :spec => [ "spec:explain", "spec:default" ]
|
6
|
+
|
7
|
+
namespace :spec do
|
8
|
+
|
9
|
+
slice_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
10
|
+
|
11
|
+
task :explain do
|
12
|
+
puts "\nNote: By running MerbAdmin specs inside the application context any\n" +
|
13
|
+
"overrides could break existing specs. This isn't always a problem,\n" +
|
14
|
+
"especially in the case of views. Use these spec tasks to check how\n" +
|
15
|
+
"well your application conforms to the original slice implementation."
|
16
|
+
end
|
17
|
+
|
18
|
+
Spec::Rake::SpecTask.new('default') do |t|
|
19
|
+
t.spec_opts = ["--format", "specdoc", "--colour"]
|
20
|
+
t.spec_files = Dir["#{slice_root}/spec/**/*_spec.rb"].sort
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "Run all model specs, run a spec for a specific Model with MODEL=MyModel"
|
24
|
+
Spec::Rake::SpecTask.new('model') do |t|
|
25
|
+
t.spec_opts = ["--format", "specdoc", "--colour"]
|
26
|
+
if(ENV['MODEL'])
|
27
|
+
t.spec_files = Dir["#{slice_root}/spec/models/**/#{ENV['MODEL']}_spec.rb"].sort
|
28
|
+
else
|
29
|
+
t.spec_files = Dir["#{slice_root}/spec/models/**/*_spec.rb"].sort
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Run all request specs, run a spec for a specific request with REQUEST=MyRequest"
|
34
|
+
Spec::Rake::SpecTask.new('request') do |t|
|
35
|
+
t.spec_opts = ["--format", "specdoc", "--colour"]
|
36
|
+
if(ENV['REQUEST'])
|
37
|
+
t.spec_files = Dir["#{slice_root}/spec/requests/**/#{ENV['REQUEST']}_spec.rb"].sort
|
38
|
+
else
|
39
|
+
t.spec_files = Dir["#{slice_root}/spec/requests/**/*_spec.rb"].sort
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Run all specs and output the result in html"
|
44
|
+
Spec::Rake::SpecTask.new('html') do |t|
|
45
|
+
t.spec_opts = ["--format", "html"]
|
46
|
+
t.libs = ['lib', 'server/lib' ]
|
47
|
+
t.spec_files = Dir["#{slice_root}/spec/**/*_spec.rb"].sort
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
data/lib/merb-admin.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
if defined?(Merb::Plugins)
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__)
|
4
|
+
|
5
|
+
dependency 'merb-slices', :immediate => true
|
6
|
+
Merb::Plugins.add_rakefiles "merb-admin/merbtasks", "merb-admin/slicetasks", "merb-admin/spectasks"
|
7
|
+
|
8
|
+
# Register the Slice for the current host application
|
9
|
+
Merb::Slices::register(__FILE__)
|
10
|
+
|
11
|
+
# Slice configuration - set this in a before_app_loads callback.
|
12
|
+
# By default a Slice uses its own layout, so you can swicht to
|
13
|
+
# the main application layout or no layout at all if needed.
|
14
|
+
#
|
15
|
+
# Configuration options:
|
16
|
+
# :layout - the layout to use; defaults to :merb-admin
|
17
|
+
# :mirror - which path component types to use on copy operations; defaults to all
|
18
|
+
Merb::Slices::config[:merb_admin][:layout] ||= :merb_admin
|
19
|
+
Merb::Slices::config[:merb_admin][:per_page] ||= 100
|
20
|
+
|
21
|
+
# All Slice code is expected to be namespaced inside a module
|
22
|
+
module MerbAdmin
|
23
|
+
|
24
|
+
# Slice metadata
|
25
|
+
self.description = "MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data."
|
26
|
+
self.version = "0.4.3"
|
27
|
+
self.author = "Erik Michaels-Ober"
|
28
|
+
|
29
|
+
# Stub classes loaded hook - runs before LoadClasses BootLoader
|
30
|
+
# right after a slice's classes have been loaded internally.
|
31
|
+
def self.loaded
|
32
|
+
end
|
33
|
+
|
34
|
+
# Initialization hook - runs before AfterAppLoads BootLoader
|
35
|
+
def self.init
|
36
|
+
end
|
37
|
+
|
38
|
+
# Activation hook - runs after AfterAppLoads BootLoader
|
39
|
+
def self.activate
|
40
|
+
end
|
41
|
+
|
42
|
+
# Deactivation hook - triggered by Merb::Slices.deactivate(MerbAdmin)
|
43
|
+
def self.deactivate
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.setup_router(scope)
|
47
|
+
scope.match("/", :method => :get).
|
48
|
+
to(:controller => "main", :action => "index").
|
49
|
+
name(:admin_dashboard)
|
50
|
+
|
51
|
+
scope.match("/:model_name", :method => :get).
|
52
|
+
to(:controller => "main", :action => "list").
|
53
|
+
name(:admin_list)
|
54
|
+
|
55
|
+
scope.match("/:model_name/new", :method => :get).
|
56
|
+
to(:controller => "main", :action => "new").
|
57
|
+
name(:admin_new)
|
58
|
+
|
59
|
+
scope.match("/:model_name/:id/edit", :method => :get).
|
60
|
+
to(:controller => "main", :action => "edit").
|
61
|
+
name(:admin_edit)
|
62
|
+
|
63
|
+
scope.match("/:model_name", :method => :post).
|
64
|
+
to(:controller => "main", :action => "create").
|
65
|
+
name(:admin_create)
|
66
|
+
|
67
|
+
scope.match("/:model_name/:id", :method => :put).
|
68
|
+
to(:controller => "main", :action => "update").
|
69
|
+
name(:admin_update)
|
70
|
+
|
71
|
+
scope.match("/:model_name/:id/delete", :method => :get).
|
72
|
+
to(:controller => "main", :action => "delete").
|
73
|
+
name(:admin_delete)
|
74
|
+
|
75
|
+
scope.match("/:model_name/:id(.:format)", :method => :delete).
|
76
|
+
to(:controller => "main", :action => "destroy").
|
77
|
+
name(:admin_destroy)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
# Setup the slice layout for MerbAdmin
|
83
|
+
#
|
84
|
+
# Use MerbAdmin.push_path and MerbAdmin.push_app_path
|
85
|
+
# to set paths to merb-admin-level and app-level paths. Example:
|
86
|
+
#
|
87
|
+
# MerbAdmin.push_path(:application, MerbAdmin.root)
|
88
|
+
# MerbAdmin.push_app_path(:application, Merb.root / 'slices' / 'merb-admin')
|
89
|
+
# ...
|
90
|
+
#
|
91
|
+
# Any component path that hasn't been set will default to MerbAdmin.root
|
92
|
+
#
|
93
|
+
# Or just call setup_default_structure! to setup a basic Merb MVC structure.
|
94
|
+
MerbAdmin.setup_default_structure!
|
95
|
+
|
96
|
+
# Add dependencies for other MerbAdmin classes below. Example:
|
97
|
+
# dependency "merb-admin/other"
|
98
|
+
|
99
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,85 @@
|
|
1
|
+
// Finds all fieldsets with class="collapse", collapses them, and gives each
|
2
|
+
// one a "Show" link that uncollapses it. The "Show" link becomes a "Hide"
|
3
|
+
// link when the fieldset is visible.
|
4
|
+
|
5
|
+
function findForm(node) {
|
6
|
+
// returns the node of the form containing the given node
|
7
|
+
if (node.tagName.toLowerCase() != 'form') {
|
8
|
+
return findForm(node.parentNode);
|
9
|
+
}
|
10
|
+
return node;
|
11
|
+
}
|
12
|
+
|
13
|
+
var CollapsedFieldsets = {
|
14
|
+
collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
|
15
|
+
collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
|
16
|
+
collapsed_class: 'collapsed',
|
17
|
+
init: function() {
|
18
|
+
var fieldsets = document.getElementsByTagName('fieldset');
|
19
|
+
var collapsed_seen = false;
|
20
|
+
for (var i = 0, fs; fs = fieldsets[i]; i++) {
|
21
|
+
// Collapse this fieldset if it has the correct class, and if it
|
22
|
+
// doesn't have any errors. (Collapsing shouldn't apply in the case
|
23
|
+
// of error messages.)
|
24
|
+
if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
|
25
|
+
collapsed_seen = true;
|
26
|
+
// Give it an additional class, used by CSS to hide it.
|
27
|
+
fs.className += ' ' + CollapsedFieldsets.collapsed_class;
|
28
|
+
// (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
|
29
|
+
var collapse_link = document.createElement('a');
|
30
|
+
collapse_link.className = 'collapse-toggle';
|
31
|
+
collapse_link.id = 'fieldsetcollapser' + i;
|
32
|
+
collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
|
33
|
+
collapse_link.href = '#';
|
34
|
+
collapse_link.innerHTML = gettext('Show');
|
35
|
+
var h2 = fs.getElementsByTagName('h2')[0];
|
36
|
+
h2.appendChild(document.createTextNode(' ('));
|
37
|
+
h2.appendChild(collapse_link);
|
38
|
+
h2.appendChild(document.createTextNode(')'));
|
39
|
+
}
|
40
|
+
}
|
41
|
+
if (collapsed_seen) {
|
42
|
+
// Expand all collapsed fieldsets when form is submitted.
|
43
|
+
addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
|
44
|
+
}
|
45
|
+
},
|
46
|
+
fieldset_has_errors: function(fs) {
|
47
|
+
// Returns true if any fields in the fieldset have validation errors.
|
48
|
+
var divs = fs.getElementsByTagName('div');
|
49
|
+
for (var i=0; i<divs.length; i++) {
|
50
|
+
if (divs[i].className.match(/\berrors\b/)) {
|
51
|
+
return true;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
return false;
|
55
|
+
},
|
56
|
+
show: function(fieldset_index) {
|
57
|
+
var fs = document.getElementsByTagName('fieldset')[fieldset_index];
|
58
|
+
// Remove the class name that causes the "display: none".
|
59
|
+
fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
|
60
|
+
// Toggle the "Show" link to a "Hide" link
|
61
|
+
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
62
|
+
collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
|
63
|
+
collapse_link.innerHTML = gettext('Hide');
|
64
|
+
},
|
65
|
+
hide: function(fieldset_index) {
|
66
|
+
var fs = document.getElementsByTagName('fieldset')[fieldset_index];
|
67
|
+
// Add the class name that causes the "display: none".
|
68
|
+
fs.className += ' ' + CollapsedFieldsets.collapsed_class;
|
69
|
+
// Toggle the "Hide" link to a "Show" link
|
70
|
+
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
71
|
+
collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
|
72
|
+
collapse_link.innerHTML = gettext('Show');
|
73
|
+
},
|
74
|
+
|
75
|
+
uncollapse_all: function() {
|
76
|
+
var fieldsets = document.getElementsByTagName('fieldset');
|
77
|
+
for (var i=0; i<fieldsets.length; i++) {
|
78
|
+
if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
|
79
|
+
CollapsedFieldsets.show(i);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
addEvent(window, 'load', CollapsedFieldsets.init);
|