app_frame 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +26 -0
  4. data/Gemfile.lock +181 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +25 -0
  7. data/Rakefile +47 -0
  8. data/VERSION +1 -0
  9. data/app/assets/javascripts/app_frame/application.js +9 -0
  10. data/app/assets/stylesheets/app_frame/_devise.scss +41 -0
  11. data/app/assets/stylesheets/app_frame/_tree.scss +31 -0
  12. data/app/assets/stylesheets/app_frame/application.scss +73 -0
  13. data/app/controllers/app_frame/devise/confirmations_controller.rb +3 -0
  14. data/app/controllers/app_frame/devise/passwords_controller.rb +3 -0
  15. data/app/controllers/app_frame/devise/registrations_controller.rb +3 -0
  16. data/app/controllers/app_frame/devise/sessions_controller.rb +3 -0
  17. data/app/helpers/app_frame/bootstrap_helper.rb +36 -0
  18. data/app/helpers/app_frame/breadcrumb_helper.rb +18 -0
  19. data/app/helpers/app_frame/menu_helper.rb +43 -0
  20. data/app/helpers/app_frame/pagination_helper.rb +12 -0
  21. data/app/helpers/app_frame/resources_helper.rb +63 -0
  22. data/app/helpers/app_frame/scopes_helper.rb +94 -0
  23. data/app/helpers/app_frame/select_helper.rb +8 -0
  24. data/app/helpers/app_frame/tree_nav_helper.rb +18 -0
  25. data/app/models/menu.rb +44 -0
  26. data/app/models/settings.rb +4 -0
  27. data/app/views/app_frame/devise/confirmations/new.html.haml +8 -0
  28. data/app/views/app_frame/devise/passwords/edit.html.haml +13 -0
  29. data/app/views/app_frame/devise/passwords/new.html.haml +8 -0
  30. data/app/views/app_frame/devise/registrations/edit.html.haml +19 -0
  31. data/app/views/app_frame/devise/registrations/new.html.haml +10 -0
  32. data/app/views/app_frame/devise/sessions/new.html.haml +12 -0
  33. data/app/views/app_frame/devise/shared/_links.html.haml +14 -0
  34. data/app/views/app_frame/devise/unlocks/new.html.haml +9 -0
  35. data/app/views/application/_brand.html.haml +1 -0
  36. data/app/views/application/_breadcrumb.html.haml +12 -0
  37. data/app/views/application/_flashes.html.haml +2 -0
  38. data/app/views/application/_form.html.haml +2 -0
  39. data/app/views/application/_head.html.haml +6 -0
  40. data/app/views/application/_secondary_menu.html.haml +3 -0
  41. data/app/views/application/_show.html.haml +5 -0
  42. data/app/views/application/_sidebar.html.haml +12 -0
  43. data/app/views/application/_sub_menu.html.haml +0 -0
  44. data/app/views/application/_table.html.haml +3 -0
  45. data/app/views/application/_toolbar.html.haml +7 -0
  46. data/app/views/application/_top_menu.html.haml +1 -0
  47. data/app/views/application/edit.html.haml +8 -0
  48. data/app/views/application/index.html.haml +8 -0
  49. data/app/views/application/new.html.haml +7 -0
  50. data/app/views/application/show.html.haml +10 -0
  51. data/app/views/kaminari/app_frame/_first_page.html.haml +9 -0
  52. data/app/views/kaminari/app_frame/_gap.html.haml +8 -0
  53. data/app/views/kaminari/app_frame/_last_page.html.haml +9 -0
  54. data/app/views/kaminari/app_frame/_next_page.html.haml +9 -0
  55. data/app/views/kaminari/app_frame/_page.html.haml +10 -0
  56. data/app/views/kaminari/app_frame/_paginator.html.haml +19 -0
  57. data/app/views/kaminari/app_frame/_prev_page.html.haml +9 -0
  58. data/app/views/layouts/app_frame/default.html.haml +33 -0
  59. data/app/views/layouts/app_frame/devise.html.haml +17 -0
  60. data/app_frame.gemspec +162 -0
  61. data/lib/app_frame.rb +27 -0
  62. data/lib/app_frame/controller_methods.rb +111 -0
  63. data/lib/app_frame/view_methods.rb +19 -0
  64. data/lib/assets/images/.gitkeep +0 -0
  65. data/lib/assets/javascripts/anytime.js +3716 -0
  66. data/lib/assets/stylesheets/anytime.css +777 -0
  67. data/lib/engine.rb +197 -0
  68. data/spec/app_frame_spec.rb +7 -0
  69. data/spec/spec_helper.rb +12 -0
  70. metadata +423 -0
@@ -0,0 +1,3 @@
1
+ class AppFrame::Devise::ConfirmationsController < Devise::ConfirmationsController
2
+ layout 'app_frame/devise'
3
+ end
@@ -0,0 +1,3 @@
1
+ class AppFrame::Devise::PasswordsController < Devise::PasswordsController
2
+ layout 'app_frame/devise'
3
+ end
@@ -0,0 +1,3 @@
1
+ class AppFrame::Devise::RegistrationsController < Devise::RegistrationsController
2
+ layout 'app_frame/devise'
3
+ end
@@ -0,0 +1,3 @@
1
+ class AppFrame::Devise::SessionsController < Devise::SessionsController
2
+ layout 'app_frame/devise'
3
+ end
@@ -0,0 +1,36 @@
1
+ module AppFrame
2
+ module BootstrapHelper
3
+ def alert(message, type = nil)
4
+ message = close_button + message
5
+ content_tag(:div, message, :class => "alert alert-#{alert_type_map(type)}")
6
+ end
7
+
8
+ def close_button
9
+ content_tag(:a, "&times;".html_safe, :class => 'close', :data => { :dismiss => "alert" })
10
+ end
11
+
12
+ def alert_type_map(type)
13
+ map = {
14
+ :alert => 'error',
15
+ :notice => 'success'
16
+ }
17
+
18
+ map[type.to_sym] || type
19
+ end
20
+
21
+ def icon(key, options = {})
22
+ css_class = "icon-#{key}"
23
+ css_class += " icon-white" if options[:invert]
24
+ content_tag(:i, '', :class => css_class).html_safe
25
+ end
26
+
27
+ def page_header(title, &block)
28
+ content = "".html_safe
29
+ content += content_tag(:div, capture(&block), :class => 'page-actions') if block_given?
30
+ content += content_tag(:h1, title)
31
+
32
+ content_tag(:div, content, :class => 'page-header')
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ module AppFrame::BreadcrumbHelper
2
+
3
+ def breadcrumb(items = [])
4
+
5
+ yield items if block_given?
6
+
7
+ return unless items.any?
8
+
9
+ last = items.pop
10
+
11
+ result = items.map { |i| content_tag(:li, i + content_tag(:span, "/", :class => 'divider')) }
12
+ result << content_tag(:li, last, :class => 'active')
13
+
14
+ content_tag :ul, result.join().html_safe, :class => 'breadcrumb'
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,43 @@
1
+ module AppFrame
2
+ module MenuHelper
3
+ def menu_link(key, path = '#', options = {}, &block)
4
+ active = false
5
+ highlight = options.delete(:highlights_on) || /#{path}/
6
+ dropdown = options.delete(:dropdown)
7
+
8
+ Array(highlight).each do |regex|
9
+ active = true if request.path =~ regex
10
+ end
11
+
12
+ options[:class] ||= ""
13
+ options[:class] << ' active' if active
14
+ options[:class] << ' dropdown' if dropdown
15
+ options[:class] = options[:class].present? ? options[:class].strip : nil
16
+
17
+ key = t(:"menu.#{key}") if key.is_a?(Symbol)
18
+
19
+ a_class = dropdown ? 'dropdown-toggle' : nil
20
+ ul_class = dropdown ? 'dropdown-menu' : nil
21
+
22
+ content = link_to(key, path, :class => a_class)
23
+ content += content_tag(:ul, capture(&block), :class => ul_class) if block_given?
24
+
25
+ content_tag :li, content, options
26
+ end
27
+
28
+ def content_locale_switch(obj = nil)
29
+ return unless obj.respond_to?(:translated_locales)
30
+
31
+ current_locale = (params[:content_locale] || I18n.default_locale).to_sym
32
+
33
+ locales = I18n.available_locales.map do |s|
34
+ text = s.to_s.upcase
35
+ text << "*" if obj && !obj.translated_locales.include?(s)
36
+ content_tag :li, link_to(text, url_for(:content_locale => s)), :class => current_locale == s ? 'active' : nil
37
+ end
38
+
39
+ content_tag :ul, locales.join("").html_safe, :class => 'nav nav-pills'
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,12 @@
1
+ module AppFrame::PaginationHelper
2
+
3
+ def page_range
4
+ return nil if count == 0
5
+
6
+ range_start = (page - 1) * per_page + 1
7
+ range_end = (page) * per_page
8
+ range_end = count if range_end > count
9
+
10
+ "<div class='page-range'>Displaying <strong>#{range_start} - #{range_end}</strong> of <strong>#{count}</strong> in total</div>".html_safe
11
+ end
12
+ end
@@ -0,0 +1,63 @@
1
+ module AppFrame::ResourcesHelper
2
+
3
+ def collection?
4
+ !!collection
5
+ rescue NameError
6
+ false
7
+ end
8
+
9
+ def resource?
10
+ !!resource
11
+ rescue NameError, ActiveRecord::RecordNotFound
12
+ false
13
+ end
14
+
15
+ def resource_name
16
+ if resource_class
17
+ resource_class.model_name.human
18
+ else
19
+ controller_name
20
+ end
21
+ end
22
+
23
+ def parent?
24
+ controller.respond_to?(:parent?) && controller.send(:parent?)
25
+ end
26
+
27
+ def parent_resource_class
28
+ parent.class
29
+ end
30
+
31
+ def parent_resource_name
32
+ parent_resource_class.model_name.human
33
+ end
34
+
35
+ def controller_namespaces
36
+ result = controller.class.to_s.split('::')
37
+ result.pop
38
+ result.map(&:underscore)
39
+ end
40
+
41
+ def namespaced(string)
42
+ if controller_namespaces.any?
43
+ File.join(controller_namespaces, string)
44
+ else
45
+ string
46
+ end
47
+ end
48
+
49
+ def resource_path_array
50
+ result = controller_namespaces
51
+ result << parent if parent?
52
+ result << resource
53
+ end
54
+
55
+ def parent_collection_url
56
+ return unless parent?
57
+
58
+ result = controller_namespaces
59
+ result << parent_resource_name.underscore.pluralize
60
+ polymorphic_url(result)
61
+ end
62
+
63
+ end
@@ -0,0 +1,94 @@
1
+ module AppFrame::ScopesHelper
2
+ # return all scopes configured in the controller
3
+ def scopes
4
+ controller.class.scopes_configuration || {}
5
+ end
6
+
7
+ def default_scopes
8
+ @default_scopes ||= scopes.inject({}) do |result, element|
9
+ result[element.first] = element.last if element.last[:default] == true
10
+ result
11
+ end
12
+ end
13
+
14
+ # return only the boolean scopes
15
+ def boolean_scopes
16
+ @boolean_scopes ||= scopes.inject({}) do |result, element|
17
+ result[element.first] = element.last if element.last[:type] == :boolean
18
+ result
19
+ end
20
+ end
21
+
22
+ # return only the filter (non boolean) scopes
23
+ def filter_scopes
24
+ @filter_scopes ||= scopes.inject({}) do |result, element|
25
+ result[element.first] = element.last if element.last[:type] != :boolean
26
+ result
27
+ end
28
+ end
29
+
30
+ def current_boolean_scopes
31
+ @current_boolean_scopes ||= current_scopes.inject({}) do |result, element|
32
+ result[element.first] = element.last if boolean_scopes.keys.include?(element.first)
33
+ result
34
+ end
35
+ end
36
+
37
+ def current_filter_scopes
38
+ @current_filter_scopes ||= current_scopes.inject({}) do |result, element|
39
+ result[element.first] = element.last if filter_scopes.keys.include?(element.first)
40
+ result
41
+ end
42
+ end
43
+
44
+ # create a link to a scope (or no scopes), wrapped in a list item
45
+ def scope_link(scope = nil)
46
+ if scope
47
+ as = scope[:as]
48
+ name = as.to_s.humanize
49
+ else
50
+ as = nil
51
+ name = "All"
52
+ end
53
+
54
+ link = current_filter_scopes.dup
55
+
56
+ if as
57
+ unless scope[:default]
58
+ link[as] = true
59
+ default_scopes.each { |dn, ds| link[ds[:as]] = false }
60
+ end
61
+
62
+ active = current_boolean_scopes.keys.include?(as)
63
+ else
64
+ active = current_boolean_scopes.empty?
65
+ end
66
+
67
+ # name = "#{name}: #{scope_count(scope)}"
68
+
69
+ content_tag(:li, link_to(name, link), :class => active ? 'active' : nil)
70
+ end
71
+
72
+ def scope_count(scope)
73
+ chain = controller.end_of_association_chain
74
+ chain = chain.send(scope) if scope
75
+ chain.count
76
+ end
77
+
78
+ # craete a navigation for all the boolean scopes
79
+ def scope_nav
80
+ return unless boolean_scopes.count > 0
81
+
82
+ if default_scopes.any?
83
+ result = []
84
+ else
85
+ result = [scope_link]
86
+ end
87
+
88
+ boolean_scopes.each do |name, s|
89
+ result << scope_link(s)
90
+ end
91
+
92
+ content_tag :ul, result.join("\n").html_safe, :class => 'nav nav-pills'
93
+ end
94
+ end
@@ -0,0 +1,8 @@
1
+ module AppFrame::SelectHelper
2
+ def prepopulate(association)
3
+ return [].to_json unless association
4
+
5
+ association = [association] if association.is_a?(ActiveRecord::Base)
6
+ association.map(&:to_token_hash).to_json
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ module AppFrame::TreeNavHelper
2
+ def tree_nav(node)
3
+ result = []
4
+ result << tree_nav_link("&uarr;", left_admin_section_page_path(parent, node), node.left_sibling)
5
+ result << tree_nav_link("&darr;", right_admin_section_page_path(parent, node), node.right_sibling)
6
+ result << tree_nav_link("&rarr;", down_admin_section_page_path(parent, node), node.left_sibling)
7
+ result << tree_nav_link("&larr;", up_admin_section_page_path(parent, node), node.parent)
8
+ result << link_to("Edit", edit_admin_section_page_path(parent, node))
9
+ yield result if block_given?
10
+ result << link_to("Delete", admin_section_page_path(parent, node), :method => :delete)
11
+ content_tag :span, result.join('').html_safe, :class => 'tree_nav'
12
+ end
13
+
14
+ def tree_nav_link(text, link, condition = true)
15
+ condition ? link_to(text.html_safe, link) : content_tag(:span, text.html_safe)
16
+ end
17
+
18
+ end
@@ -0,0 +1,44 @@
1
+ class MenuItem
2
+ attr_reader :name, :path, :namespace
3
+
4
+ def initialize(namespace, path)
5
+ @namespace = namespace
6
+ @path = path
7
+ @name = path.humanize
8
+ end
9
+
10
+ def url
11
+ "/#{namespace}/#{path}"
12
+ end
13
+ end
14
+
15
+
16
+ class Menu
17
+ attr_reader :namespace
18
+
19
+ def initialize(namespace)
20
+ @namespace = namespace
21
+ end
22
+
23
+ def routes
24
+ @routes ||= Rails.application.routes.routes
25
+ end
26
+
27
+ def menu_routes
28
+ @menu_routes ||= routes.select { |r| r.defaults[:action] == 'index' }
29
+ end
30
+
31
+ def specs
32
+ @specs ||= menu_routes.map { |r| r.path.spec }.uniq
33
+ end
34
+
35
+ def menu_items
36
+ @menu_items = []
37
+ specs.each do |s|
38
+ matches = /\/#{@namespace}\/(\w*)/.match(s.to_s)
39
+ @menu_items << matches[1] if matches
40
+ end
41
+ @menu_items.uniq.map { |i| MenuItem.new(@namespace, i) }
42
+ end
43
+
44
+ end
@@ -0,0 +1,4 @@
1
+ class Settings < Settingslogic
2
+ source "#{Rails.root}/config/application.yml"
3
+ namespace Rails.env
4
+ end
@@ -0,0 +1,8 @@
1
+ = page_header "Resend confirmation instructions"
2
+
3
+ = simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f|
4
+ = f.error_notification
5
+
6
+ = f.input :email, :required => true
7
+
8
+ = f.button :submit, "Resend confirmation instructions", :class => 'btn'
@@ -0,0 +1,13 @@
1
+ = page_header "Change your password"
2
+
3
+ = simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f|
4
+ = f.error_notification
5
+
6
+ = f.input :reset_password_token, :as => :hidden
7
+ = f.full_error :reset_password_token
8
+
9
+ = f.input :password, :label => "New password", :required => true
10
+ = f.input :password_confirmation, :label => "Confirm your new password", :required => true
11
+
12
+ = f.button :submit, "Change my password"
13
+
@@ -0,0 +1,8 @@
1
+ =page_header "Forgot your password?"
2
+
3
+ = simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f|
4
+ = f.error_notification
5
+
6
+ = f.input :email, :required => true
7
+
8
+ = f.button :submit, "Send", :class => 'btn'
@@ -0,0 +1,19 @@
1
+ = page_header "Edit #{resource_name.to_s.humanize}"
2
+
3
+ = simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f|
4
+ = f.error_notification
5
+
6
+ = f.input :email, :required => true, :autofocus => true
7
+ = f.input :password, :hint => "leave it blank if you don't want to change it", :required => false
8
+ = f.input :password_confirmation, :required => false
9
+ = f.input :current_password, :hint => "we need your current password to confirm your changes", :required => true
10
+
11
+ = f.button :submit, "Update", :class => 'btn'
12
+
13
+ %h3 Cancel my account<
14
+
15
+ %p
16
+ Unhappy?
17
+ = link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete
18
+
19
+ = link_to "Back", :back, :class => 'btn'
@@ -0,0 +1,10 @@
1
+ = page_header "Sign up"
2
+
3
+ = simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f|
4
+ = f.error_notification
5
+
6
+ = f.input :email, :required => true, :autofocus => true
7
+ = f.input :password, :required => true
8
+ = f.input :password_confirmation, :required => true
9
+
10
+ = f.button :submit, "Sign up", :class => 'btn'
@@ -0,0 +1,12 @@
1
+ =page_header "Sign in"
2
+
3
+ = simple_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
4
+ = f.input :email, :required => false, :autofocus => true
5
+ = f.input :password, :required => false
6
+
7
+ - if devise_mapping.rememberable?
8
+ = f.label :remember_me, :class => 'checkbox' do
9
+ = f.check_box :remember_me
10
+ Remember me
11
+
12
+ = f.button :submit, "Sign in", :class => 'btn'