bhm-admin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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