merb-admin 0.4.3
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/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);
|