bhf 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +0 -0
- data/app/controllers/bhf/application_controller.rb +77 -0
- data/app/controllers/bhf/entries_controller.rb +123 -0
- data/app/controllers/bhf/pages_controller.rb +49 -0
- data/app/helpers/bhf/application_helper.rb +22 -0
- data/app/helpers/bhf/entries_helper.rb +16 -0
- data/app/helpers/bhf/pages_helper.rb +30 -0
- data/app/views/bhf/_footer.haml +11 -0
- data/app/views/bhf/application/index.haml +3 -0
- data/app/views/bhf/entries/_form.haml +14 -0
- data/app/views/bhf/entries/_validation_errors.haml +5 -0
- data/app/views/bhf/entries/edit.haml +2 -0
- data/app/views/bhf/entries/form/belongs_to/_radio.haml +7 -0
- data/app/views/bhf/entries/form/belongs_to/_select.haml +6 -0
- data/app/views/bhf/entries/form/belongs_to/_static.haml +9 -0
- data/app/views/bhf/entries/form/column/_boolean.haml +2 -0
- data/app/views/bhf/entries/form/column/_date.haml +2 -0
- data/app/views/bhf/entries/form/column/_file.haml +2 -0
- data/app/views/bhf/entries/form/column/_markdown.haml +3 -0
- data/app/views/bhf/entries/form/column/_number.haml +2 -0
- data/app/views/bhf/entries/form/column/_static.haml +8 -0
- data/app/views/bhf/entries/form/column/_string.haml +2 -0
- data/app/views/bhf/entries/form/column/_text.haml +2 -0
- data/app/views/bhf/entries/form/column/_wysiwyg.haml +3 -0
- data/app/views/bhf/entries/form/has_and_belongs_to_many/_check_box.haml +4 -0
- data/app/views/bhf/entries/form/has_and_belongs_to_many/_static.haml +12 -0
- data/app/views/bhf/entries/form/has_many/_static.haml +12 -0
- data/app/views/bhf/entries/form/has_one/_static.haml +9 -0
- data/app/views/bhf/entries/new.haml +2 -0
- data/app/views/bhf/helper/_field_errors.haml +4 -0
- data/app/views/bhf/helper/_flash.haml +4 -0
- data/app/views/bhf/helper/_info.haml +2 -0
- data/app/views/bhf/helper/_node.haml +6 -0
- data/app/views/bhf/helper/_reflection_node.haml +7 -0
- data/app/views/bhf/pages/_platform.haml +41 -0
- data/app/views/bhf/pages/macro/belongs_to/_default.haml +2 -0
- data/app/views/bhf/pages/macro/column/_boolean.haml +1 -0
- data/app/views/bhf/pages/macro/column/_date.haml +1 -0
- data/app/views/bhf/pages/macro/column/_number.haml +1 -0
- data/app/views/bhf/pages/macro/column/_primary_key.haml +1 -0
- data/app/views/bhf/pages/macro/column/_string.haml +1 -0
- data/app/views/bhf/pages/macro/column/_text.haml +1 -0
- data/app/views/bhf/pages/macro/has_and_belongs_to_many/_default.haml +2 -0
- data/app/views/bhf/pages/macro/has_many/_default.haml +2 -0
- data/app/views/bhf/pages/macro/has_one/_default.haml +2 -0
- data/app/views/bhf/pages/show.haml +3 -0
- data/app/views/layouts/bhf/default.haml +27 -0
- data/app/views/layouts/bhf/quick_edit.haml +5 -0
- data/config/locales/en.yml +56 -0
- data/config/routes.rb +14 -0
- data/lib/bhf/active_record.rb +18 -0
- data/lib/bhf/data.rb +127 -0
- data/lib/bhf/form.rb +35 -0
- data/lib/bhf/pagination.rb +111 -0
- data/lib/bhf/platform.rb +202 -0
- data/lib/bhf/settings.rb +40 -0
- data/lib/bhf.rb +13 -0
- data/lib/engine.rb +19 -0
- data/lib/rails/generators/bhf/templates/initializer.rb +9 -0
- data/public/javascripts/bhf.js +0 -0
- data/public/stylesheets/bhf.css +1 -0
- data/test/test_helper.rb +55 -0
- metadata +169 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
en:
|
2
|
+
bhf:
|
3
|
+
pages:
|
4
|
+
headline: Content
|
5
|
+
|
6
|
+
helpers:
|
7
|
+
searchform:
|
8
|
+
placeholder: Search
|
9
|
+
promts:
|
10
|
+
confirm: Are you sure?
|
11
|
+
entry:
|
12
|
+
new: "Create new %{platform_name}"
|
13
|
+
edit: "Edit %{platform_name}"
|
14
|
+
delete: "Delete %{platform_name}"
|
15
|
+
empty: Empty
|
16
|
+
entries:
|
17
|
+
empty: Empty
|
18
|
+
login:
|
19
|
+
success: "Login was successful"
|
20
|
+
error: "Can't login"
|
21
|
+
activated:
|
22
|
+
success: "%{model} was activated successfuly"
|
23
|
+
error: "%{model} error"
|
24
|
+
validation:
|
25
|
+
header: "%{error} prohibited this %{name} from being saved:"
|
26
|
+
error: error
|
27
|
+
|
28
|
+
quick_edit:
|
29
|
+
buttons:
|
30
|
+
cancel: Cancel
|
31
|
+
open: Open
|
32
|
+
save: Save
|
33
|
+
save_and_next: Save and go to next
|
34
|
+
|
35
|
+
pagination:
|
36
|
+
previous_label: « Previous
|
37
|
+
next_label: Next »
|
38
|
+
load_more: Show more entries
|
39
|
+
load_less: Show less entries
|
40
|
+
info:
|
41
|
+
default: "Displaying <strong>%{offset_start} - %{offset_end}</strong> of <strong>%{total_count}</strong> %{name} in total"
|
42
|
+
nothing_found: "No %{name} found"
|
43
|
+
one_found: "Displaying <strong>1</strong> %{name}"
|
44
|
+
all_displayed: "Displaying <strong>all %{total_count}</strong> %{name}"
|
45
|
+
activerecord:
|
46
|
+
notices:
|
47
|
+
messages:
|
48
|
+
create:
|
49
|
+
success: "%{model} was created successfuly"
|
50
|
+
error: "%{model} error"
|
51
|
+
update:
|
52
|
+
success: "%{model} was updated successfuly"
|
53
|
+
error: "%{model} error"
|
54
|
+
destory:
|
55
|
+
success: "%{model} was deleted successfuly"
|
56
|
+
error: "%{model} error"
|
data/config/routes.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
|
3
|
+
namespace :bhf, :path => Bhf::Engine.config.mount_at do
|
4
|
+
root :to => 'application#index'
|
5
|
+
|
6
|
+
get 'page/:page', :to => 'pages#show', :as => :page
|
7
|
+
|
8
|
+
scope ':platform' do
|
9
|
+
resources :entries, :except => [:index, :show]
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Bhf
|
2
|
+
module ActiveRecord
|
3
|
+
|
4
|
+
def to_bhf_s
|
5
|
+
return title if self.respond_to? :title
|
6
|
+
return name if self.respond_to? :name
|
7
|
+
|
8
|
+
if self.respond_to? :attributes
|
9
|
+
return title if attributes['title']
|
10
|
+
return name if attributes['name']
|
11
|
+
return "#{self.class.to_s.humanize} ID: #{send(self.class.primary_key)}" if attributes[self.class.primary_key]
|
12
|
+
end
|
13
|
+
|
14
|
+
self.to_s.humanize
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/bhf/data.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
module Bhf
|
2
|
+
module Data
|
3
|
+
|
4
|
+
class Field
|
5
|
+
|
6
|
+
attr_reader :info
|
7
|
+
|
8
|
+
def initialize(props, options = {}, pk = 'id')
|
9
|
+
@props = props
|
10
|
+
@info = options[:info] if options[:info]
|
11
|
+
|
12
|
+
@overwrite_type = options[:overwrite_type].to_sym if options[:overwrite_type]
|
13
|
+
|
14
|
+
@primary_key = pk
|
15
|
+
end
|
16
|
+
|
17
|
+
def macro
|
18
|
+
:column
|
19
|
+
end
|
20
|
+
|
21
|
+
def type
|
22
|
+
return @overwrite_type if @overwrite_type
|
23
|
+
|
24
|
+
@props.type
|
25
|
+
end
|
26
|
+
|
27
|
+
def form_type
|
28
|
+
return @overwrite_type if @overwrite_type
|
29
|
+
|
30
|
+
if name === @primary_key || name === 'updated_at' || name === 'created_at'
|
31
|
+
:static
|
32
|
+
else
|
33
|
+
supported_types(@props.type)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def display_type
|
38
|
+
if name === @primary_key
|
39
|
+
:primary_key
|
40
|
+
elsif name === 'updated_at' || name === 'created_at'
|
41
|
+
:date
|
42
|
+
else
|
43
|
+
supported_types(@props.type)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def name
|
48
|
+
@props.name
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def supported_types(check_type)
|
54
|
+
if [:boolean, :text].include?(check_type)
|
55
|
+
check_type
|
56
|
+
elsif type_sym = group_types(check_type)
|
57
|
+
type_sym
|
58
|
+
else
|
59
|
+
:string
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def group_types(type_sym)
|
64
|
+
return :date if [:date, :datetime, :timestamp, :time, :year].include?(type_sym)
|
65
|
+
return :number if [:integer, :float].include?(type_sym)
|
66
|
+
return :file if type_sym === :file
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
class Reflection
|
73
|
+
|
74
|
+
attr_reader :reflection, :info, :link
|
75
|
+
|
76
|
+
def initialize(reflection, options = {})
|
77
|
+
@reflection = reflection
|
78
|
+
@info = options[:info] if options[:info]
|
79
|
+
@link = options[:link].to_sym if options[:link]
|
80
|
+
|
81
|
+
@overwrite_type = options[:overwrite_type].to_sym if options[:overwrite_type]
|
82
|
+
end
|
83
|
+
|
84
|
+
def macro
|
85
|
+
@reflection.macro
|
86
|
+
end
|
87
|
+
|
88
|
+
def type
|
89
|
+
return @overwrite_type if @overwrite_type
|
90
|
+
|
91
|
+
if macro === :has_and_belongs_to_many
|
92
|
+
:check_box
|
93
|
+
elsif macro === :belongs_to
|
94
|
+
:select
|
95
|
+
else
|
96
|
+
:static
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def form_type
|
101
|
+
type
|
102
|
+
end
|
103
|
+
|
104
|
+
def display_type
|
105
|
+
:default
|
106
|
+
end
|
107
|
+
|
108
|
+
def name
|
109
|
+
@reflection.name.to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
class Column
|
116
|
+
|
117
|
+
attr_reader :name, :field
|
118
|
+
|
119
|
+
def initialize(field)
|
120
|
+
@name = field.name
|
121
|
+
@field = field
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
data/lib/bhf/form.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Bhf
|
2
|
+
module Form
|
3
|
+
|
4
|
+
class Builder < ActionView::Helpers::FormBuilder
|
5
|
+
include ActionView::Helpers::FormTagHelper
|
6
|
+
|
7
|
+
def error_label(name, message)
|
8
|
+
label name, "#{object.class.human_attribute_name(name)} #{message}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def field_errors(field)
|
12
|
+
object.errors[field.to_sym]
|
13
|
+
end
|
14
|
+
|
15
|
+
def field_has_errors?(field)
|
16
|
+
field_errors(field).any?
|
17
|
+
end
|
18
|
+
|
19
|
+
def many_to_many_check_box(obj, ref_name, params)
|
20
|
+
mm = :has_and_belongs_to_many
|
21
|
+
checked = if params[mm] && params[mm][ref_name]
|
22
|
+
params[mm][ref_name][obj.id.to_s] != ''
|
23
|
+
else
|
24
|
+
object.send(ref_name).include?(obj)
|
25
|
+
end
|
26
|
+
|
27
|
+
hidden_field_tag("#{mm}[#{ref_name}][#{obj.id}]", '', :id => "hidden_has_and_belongs_to_many_#{ref_name}_#{obj.id}")+' '+
|
28
|
+
check_box_tag("#{mm}[#{ref_name}][#{obj.id}]", obj.id, checked)+' '+
|
29
|
+
label_tag("#{mm}_#{ref_name}_#{obj.id}", obj.to_bhf_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Bhf
|
2
|
+
|
3
|
+
class Pagination
|
4
|
+
|
5
|
+
attr_accessor :template
|
6
|
+
attr_reader :offset_per_page, :offset_to_add
|
7
|
+
|
8
|
+
def initialize(offset_per_page = 10, offset_to_add = 5)
|
9
|
+
@offset_per_page = offset_per_page
|
10
|
+
@offset_to_add = offset_to_add
|
11
|
+
end
|
12
|
+
|
13
|
+
def paginate(platform)
|
14
|
+
platform_params = template.params[platform.name] || {}
|
15
|
+
|
16
|
+
if page_links = template.will_paginate(platform.paginated_objects, {
|
17
|
+
:previous_label => I18n.t('bhf.pagination.previous_label'),
|
18
|
+
:next_label => I18n.t('bhf.pagination.next_label'),
|
19
|
+
:renderer => LinkRenderer.new(self, platform),
|
20
|
+
:container => false
|
21
|
+
})
|
22
|
+
links = "#{load_more(platform)} #{page_links}"
|
23
|
+
elsif platform.paginated_objects.total_pages == 1 && platform.paginated_objects.size > @offset_to_add
|
24
|
+
links = load_less(platform)
|
25
|
+
end
|
26
|
+
|
27
|
+
if links
|
28
|
+
template.content_tag(:div, links.html_safe, {:class => 'pagination'})
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def info(platform, options = {})
|
33
|
+
collection = platform.paginated_objects
|
34
|
+
|
35
|
+
entry_name = options[:entry_name] ||
|
36
|
+
(collection.empty?? 'entry' : collection.first.class.model_name.human)
|
37
|
+
|
38
|
+
info = if collection.total_pages < 2
|
39
|
+
case collection.size
|
40
|
+
when 0
|
41
|
+
I18n.t 'bhf.pagination.info.nothing_found', :name => entry_name.pluralize
|
42
|
+
when 1
|
43
|
+
I18n.t 'bhf.pagination.info.one_found', :name => entry_name
|
44
|
+
else
|
45
|
+
I18n.t 'bhf.pagination.info.all_displayed', :total_count => collection.size, :name => entry_name.pluralize
|
46
|
+
end
|
47
|
+
else
|
48
|
+
I18n.t('bhf.pagination.info.default', {
|
49
|
+
:name => entry_name.pluralize,
|
50
|
+
:total_count => collection.total_entries,
|
51
|
+
:offset_start => collection.offset + 1,
|
52
|
+
:offset_end => collection.offset + collection.length
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
info.html_safe
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_more(platform, attributes = {}, plus = true)
|
60
|
+
platform_params = template.params[platform.name] || {}
|
61
|
+
load_offset = @offset_per_page
|
62
|
+
load_offset = platform_params[:per_page].to_i if platform_params[:per_page]
|
63
|
+
if plus
|
64
|
+
load_offset += @offset_to_add
|
65
|
+
else
|
66
|
+
load_offset -= @offset_to_add
|
67
|
+
end
|
68
|
+
|
69
|
+
platform_params.delete(:page)
|
70
|
+
platform_params[:per_page] = load_offset
|
71
|
+
|
72
|
+
direction = (plus ? 'more' : 'less')
|
73
|
+
template.link_to(
|
74
|
+
I18n.t("bhf.pagination.load_#{direction}"),
|
75
|
+
template.bhf_page_path(
|
76
|
+
platform.page_name,
|
77
|
+
template.params.merge(platform.name => platform_params)
|
78
|
+
), attributes.merge(:class => "load_#{direction}")
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
def load_less(platform, attributes = {})
|
83
|
+
load_more(platform, attributes, false)
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
class LinkRenderer < WillPaginate::LinkRenderer
|
88
|
+
|
89
|
+
def initialize(bhf_pagination, platform)
|
90
|
+
@b_p = bhf_pagination
|
91
|
+
@platform = platform
|
92
|
+
end
|
93
|
+
|
94
|
+
def page_link(page, text, attributes = {})
|
95
|
+
platform_params = @b_p.template.params[@platform.name] || {}
|
96
|
+
platform_params[:page] = page
|
97
|
+
|
98
|
+
@b_p.template.link_to(
|
99
|
+
text,
|
100
|
+
@b_p.template.bhf_page_path(
|
101
|
+
@platform.page_name,
|
102
|
+
@b_p.template.params.merge(@platform.name => platform_params)
|
103
|
+
), attributes
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
data/lib/bhf/platform.rb
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
module Bhf
|
2
|
+
class Platform
|
3
|
+
|
4
|
+
attr_accessor :paginated_objects
|
5
|
+
attr_reader :name, :title, :page_name
|
6
|
+
|
7
|
+
def initialize(options, page_name)
|
8
|
+
@paginated_objects = []
|
9
|
+
|
10
|
+
if options.is_a?(String)
|
11
|
+
options = {options => nil}
|
12
|
+
end
|
13
|
+
@name = options.keys[0]
|
14
|
+
@data = options.values[0] || {}
|
15
|
+
@collection = get_collection
|
16
|
+
|
17
|
+
human_title = if model.to_s === @name.singularize.camelize
|
18
|
+
model.model_name.human
|
19
|
+
else
|
20
|
+
@name.humanize
|
21
|
+
end
|
22
|
+
|
23
|
+
@title = I18n.t("bhf.platforms.#{@name}.title", :platform_title => human_title, :default => human_title).pluralize
|
24
|
+
@page_name = page_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def search?
|
28
|
+
table_options(:search) != false
|
29
|
+
end
|
30
|
+
|
31
|
+
def custom_columns?
|
32
|
+
table_options(:columns).is_a?(Array)
|
33
|
+
end
|
34
|
+
|
35
|
+
def search
|
36
|
+
table_options(:search) || :where
|
37
|
+
end
|
38
|
+
|
39
|
+
def prepare_objects(options)
|
40
|
+
chain = model
|
41
|
+
|
42
|
+
if options[:order]
|
43
|
+
chain = chain.order("#{options[:order]} #{options[:direction]}")
|
44
|
+
end
|
45
|
+
|
46
|
+
if search? && options[:search].present?
|
47
|
+
chain = do_search(chain, options[:search])
|
48
|
+
end
|
49
|
+
|
50
|
+
@objects = chain.send(data_source)
|
51
|
+
end
|
52
|
+
|
53
|
+
def model
|
54
|
+
return @data['model'].constantize if @data['model']
|
55
|
+
@name.singularize.camelize.constantize
|
56
|
+
end
|
57
|
+
|
58
|
+
def model_name
|
59
|
+
ActiveModel::Naming.singular(model)
|
60
|
+
end
|
61
|
+
|
62
|
+
def fields
|
63
|
+
default_attrs(form_options(:display))
|
64
|
+
end
|
65
|
+
|
66
|
+
def columns
|
67
|
+
default_attrs(table_options(:columns)).
|
68
|
+
each_with_object([]) do |field, obj|
|
69
|
+
obj << Bhf::Data::Column.new(field)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def has_file_upload?
|
74
|
+
@collection.each do |field|
|
75
|
+
return true if field.form_type === :file
|
76
|
+
end
|
77
|
+
return false
|
78
|
+
end
|
79
|
+
|
80
|
+
def table
|
81
|
+
@data['table']
|
82
|
+
end
|
83
|
+
|
84
|
+
def form
|
85
|
+
@data['form']
|
86
|
+
end
|
87
|
+
|
88
|
+
def hooks(method)
|
89
|
+
@data['hooks'][method.to_s] if @data['hooks']
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def do_search(chain, search_term)
|
95
|
+
search_condition = if table_options(:search)
|
96
|
+
search_term
|
97
|
+
else
|
98
|
+
where_statement = []
|
99
|
+
model.columns_hash.each_pair do |name, props|
|
100
|
+
if props.type === :string
|
101
|
+
where_statement << "#{name} LIKE '%#{search_term}%'"
|
102
|
+
elsif props.type === :integer
|
103
|
+
where_statement << "#{name} = #{search_term.to_i}"
|
104
|
+
elsif props.type === :float
|
105
|
+
where_statement << "#{name} = #{search_term.to_f}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
where_statement.join(' OR ')
|
110
|
+
end
|
111
|
+
|
112
|
+
chain.send search, search_condition
|
113
|
+
end
|
114
|
+
|
115
|
+
def data_source
|
116
|
+
table_options(:source) || :all
|
117
|
+
end
|
118
|
+
|
119
|
+
def default_attrs(attrs)
|
120
|
+
if attrs
|
121
|
+
model_respond_to?(attrs)
|
122
|
+
@collection.select do |field|
|
123
|
+
attrs.include?(field.name)
|
124
|
+
end
|
125
|
+
else
|
126
|
+
@collection
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def get_collection
|
131
|
+
all = {}
|
132
|
+
|
133
|
+
model.columns_hash.each_pair do |name, props|
|
134
|
+
all[name] = Bhf::Data::Field.new(props, {
|
135
|
+
:overwrite_type => form_options(:types, name),
|
136
|
+
:info => I18n.t("bhf.platforms.#{@name}.infos.#{name}", :default => '')
|
137
|
+
}, model.primary_key)
|
138
|
+
end
|
139
|
+
|
140
|
+
model.reflections.each_pair do |name, props|
|
141
|
+
all[name.to_s] = Bhf::Data::Reflection.new(props, {
|
142
|
+
:overwrite_type => form_options(:types, name),
|
143
|
+
:info => I18n.t("bhf.platforms.#{@name}.infos.#{name}", :default => ''),
|
144
|
+
:link => form_options(:links, name)
|
145
|
+
})
|
146
|
+
|
147
|
+
fk = all[name.to_s].reflection.association_foreign_key
|
148
|
+
if all.has_key?(fk)
|
149
|
+
all.delete(fk)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
default_sort(all)
|
154
|
+
end
|
155
|
+
|
156
|
+
def default_sort(attrs)
|
157
|
+
id = []
|
158
|
+
static_dates = []
|
159
|
+
output = []
|
160
|
+
|
161
|
+
attrs.each_pair do |key, value|
|
162
|
+
if key === model.primary_key
|
163
|
+
id << value
|
164
|
+
elsif key === 'created_at' || key === 'updated_at'
|
165
|
+
static_dates << value
|
166
|
+
else
|
167
|
+
output << value
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
id + output.sort_by(&:name) + static_dates
|
172
|
+
end
|
173
|
+
|
174
|
+
def model_respond_to?(field_names)
|
175
|
+
new_obj = model.new
|
176
|
+
field_names.each do |field_name|
|
177
|
+
unless new_obj.respond_to?(field_name)
|
178
|
+
raise Exception.new("Model '#{model}' does not respond to '#{field_name}'")
|
179
|
+
return false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
true
|
183
|
+
end
|
184
|
+
|
185
|
+
def form_options(key, attribute = nil)
|
186
|
+
if form
|
187
|
+
if attribute === nil
|
188
|
+
form[key.to_s]
|
189
|
+
elsif form[key.to_s]
|
190
|
+
form[key.to_s][attribute.to_s]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def table_options(key)
|
196
|
+
if table
|
197
|
+
return table[key.to_s]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
end
|
data/lib/bhf/settings.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Bhf
|
2
|
+
|
3
|
+
class Settings
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def pages
|
10
|
+
@options['pages'].each_with_object([]) do |page, obj|
|
11
|
+
if page.is_a?(String)
|
12
|
+
page = {page => nil}
|
13
|
+
end
|
14
|
+
obj << page.keys[0]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def content_for_page(selected_page)
|
19
|
+
@options['pages'].each do |page|
|
20
|
+
if page.is_a?(String)
|
21
|
+
page = {page => nil}
|
22
|
+
end
|
23
|
+
if selected_page == page.keys[0]
|
24
|
+
return page.values.flatten
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_platform(platform_name)
|
30
|
+
pages.each do |page|
|
31
|
+
content_for_page(page).each do |platform|
|
32
|
+
bhf_platform = Bhf::Platform.new(platform, page)
|
33
|
+
return bhf_platform if bhf_platform.name == platform_name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/bhf.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
def d(var)
|
2
|
+
raise var.inspect.split(', ').join(", \n")
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
6
|
+
require 'bhf/active_record'
|
7
|
+
require 'bhf/data'
|
8
|
+
require 'bhf/platform'
|
9
|
+
require 'bhf/settings'
|
10
|
+
require 'bhf/pagination'
|
11
|
+
require 'bhf/form'
|
12
|
+
|
13
|
+
::ActiveRecord::Base.send :include, Bhf::ActiveRecord
|
data/lib/engine.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'haml'
|
2
|
+
require 'will_paginate'
|
3
|
+
|
4
|
+
module Bhf
|
5
|
+
class Engine < Rails::Engine
|
6
|
+
|
7
|
+
# Config defaults
|
8
|
+
config.page_title = nil
|
9
|
+
config.mount_at = 'bhf'
|
10
|
+
config.auth_logic_from = 'ApplicationController'
|
11
|
+
|
12
|
+
# config.bhf_logic = YAML::load(IO.read('config/bhf.yml'))
|
13
|
+
|
14
|
+
initializer 'static assets' do |app|
|
15
|
+
app.middleware.use ::ActionDispatch::Static, "#{root}/public"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{line-height:1}ol,ul{list-style:none}ins{text-decoration:none}del{text-decoration:line-through}table{border-spacing:0}textarea,input,button,body{font:14px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif}a:focus{outline:1px dotted}hr{border:0 #C8C8C8 solid;border-top-width:1px;clear:both;height:0;margin-bottom:20px}h1{font-size:25px}h2{font-size:23px}h3{font-size:21px}h4{font-size:19px}h5{font-size:17px}h6{font-size:15px}ol{list-style:decimal}html{min-width:700px}body{background:url(/images/bg.png);margin-right:-40px;overflow-x:hidden}a{text-decoration:none;color:inherit}header{display:block;overflow:hidden;clear:both;padding:20px 20px 0 20px}header h1{float:left;display:none}header li{float:left;font-weight:bold;margin-right:30px}header li.active a{text-shadow:#fff 0px -1px 0px;background:#d5d5d5;background:-moz-linear-gradient(top, #d5d5d5, #fff);background:-webkit-gradient(linear, left top, left bottom, from(#d5d5d5), to(#fff));box-shadow:0px 1px 4px #000;-moz-box-shadow:0px 1px 4px #000;-webkit-box-shadow:0px 1px 4px #000;color:#414756}header li.active a:hover{background:#fff;background:-moz-linear-gradient(top, #fff, #d5d5d5);background:-webkit-gradient(linear, left top, left bottom, from(#fff), to(#d5d5d5));border-color:#fff;text-shadow:#fff 0px 1px 0px;box-shadow:inset 0px 0px 3px #fff;-moz-box-shadow:inset 0px 0px 3px #fff;-webkit-box-shadow:inset 0px 0px 3px #fff}header li a{text-decoration:none;display:block;padding:5px 20px;border:1px solid transparent;color:#d8d8d8;text-shadow:#000 0px -1px 0px}header li a:hover{border-color:#2b303c;box-shadow:inset 0px 0px 35px #2b303c;-moz-box-shadow:inset 0px 0px 35px #2b303c;-webkit-box-shadow:inset 0px 0px 35px #2b303c}#content{display:table;width:100%;box-sizing:border-box;margin-left:-20px;border-spacing:20px}.quick_edit_holder,#main{display:table-cell;background:#eaeaea;border:3px solid #fff;padding:10px 20px;box-shadow:0px 1px 4px rgba(0,0,0,0.5);-moz-box-shadow:0px 1px 4px rgba(0,0,0,0.5);-webkit-box-shadow:0px 1px 4px rgba(0,0,0,0.5)}#content #main{border-right:none;border-left:none}#content .quick_edit_holder{border-right:none;position:relative;width:400px}#content .quick_edit_holder .node,#content .quick_edit_holder .input,#content .quick_edit_holder .label{display:block}#content .quick_edit_holder .input{padding-top:0}#content .quick_edit_holder textarea{width:300px;height:100px}#content .quick_edit_holder > .button.cancel,#content .quick_edit_holder > .cancel.alt_button,#content .quick_edit_holder > .pagination a.cancel,.pagination #content .quick_edit_holder > a.cancel,#content .quick_edit_holder > .pagination span.cancel,.pagination #content .quick_edit_holder > span.cancel,#content .quick_edit_holder > .pagination em.cancel,.pagination #content .quick_edit_holder > em.cancel,#content .quick_edit_holder > .button.open,#content .quick_edit_holder > .open.alt_button,#content .quick_edit_holder > .pagination a.open,.pagination #content .quick_edit_holder > a.open,#content .quick_edit_holder > .pagination span.open,.pagination #content .quick_edit_holder > span.open,#content .quick_edit_holder > .pagination em.open,.pagination #content .quick_edit_holder > em.open{float:right}#content .quick_edit_holder > .button.open,#content .quick_edit_holder > .open.alt_button,#content .quick_edit_holder > .pagination a.open,.pagination #content .quick_edit_holder > a.open,#content .quick_edit_holder > .pagination span.open,.pagination #content .quick_edit_holder > span.open,#content .quick_edit_holder > .pagination em.open,.pagination #content .quick_edit_holder > em.open{margin-right:10px}table{margin-top:40px;width:100%}table caption{height:60px;background-image:url(/images/button_bg_2.png)}table caption h4,table caption .info{float:left}table caption .info{padding:5px 20px;text-transform:uppercase;font-size:12px}table caption .create{float:right}table caption form{float:left}table thead th{padding:4px 0;padding-left:5px;text-align:left;border-top:1px solid #fff;border-bottom:1px solid #c6c6c6;white-space:nowrap}table thead th.primary_key{text-transform:uppercase}table thead th.sorted{background:#414756}table thead th.sorted a:after,table thead th.sorted.desc:hover a:after{content:" ▼"}table thead th.sorted:hover a:after,table thead th.sorted.desc a:after{content:" ▲"}table thead th.sorted a{color:#fff;text-shadow:#000 0px 1px 0px}table tbody td{border-top:1px solid #fff;border-bottom:1px solid #c6c6c6}table tbody td.has_many,table tbody td.has_and_belongs_to_many,table tbody td.text{max-width:200px;white-space:nowrap;overflow:hidden}table tbody td.has_many a,table tbody td.has_and_belongs_to_many a,table tbody td.text a{-webkit-mask-image:-webkit-gradient(linear, left top, right top, color-stop(50%, #000), to(rgba(255,255,255,0)))}table tbody a{display:block;padding:5px 3px}table tbody a.edit,table tbody a.delete{padding:0;margin-right:5px;display:inline-block;text-indent:-9999px;width:20px;height:20px}table tbody a.edit:active,table tbody a.delete:active{background-position:0 1px}table tbody a.edit{background:url(/images/icon_edit.png)}table tbody a.edit:hover{background-image:url(/images/icon_edit_a.png)}table tbody a.delete{background:url(/images/icon_delete.png)}table tbody a.delete:hover{background-image:url(/images/icon_delete_a.png)}table tbody tr:hover td,table tbody tr.live_edit td{background:#0f8fdd;color:#fff}table tbody tr:hover td:first-child,table tbody tr.live_edit td:first-child{border-radius:0px;border-top-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius:0px;-moz-border-radius-topleft:4px;-moz-border-radius-bottomleft:4px}table tbody tr:hover td:last-child,table tbody tr.live_edit td:last-child{border-radius:0px;border-top-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius:0px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}table tbody tr.live_edit td{background:red}table tfoot td{padding-top:10px;border-top:1px solid #fff}table thead .primary_key,table thead .number,table tbody .primary_key,table tbody .number{padding-right:10px;text-align:right}table thead .primary_key,table tbody .primary_key{width:30px}table thead .action,table tbody .action{width:50px}.default_input,.search input,form .node .input input[type="password"],form .node .input input[type="text"],form .node .input textarea{border:1px solid #bbb;background:#fff;border-radius:2px;-moz-border-radius:2px;box-shadow:0px 1px 0px #fff;-moz-box-shadow:0px 1px 0px #fff;-webkit-box-shadow:0px 1px 0px #fff;padding:3px 5px 1px 5px;width:300px}.default_input:focus,.search input:focus,form .node .input input[type="password"]:focus,form .node .input input[type="text"]:focus,form .node .input textarea:focus{outline:0;transition-duration:1s;-moz-transition-duration:1s;-webkit-transition-duration:1s;-webkit-box-shadow:0 1px 12px #0f8fdd;border-color:#0f8fdd}.search input{width:200px}form .node{display:table-row}form .node.string .input,form .node.string .label,form .node.text .input,form .node.text .label,form .node.password .input,form .node.password .label{padding-top:5px}form .node.string .label label,form .node.text .label label,form .node.password .label label{padding-top:5px}form .node .label{width:200px}form .node .label label{display:block}form .node .label .field_with_errors{color:red}form .node.primary_key .label{text-transform:uppercase}form .node .input,form .node .label{padding-top:10px;vertical-align:top;display:table-cell}form .node .input textarea{width:500px;height:200px}form .node .input .errors{color:red}form .node .input .field_with_errors input{border-color:red}form .error_explanation label{color:red;cursor:pointer;display:block}form .error_explanation label:hover{color:#f90}footer{text-shadow:#000 0px -1px 0px;text-align:center;color:gray;font-size:12px;line-height:20px}footer a{text-decoration:none}footer a:hover{text-decoration:underline}input[type="submit"],button,.button,.alt_button,.pagination a,.pagination a,.pagination span,.pagination span,.pagination em,.pagination em{display:inline-block;border:0;padding:12px 50px;background:url(/images/button_bg.png);border-radius:4px;-moz-border-radius:4px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.5),inset 0 2px 0 rgba(255,255,255,0.3),inset 0 1px 0 rgba(0,0,0,0.9);text-decoration:none;font-weight:bold;color:#f1f1f1;font-size:13px;text-shadow:0 -1px 0 #000;cursor:pointer;transition-duration:0.8s;-moz-transition-duration:0.8s;-webkit-transition-duration:0.8s;transition-property:color;-moz-transition-property:color;-webkit-transition-property:color}input[type="submit"]:hover,button:hover,.button:hover,.alt_button:hover,.pagination a:hover,.pagination a:hover,.pagination span:hover,.pagination span:hover,.pagination em:hover,.pagination em:hover{-webkit-box-shadow:inset 0 10px 20px 5px #000,inset 0 -2px 0 rgba(255,255,255,0.5),inset 0 -1px 0 #000;color:#38a5e9;text-shadow:0 1px 0 #000}input[type="submit"]:active,button:active,.button:active,.alt_button:active,.pagination a:active,.pagination a:active,.pagination span:active,.pagination span:active,.pagination em:active,.pagination em:active{-webkit-box-shadow:inset 0 1px 6px rgba(0,0,0,0.3),inset 0 -1px 0 #0f8fdd,inset 0 -2px 0 rgba(255,255,255,0.6);background:url(/images/button_bg_a.png);color:#fff}input[type="submit"]:focus,button:focus,.button:focus,.alt_button:focus,.pagination a:focus,.pagination a:focus,.pagination span:focus,.pagination span:focus,.pagination em:focus,.pagination em:focus{outline:0;padding:10px 48px;transition-duration:1s;-moz-transition-duration:1s;-webkit-transition-duration:1s;transition-property:-webkit-box-shadow;-moz-transition-property:-webkit-box-shadow;-webkit-transition-property:-webkit-box-shadow;-webkit-box-shadow:0 1px 12px #0f8fdd;border:2px solid #0f8fdd}.alt_button,.pagination a,.pagination span,.pagination em{background-image:url(/images/button_bg_2.png);padding:5px 10px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.7);color:#000;text-shadow:#fff 0px 1px 0px}@media (max-width: 800px){body{overflow-x:auto}}@media (max-width: 960px){.default_columns thead th:nth-last-child(2),.default_columns tbody td:nth-last-child(2),.default_columns thead th:nth-last-child(3),.default_columns tbody td:nth-last-child(3){display:none}}
|