bhm-admin 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +64 -0
- data/app/controllers/admin/base_controller.rb +10 -0
- data/app/controllers/admin_controller.rb +21 -0
- data/app/views/admin/shared/_edit_base.html.haml +8 -0
- data/app/views/admin/shared/_footer.html.haml +1 -0
- data/app/views/admin/shared/_header.html.haml +7 -0
- data/app/views/admin/shared/_new_base.html.haml +8 -0
- data/app/views/admin/shared/_sections.html.haml +1 -0
- data/app/views/admin/shared/_sidebar.html.haml +2 -0
- data/app/views/layouts/admin.html.haml +29 -0
- data/bhm-admin.gemspec +119 -0
- data/compass/stylesheets/bhm/admin/_base.sass +25 -0
- data/compass/stylesheets/bhm/admin/_content.sass +11 -0
- data/compass/stylesheets/bhm/admin/_flash.sass +19 -0
- data/compass/stylesheets/bhm/admin/_footer.sass +5 -0
- data/compass/stylesheets/bhm/admin/_forms.sass +43 -0
- data/compass/stylesheets/bhm/admin/_formtastic.sass +136 -0
- data/compass/stylesheets/bhm/admin/_general.sass +32 -0
- data/compass/stylesheets/bhm/admin/_grid.sass +21 -0
- data/compass/stylesheets/bhm/admin/_header.sass +34 -0
- data/compass/stylesheets/bhm/admin/_listing.sass +80 -0
- data/compass/stylesheets/bhm/admin/_sidebar.sass +22 -0
- data/compass/stylesheets/bhm/admin/_util.sass +5 -0
- data/compass/templates/project/admin.sass +3 -0
- data/compass/templates/project/manifest.rb +1 -0
- data/config/locales/en.yml +12 -0
- data/lib/bhm/admin/attr_accessible_scoping.rb +53 -0
- data/lib/bhm/admin/compass_framework.rb +14 -0
- data/lib/bhm/admin/engine.rb +18 -0
- data/lib/bhm/admin/nested_form_helper.rb +6 -0
- data/lib/bhm/admin/presentation_helper.rb +60 -0
- data/lib/bhm/admin/sidebar_helper.rb +75 -0
- data/lib/bhm/admin.rb +38 -0
- data/lib/bhm-admin.rb +1 -0
- data/lib/generators/bhm_admin/resource/resource_generator.rb +26 -0
- data/lib/generators/bhm_admin/resource/templates/_form.html.haml +0 -0
- data/lib/generators/bhm_admin/resource/templates/controller.rb +2 -0
- data/lib/generators/bhm_admin/resource/templates/edit.html.haml +1 -0
- data/lib/generators/bhm_admin/resource/templates/index.html.haml +21 -0
- data/lib/generators/bhm_admin/resource/templates/new.html.haml +1 -0
- data/lib/generators/bhm_admin/resource/templates/show.html.haml +5 -0
- data/test/helper.rb +10 -0
- data/test/test_bhm_admin.rb +7 -0
- metadata +233 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
header
|
2
|
+
background: #333333
|
3
|
+
margin: 0 0 1.5em 0
|
4
|
+
+border-bottom-radius(0.5em)
|
5
|
+
+box-shadow(#777777, 0, 0, 0.25em)
|
6
|
+
+linear-gradient(color-stops(#333333, #555555), bottom)
|
7
|
+
+clearfix
|
8
|
+
|
9
|
+
#header-logo
|
10
|
+
h1
|
11
|
+
font-weight: bold
|
12
|
+
color: white
|
13
|
+
font-size: 1.4em
|
14
|
+
margin: 0.5em 0
|
15
|
+
+text-shadow(0, 0, 2px, #000)
|
16
|
+
|
17
|
+
#header-menu
|
18
|
+
text-align: right
|
19
|
+
|
20
|
+
#header-menu ul
|
21
|
+
padding: 0
|
22
|
+
margin: 0.8em 1.5em 0 0
|
23
|
+
li
|
24
|
+
+inline-list
|
25
|
+
margin: 0 0 0 1.5em
|
26
|
+
a
|
27
|
+
vertical-align: middle
|
28
|
+
font-size: 1.25em
|
29
|
+
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif
|
30
|
+
+link-colors(white, #ee6673)
|
31
|
+
+hover-link
|
32
|
+
a#view-site-link
|
33
|
+
font-size: 1em
|
34
|
+
color: #cccccc
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#content
|
2
|
+
table
|
3
|
+
width: 100%
|
4
|
+
border-left: 0.1em solid #999999
|
5
|
+
border-right: 0.1em solid #999999
|
6
|
+
thead
|
7
|
+
tr th
|
8
|
+
border-top: 0.1em solid #999999
|
9
|
+
border-bottom: 0.1em solid #999999
|
10
|
+
font-weight: bold
|
11
|
+
padding: 0.5em 0.4em
|
12
|
+
font-weight: bold
|
13
|
+
color: white
|
14
|
+
background: #555555
|
15
|
+
+linear-gradient(color-stops(#555555, #777777), bottom)
|
16
|
+
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif
|
17
|
+
tbody
|
18
|
+
tr.empty
|
19
|
+
background: #eeeeee
|
20
|
+
color: #333333
|
21
|
+
td
|
22
|
+
padding: 1em
|
23
|
+
text-align: center
|
24
|
+
tr.odd
|
25
|
+
background: #f9f9f9
|
26
|
+
tr.even
|
27
|
+
background: #f0f0f0
|
28
|
+
td
|
29
|
+
border-bottom: 0.1em solid #999999
|
30
|
+
padding: 0.4em
|
31
|
+
td.actions
|
32
|
+
text-align: right
|
33
|
+
ul
|
34
|
+
+inline-list
|
35
|
+
li
|
36
|
+
margin: 0 0.5em
|
37
|
+
a
|
38
|
+
+hover-link
|
39
|
+
+link-colors(#2e5499, #993a3f)
|
40
|
+
font-weight: bold
|
41
|
+
span.default-value
|
42
|
+
color: #666666
|
43
|
+
dl
|
44
|
+
font-size: 1.2em
|
45
|
+
width: 100%
|
46
|
+
+clearfix
|
47
|
+
border-bottom: 0.1em solid #999999
|
48
|
+
dt
|
49
|
+
font-weight: bold
|
50
|
+
margin: 0
|
51
|
+
padding: 5px 10px
|
52
|
+
clear: left
|
53
|
+
float: left
|
54
|
+
border-top: 0.1em solid #999999
|
55
|
+
width: 150px
|
56
|
+
text-align: right
|
57
|
+
dd
|
58
|
+
border-top: 0.1em solid #999999
|
59
|
+
width: 550px
|
60
|
+
margin: 0
|
61
|
+
padding: 5px 10px
|
62
|
+
float: left
|
63
|
+
ol, ul
|
64
|
+
margin: 0
|
65
|
+
li
|
66
|
+
list-style-position: inside
|
67
|
+
margin: 0
|
68
|
+
padding: 0
|
69
|
+
li.empty
|
70
|
+
list-style: none
|
71
|
+
margin: 0
|
72
|
+
color: #666666
|
73
|
+
ol li
|
74
|
+
list-style-type: upper-alpha
|
75
|
+
dt.question
|
76
|
+
width: 300px
|
77
|
+
font-size: 0.9em
|
78
|
+
dd.answer
|
79
|
+
width: 400px
|
80
|
+
font-size: 0.9em
|
@@ -0,0 +1,22 @@
|
|
1
|
+
section#sidebar
|
2
|
+
ul.sidebar-menu
|
3
|
+
+no-bullets
|
4
|
+
li a
|
5
|
+
+unstyled-link
|
6
|
+
font-size: 1em
|
7
|
+
font-weight: bold
|
8
|
+
display: block
|
9
|
+
padding: 0.3em 0.5em
|
10
|
+
margin: 0 0 0.5em
|
11
|
+
border: 0.2em solid #cccccc
|
12
|
+
text-align: center
|
13
|
+
color: #222222
|
14
|
+
background: #dfdfdf
|
15
|
+
+linear-gradient(color-stops(#dddddd, #eeeeee), bottom)
|
16
|
+
+border-radius(0.5em)
|
17
|
+
&:hover, &:active
|
18
|
+
+linear-gradient(color-stops(#333333, #555555), bottom)
|
19
|
+
color: white
|
20
|
+
border-color: #111111
|
21
|
+
h2
|
22
|
+
text-align: center
|
@@ -0,0 +1 @@
|
|
1
|
+
stylesheet 'admin.sass', :media => 'screen, projection'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
---
|
2
|
+
en:
|
3
|
+
bhm:
|
4
|
+
admin:
|
5
|
+
blank_value: "Currently blank"
|
6
|
+
empty_row: "There are currently no {{plural_object_name}}."
|
7
|
+
buttons:
|
8
|
+
show: "View"
|
9
|
+
edit: "Edit"
|
10
|
+
destroy: "Remove"
|
11
|
+
confirmation:
|
12
|
+
destroy: "Are you sure you wish to remove this {{object_name}admThis can't be reversed."
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module BHM
|
2
|
+
module Admin
|
3
|
+
module AttrAccessibleScoping
|
4
|
+
UnassignableAttribute = Class.new(StandardError)
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
attr_accessor :verbose
|
9
|
+
|
10
|
+
def disabled?
|
11
|
+
!!Thread.current[:attr_accessible_disabled]
|
12
|
+
end
|
13
|
+
|
14
|
+
def disable!
|
15
|
+
Thread.current[:attr_accessible_disabled] = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def enable!
|
19
|
+
Thread.current[:attr_accessible_disabled] = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def disable
|
23
|
+
disabled = disabled?
|
24
|
+
disable! if !disabled
|
25
|
+
begin
|
26
|
+
yield if block_given?
|
27
|
+
ensure
|
28
|
+
enable! if disabled
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
module ARMixin
|
35
|
+
|
36
|
+
def self.included(parent)
|
37
|
+
parent.alias_method_chain :remove_attributes_protected_from_mass_assignment, :global_disable
|
38
|
+
end
|
39
|
+
|
40
|
+
def remove_attributes_protected_from_mass_assignment_with_global_disable(attributes)
|
41
|
+
unless AttrAccessibleScoping.disabled? || (self.class.accessible_attributes && self.class.accessible_attributes.include?("all"))
|
42
|
+
trusted_attributes = Array(self.class.accessible_attributes)
|
43
|
+
attributes.each_pair do |k, v|
|
44
|
+
raise UnassignableAttribute, "The attribute #{k} can't be assigned on #{self.class.name}" unless trusted_attributes.include?(k.to_s.gsub(/\(\d+\w\)$/, ''))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
attributes
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module BHM
|
2
|
+
module Admin
|
3
|
+
|
4
|
+
def self.register_compass_framework!
|
5
|
+
root_path = File.expand_path('../../../compass', File.dirname(__FILE__))
|
6
|
+
Compass::Frameworks.register 'bhm-admin',
|
7
|
+
:stylesheets_directory => File.join(root_path, 'stylesheets'),
|
8
|
+
:templates_directory => File.join(root_path, 'templates')
|
9
|
+
end
|
10
|
+
|
11
|
+
register_compass_framework!
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module BHM
|
2
|
+
module Admin
|
3
|
+
class Engine < Rails::Engine
|
4
|
+
|
5
|
+
# paths.config.locales = BHM::Admin.root.join('config', 'locales')
|
6
|
+
# paths.config.controllers = BHM::Admin.root.join('app', 'controller')
|
7
|
+
# paths.config.views = BHM::Admin.root.join('app', 'views')
|
8
|
+
|
9
|
+
initializer :configure_compass do
|
10
|
+
end
|
11
|
+
|
12
|
+
initializer :extend_activerecord do
|
13
|
+
ActiveRecord::Base.send :include, BHM::Admin::AttrAccessibleScoping
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module BHM
|
2
|
+
module Admin
|
3
|
+
module PresentationHelper
|
4
|
+
|
5
|
+
def value_with_default(v, default = BHM::Admin.t(:blank_value), &blk)
|
6
|
+
inner = ""
|
7
|
+
if v.present?
|
8
|
+
inner = blk.present? ? capture(&blk) : v
|
9
|
+
else
|
10
|
+
inner = content_tag(:span, default, :class => 'default-value')
|
11
|
+
end
|
12
|
+
inner
|
13
|
+
end
|
14
|
+
|
15
|
+
alias vwd value_with_default
|
16
|
+
|
17
|
+
def individual_resource_links(r, name = current_resource_name, opts = {}, &blk)
|
18
|
+
items = [
|
19
|
+
ml(BHM::Admin.t("buttons.show"), resource_url(r)),
|
20
|
+
ml(BHM::Admin.t("buttons.edit"), edit_resource_url(r)),
|
21
|
+
ml(BHM::Admin.t("buttons.destroy"), resource_url(r), :method => :delete,
|
22
|
+
:confirm => BHM::Admin.t("confirmation.destroy", :object_name => name))
|
23
|
+
]
|
24
|
+
if blk.present?
|
25
|
+
position = opts.fetch(:at, :before)
|
26
|
+
value = capture(&blk)
|
27
|
+
position == :before ? items.unshift(value) : items.push(value)
|
28
|
+
end
|
29
|
+
content_tag(:ul, items.join.html_safe)
|
30
|
+
end
|
31
|
+
|
32
|
+
def default_collection_columns
|
33
|
+
klass = resource_class
|
34
|
+
if klass.const_defined?(:INDEX_COLUMNS)
|
35
|
+
klass::INDEX_COLUMNS
|
36
|
+
else
|
37
|
+
klass.column_names - [:created_at, :updated_at]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def empty_row_for_collection(size = default_collection_columns.size)
|
42
|
+
return if collection.present?
|
43
|
+
name = current_resource_name
|
44
|
+
inner = content_tag :td, BHM::Admin.t(:empty_row, :object_name => name.downcase, :plural_object_name => name.pluralize.downcase), :colspan => (size + 1)
|
45
|
+
content_tag :tr, inner, :class => 'empty'
|
46
|
+
end
|
47
|
+
|
48
|
+
def humanized_errors_on(object)
|
49
|
+
if object.errors[:base].present?
|
50
|
+
prefix = "This #{object.class.model_name.human}"
|
51
|
+
errors = content_tag(:p, "Please correct the following errors before continuing:")
|
52
|
+
inner_errors = object.errors[:base].map { |e| content_tag(:li, e) }.sum(ActiveSupport::SafeBuffer.new)
|
53
|
+
errors << content_tag(:ul, inner_errors)
|
54
|
+
content_tag(:div, errors, :class => 'resource-base-errors')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module BHM
|
2
|
+
module Admin
|
3
|
+
module SidebarHelper
|
4
|
+
|
5
|
+
def hide_sidebar!
|
6
|
+
content_for :sidebar, ' '.html_safe
|
7
|
+
end
|
8
|
+
|
9
|
+
def collection_sidebar
|
10
|
+
sidebar_menu(parent_sidebar_content + resources_sidebar_content)
|
11
|
+
end
|
12
|
+
|
13
|
+
def object_sidebar
|
14
|
+
name = current_resource_name
|
15
|
+
inner_menu = parent_sidebar_content + resources_sidebar_content(name) + resource_sidebar_content(name)
|
16
|
+
sidebar_menu(inner_menu)
|
17
|
+
end
|
18
|
+
|
19
|
+
def menu_link(*args, &blk)
|
20
|
+
content_tag(:li, link_to(*args, &blk), :class => 'menu-item')
|
21
|
+
end
|
22
|
+
alias ml menu_link
|
23
|
+
|
24
|
+
def sidebar_menu(inner_content = nil, &blk)
|
25
|
+
content = []
|
26
|
+
content << content_for(:sidebar_menu_start) if content_for?(:sidebar_menu_start)
|
27
|
+
content << inner_content.to_s if inner_content
|
28
|
+
content << capture(&blk) if blk.present?
|
29
|
+
content << content_for(:sidebar_menu_end) if content_for?(:sidebar_menu_end)
|
30
|
+
content = content_tag(:ul, content.join("").html_safe, :class => 'sidebar-menu')
|
31
|
+
content
|
32
|
+
end
|
33
|
+
|
34
|
+
def sidebar_klass_name(klass)
|
35
|
+
controller_i18n_path = controller.controller_path.split("/").join(".")
|
36
|
+
BHM::Admin.t(controller_i18n_path.to_sym, :scope => :model_name, :default => klass.model_name.human)
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_resource_name
|
40
|
+
sidebar_klass_name(resource_class).titleize
|
41
|
+
end
|
42
|
+
|
43
|
+
def current_parent_name
|
44
|
+
sidebar_klass_name(parent_class).titleize
|
45
|
+
end
|
46
|
+
|
47
|
+
def parent_sidebar_content
|
48
|
+
returning ActiveSupport::SafeBuffer.new do |content|
|
49
|
+
if respond_to?(:parent?) && parent?
|
50
|
+
parent_name = current_parent_name
|
51
|
+
content << ml("View #{parent_name}", parent_url)
|
52
|
+
content << ml("Edit #{parent_name}", File.join(parent_url, 'edit'))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def resources_sidebar_content(name = current_resource_name)
|
58
|
+
returning ActiveSupport::SafeBuffer.new do |content|
|
59
|
+
content << ml("All #{name.pluralize}", collection_url)
|
60
|
+
content << ml("Add #{name}", new_resource_url)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def resource_sidebar_content(name = current_resource_name)
|
65
|
+
returning ActiveSupport::SafeBuffer.new do |content|
|
66
|
+
content << ml("View #{name}", resource_url)
|
67
|
+
content << ml("Edit #{name}", edit_resource_url)
|
68
|
+
content << ml("Remove #{name}", resource_url, :method => :delete,
|
69
|
+
:confirm => BHM::Admin.t("confirmation.destroy", :object_name => name))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/bhm/admin.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module BHM
|
4
|
+
module Admin
|
5
|
+
|
6
|
+
VERSION = "0.1.0".freeze
|
7
|
+
|
8
|
+
# Helpers for use in the admin area.
|
9
|
+
autoload :SidebarHelper, 'bhm/admin/sidebar_helper'
|
10
|
+
autoload :PresentationHelper, 'bhm/admin/presentation_helper'
|
11
|
+
autoload :NestedFormHelper, 'bhm/admin/nested_form_helper'
|
12
|
+
autoload :AttrAccessibleScoping, 'bhm/admin/attr_accessible_scoping'
|
13
|
+
|
14
|
+
class << self; attr_accessor :site_name; end
|
15
|
+
self.site_name ||= "Your Website"
|
16
|
+
|
17
|
+
def self.t(*args)
|
18
|
+
options = args.extract_options!
|
19
|
+
options[:scope] = ["bhm.admin", options.delete(:scope)].flatten.compact.join(".")
|
20
|
+
args.unshift args.shift.to_sym
|
21
|
+
args << options
|
22
|
+
::I18n.t(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.root
|
26
|
+
@_bhm_admin_root ||= Pathname(__FILE__).dirname.dirname.dirname
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.helper_classes
|
30
|
+
[SidebarHelper, PresentationHelper, NestedFormHelper]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Hook into rails.
|
34
|
+
require 'bhm/admin/engine' if defined?(Rails::Engine)
|
35
|
+
require 'bhm/admin/compass_framework' if defined?(Compass)
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/bhm-admin.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bhm/admin'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module BhmAdmin
|
2
|
+
module Generators
|
3
|
+
class ResourceGenerator < Rails::Generators::NamedBase
|
4
|
+
|
5
|
+
def self.source_root
|
6
|
+
@_bar_source_root ||= File.expand_path("templates", File.dirname(__FILE__))
|
7
|
+
end
|
8
|
+
|
9
|
+
check_class_collision :suffix => "Controller", :prefix => "Admin::"
|
10
|
+
|
11
|
+
def create_controller_files
|
12
|
+
template 'controller.rb', File.join('app/controllers/admin', class_path, "#{file_name}_controller.rb")
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_template_files
|
16
|
+
base_path = File.join("app/views/admin", class_path, file_name)
|
17
|
+
empty_directory base_path
|
18
|
+
%w(new edit index show _form).each do |view|
|
19
|
+
sub_path = "#{view}.html.haml"
|
20
|
+
template sub_path, File.join(base_path, sub_path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
= render :partial => 'admin/shared/edit_base'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
%h2.title== Viewing all #{current_resource_name.pluralize}
|
2
|
+
|
3
|
+
- column_names = default_collection_columns
|
4
|
+
|
5
|
+
= will_paginate collection
|
6
|
+
|
7
|
+
%table
|
8
|
+
%thead
|
9
|
+
%tr
|
10
|
+
- column_names.each do |column|
|
11
|
+
%th= column.to_s.titleize
|
12
|
+
%th
|
13
|
+
%tbody
|
14
|
+
- collection.each do |r|
|
15
|
+
%tr{:class => cycle('odd', 'even')}
|
16
|
+
- column_names.each do |column|
|
17
|
+
%td=vwd r.try(column)
|
18
|
+
%td.actions= individual_resource_links r
|
19
|
+
= empty_row_for_collection column_names.size
|
20
|
+
|
21
|
+
= will_paginate collection
|
@@ -0,0 +1 @@
|
|
1
|
+
= render :partial => 'admin/shared/new_base'
|
data/test/helper.rb
ADDED