effective_pages 2.0.8 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +11 -70
  4. data/app/controllers/admin/menus_controller.rb +6 -48
  5. data/app/controllers/admin/pages_controller.rb +11 -102
  6. data/app/controllers/effective/pages_controller.rb +14 -8
  7. data/app/datatables/effective_pages_datatable.rb +20 -2
  8. data/app/datatables/effective_pages_menu_datatable.rb +38 -0
  9. data/app/helpers/effective_menus_helper.rb +31 -136
  10. data/app/helpers/effective_pages_helper.rb +4 -2
  11. data/app/models/effective/page.rb +65 -22
  12. data/app/views/admin/menus/index.html.haml +10 -2
  13. data/app/views/admin/pages/_form.html.haml +20 -25
  14. data/app/views/admin/pages/_form_access.html.haml +10 -0
  15. data/app/views/admin/pages/_form_content.html.haml +3 -0
  16. data/app/views/admin/pages/_form_menu.html.haml +16 -0
  17. data/app/views/admin/pages/_form_page.html.haml +31 -0
  18. data/app/views/admin/pages/_rich_text_areas.html.haml +2 -0
  19. data/app/views/effective/pages/_menu.html.haml +20 -0
  20. data/config/effective_pages.rb +9 -38
  21. data/config/routes.rb +6 -9
  22. data/db/migrate/01_create_effective_pages.rb.erb +12 -30
  23. data/lib/effective_pages.rb +17 -61
  24. data/lib/effective_pages/version.rb +1 -1
  25. data/lib/generators/effective_pages/install_generator.rb +1 -1
  26. data/lib/generators/templates/example.html.haml +4 -5
  27. data/lib/tasks/effective_pages_tasks.rake +1 -1
  28. metadata +11 -38
  29. data/app/datatables/effective_menus_datatable.rb +0 -16
  30. data/app/helpers/effective_breadcrumbs_helper.rb +0 -41
  31. data/app/helpers/effective_menus_admin_helper.rb +0 -8
  32. data/app/models/effective/access_denied.rb +0 -17
  33. data/app/models/effective/menu.rb +0 -172
  34. data/app/models/effective/menu_item.rb +0 -78
  35. data/app/views/admin/menu_items/_actions.html.haml +0 -4
  36. data/app/views/admin/menu_items/_expand.html.haml +0 -2
  37. data/app/views/admin/menu_items/_item.html.haml +0 -13
  38. data/app/views/admin/menu_items/_new.html.haml +0 -3
  39. data/app/views/admin/menus/_actions.html.haml +0 -2
  40. data/app/views/admin/menus/_form.html.haml +0 -4
  41. data/app/views/admin/menus/edit.html.haml +0 -3
  42. data/app/views/admin/menus/new.html.haml +0 -3
  43. data/app/views/admin/menus/show.html.haml +0 -39
  44. data/app/views/admin/pages/_actions.html.haml +0 -7
  45. data/app/views/admin/pages/_roles.html.haml +0 -1
  46. data/app/views/admin/pages/edit.html.haml +0 -3
  47. data/app/views/admin/pages/index.html.haml +0 -6
  48. data/app/views/admin/pages/new.html.haml +0 -3
@@ -1,8 +0,0 @@
1
- module EffectiveMenusAdminHelper
2
-
3
- def visible_badge(menu_item, stack, comparator)
4
- visible = comparator.call(menu_item) && stack.all? { |parent_menu_item| parent_menu_item.lft == 1 || comparator.call(parent_menu_item) }
5
- content_tag(:span, (visible ? 'YES'.freeze : 'NO'.freeze), :class => "label label-#{(visible ? 'primary' : 'warning')}")
6
- end
7
-
8
- end
@@ -1,17 +0,0 @@
1
- unless defined?(Effective::AccessDenied)
2
- module Effective
3
- class AccessDenied < StandardError
4
- attr_reader :action, :subject
5
-
6
- def initialize(message = nil, action = nil, subject = nil)
7
- @message = message
8
- @action = action
9
- @subject = subject
10
- end
11
-
12
- def to_s
13
- @message || I18n.t(:'unauthorized.default', :default => 'Access Denied')
14
- end
15
- end
16
- end
17
- end
@@ -1,172 +0,0 @@
1
- module Effective
2
- class Menu < ActiveRecord::Base
3
- has_many :menu_items, dependent: :delete_all
4
-
5
- self.table_name = EffectivePages.menus_table_name.to_s
6
-
7
- # structure do
8
- # title :string
9
- # timestamps
10
- # end
11
-
12
- validates :title, presence: true, uniqueness: true, length: { maximum: 255 }
13
-
14
- accepts_nested_attributes_for :menu_items, allow_destroy: true
15
-
16
- before_save do
17
- if self.menu_items.find { |menu_item| menu_item.lft == 1 }.blank?
18
- menu_items.build(title: 'Home', url: '/', lft: 1, rgt: 2)
19
- end
20
- end
21
-
22
- def self.update_from_effective_regions!(params)
23
- Effective::Menu.transaction do
24
- (params || {}).each do |menu_id, attributes|
25
- menu = Effective::Menu.includes(:menu_items).find(menu_id)
26
- menu.menu_items.delete_all
27
-
28
- right = -1
29
-
30
- attributes[:menu_items_attributes].each do |_, atts|
31
- atts[:menuable_type] = 'Effective::Page' if atts[:menuable_type].blank?
32
- atts.delete(:id)
33
- right = [atts[:rgt].to_i, right].max
34
- end
35
-
36
- menu.attributes = attributes
37
-
38
- # So when we render the menu, we don't include the Root/Home item.
39
- # It has a left of 1 and a right of max(items.right)
40
- root_node = menu.menu_items.find { |menu_item| menu_item.lft == 1 }
41
- root_node ||= menu.menu_items.build(title: 'Home', url: '/', lft: 1, rgt: 2)
42
- root_node.rgt = right + 1
43
-
44
- menu.save!
45
- end
46
- end
47
- end
48
-
49
- def to_s
50
- self[:title] || 'New Menu'
51
- end
52
-
53
- def contains?(obj)
54
- menu_items.find { |menu_item| menu_item.url == obj || menu_item.menuable == obj }.present?
55
- end
56
-
57
- # This is the entry point to the DSL method for creating menu items
58
- def build(&block)
59
- raise 'build must be called with a block' if !block_given?
60
-
61
- root = menu_items.build(title: 'Home', url: '/', lft: 1, rgt: 2)
62
- root.parent = true
63
- instance_exec(&block) # A call to dropdown or item
64
- root.rgt = menu_items.map(&:rgt).max
65
- self
66
- end
67
-
68
- private
69
-
70
- def dropdown(title, options = {}, &block)
71
- raise 'dropdown must be called with a block' if !block_given?
72
- raise 'dropdown menu_items may not have a URL' if options.kind_of?(String) || options.kind_of?(Symbol)
73
- raise 'dropdown second parameter expects a Hash' unless options.kind_of?(Hash)
74
-
75
- prev_item = menu_items.last
76
-
77
- if prev_item.parent == true # This came from root or dropdown
78
- lft = prev_item.lft + 1 # Go down. from lft
79
- rgt = prev_item.rgt + 1
80
- else
81
- lft = prev_item.rgt + 1 # Go accross. from rgt
82
- rgt = prev_item.rgt + 2
83
- end
84
-
85
- # Make room for new item by shifting everything after me up by 2
86
- menu_items.each do |item|
87
- item.rgt = (item.rgt + 2) if item.rgt > (lft - 1)
88
- item.lft = (item.lft + 2) if item.lft > (lft - 1)
89
- end
90
-
91
- atts = build_menu_item_attributes(title, '', options).merge({:lft => lft, :rgt => rgt})
92
-
93
- dropdown = menu_items.build(atts)
94
- dropdown.parent = true
95
-
96
- instance_exec(&block)
97
-
98
- # Level up
99
- dropdown.rgt = menu_items.last.rgt + 1 # Level up
100
- dropdown.parent = false
101
- menu_items << menu_items.delete(dropdown) # Put myself on the end of the array
102
- end
103
-
104
- # The URL parameter can be:
105
- # - an Effective::Page object
106
- # - the symbol :divider
107
- # - a symbol or string that ends with _path
108
- # - or a string that is the url
109
-
110
- def item(title, url = '#', options = {})
111
- raise 'item third parameter expects a Hash' unless options.kind_of?(Hash)
112
-
113
- prev_item = menu_items.last
114
-
115
- if prev_item.parent == true # This came from root or dropdown
116
- lft = prev_item.lft + 1 # Go down. from lft
117
- rgt = prev_item.rgt + 1
118
- else
119
- lft = prev_item.rgt + 1 # Go accross, from rgt
120
- rgt = prev_item.rgt + 2
121
- end
122
-
123
- menu_items.each do |item|
124
- item.rgt = (item.rgt + 2) if item.rgt > (lft - 1)
125
- item.lft = (item.lft + 2) if item.lft > (lft - 1)
126
- end
127
-
128
- atts = build_menu_item_attributes(title, url, options).merge({:lft => lft, :rgt => rgt})
129
-
130
- menu_items.build(atts)
131
- end
132
-
133
- def divider(options = {})
134
- item(:divider, :divider, options)
135
- end
136
-
137
- def build_menu_item_attributes(title, url, options)
138
- options[:roles_mask] ||= 0 if (options.delete(:signed_in) || options.delete(:private))
139
- options[:roles_mask] ||= -1 if (options.delete(:signed_out) || options.delete(:guest))
140
-
141
- if options[:roles]
142
- options[:roles_mask] = EffectiveRoles.roles_mask_for(options.delete(:roles))
143
- end
144
-
145
- options[:classes] = options.delete(:class)
146
-
147
- if title == :divider || url == :divider || options[:divider] == true
148
- options[:title] = 'divider'
149
- options[:special] = 'divider'
150
- elsif title.kind_of?(Effective::Page)
151
- options[:title] = title.title
152
- options[:menuable] = title
153
- options[:url] = '#'
154
- elsif url.kind_of?(Effective::Page)
155
- options[:title] = title.presence || url.title
156
- options[:menuable] = url
157
- options[:url] = '#'
158
- elsif url.to_s.end_with?('_path')
159
- options[:title] = title
160
- options[:special] = url
161
- else
162
- options[:title] = title
163
- options[:url] = url
164
- end
165
-
166
- options
167
- end
168
-
169
-
170
- end
171
-
172
- end
@@ -1,78 +0,0 @@
1
- module Effective
2
- class MenuItem < ActiveRecord::Base
3
- attr_accessor :parent # This gets set on the Root node and a node created by Dropdown, so the item function knows whether to go down or to go accross
4
-
5
- belongs_to :menu, inverse_of: :menu_items
6
- belongs_to :menuable, polymorphic: true # Optionaly belong to an object
7
-
8
- self.table_name = EffectivePages.menu_items_table_name.to_s
9
-
10
- acts_as_role_restricted
11
-
12
- # structure do
13
- # title :string
14
-
15
- # url :string
16
- # special :string # divider / search / *_path
17
-
18
- # classes :string
19
- # new_window :boolean
20
- # roles_mask :integer # 0 is going to mean logged in, -1 is going to mean public, > 0 will be future implementation of roles masking
21
-
22
- # lft :integer
23
- # rgt :integer
24
- # end
25
-
26
- validates :title, presence: true, length: { maximum: 255 }
27
- validates :url, length: { maximum: 255 }
28
- validates :special, length: { maximum: 255 }
29
- validates :classes, length: { maximum: 255 }
30
- validates :new_window, inclusion: { in: [true, false] }
31
-
32
- validates :lft, presence: true
33
- validates :rgt, presence: true
34
-
35
- default_scope -> { includes(:menuable).order(:lft) }
36
-
37
- def leaf?
38
- (rgt.to_i - lft.to_i) == 1
39
- end
40
-
41
- def dropdown?
42
- !leaf?
43
- end
44
-
45
- def divider?
46
- leaf? && special == 'divider'
47
- end
48
-
49
- # For now it's just logged in or not?
50
- # This will work with effective_roles one day...
51
- def visible_for?(user)
52
- can_view_page = (
53
- if dropdown?
54
- true
55
- elsif menuable.kind_of?(Effective::Page)
56
- menuable.roles_permit?(user)
57
- else
58
- true
59
- end
60
- )
61
-
62
- can_view_menu_item = (
63
- if roles_mask == nil
64
- true
65
- elsif roles_mask == -1 # Am I logged out?
66
- user.blank?
67
- elsif roles_mask == 0 # Am I logged in?
68
- user.present?
69
- else
70
- roles_permit?(user)
71
- end
72
- )
73
-
74
- can_view_page && can_view_menu_item
75
- end
76
-
77
- end
78
- end
@@ -1,4 +0,0 @@
1
- .actions
2
- %span.add-item.glyphicon.glyphicon-plus-sign
3
- %span.remove-item.glyphicon.glyphicon-trash
4
-
@@ -1,2 +0,0 @@
1
- %ul.dropdown-menu
2
- %li.effective-menu-expand &nbsp;
@@ -1,13 +0,0 @@
1
- .menu-item
2
- = form.fields_for :menu_items, item do |f|
3
- = f.hidden_field :title, :autocomplete => 'off'
4
- = f.hidden_field :menuable_id, :autocomplete => 'off'
5
- = f.hidden_field :menuable_type, :autocomplete => 'off'
6
- = f.hidden_field :url, :autocomplete => 'off'
7
- = f.hidden_field :special, :autocomplete => 'off'
8
- = f.hidden_field :new_window, :autocomplete => 'off'
9
- = f.hidden_field :classes, :autocomplete => 'off'
10
- = f.hidden_field :roles_mask, :autocomplete => 'off'
11
- = f.hidden_field :lft, :autocomplete => 'off'
12
- = f.hidden_field :rgt, :autocomplete => 'off'
13
- = f.hidden_field :_destroy, :autocomplete => 'off'
@@ -1,3 +0,0 @@
1
- %li.new-item
2
- %a{:href => ''}
3
- = render :partial => 'admin/menu_items/item', :locals => {:item => item, :form => form}
@@ -1,2 +0,0 @@
1
- = dropdown(variation: :dropleft) do
2
- = dropdown_link_to 'Settings', effective_pages.admin_menu_path(menu)
@@ -1,4 +0,0 @@
1
- = effective_form_with(model: menu, url: (menu.persisted? ? effective_pages.admin_menu_path(menu) : effective_pages.admin_menus_path)) do |f|
2
- = f.text_field :title, hint: 'Give this menu a title'
3
-
4
- = f.submit
@@ -1,3 +0,0 @@
1
- %h1.effective-admin-heading= @page_title
2
-
3
- = render partial: 'form', as: :menu, object: @menu
@@ -1,3 +0,0 @@
1
- %h1.effective-admin-heading= @page_title
2
-
3
- = render partial: 'form', as: :menu, object: @menu
@@ -1,39 +0,0 @@
1
- %h1.effective-admin-heading= @page_title
2
-
3
- - if defined?(EffectiveRegions)
4
- .row.effective-admin-actions
5
- .col-sm-6
6
- %p
7
- All menu editing may be done from the fullscreen editor. Just drag and drop menu items.
8
- .col-sm-6
9
- %p.text-right
10
- = link_to "Edit #{@menu}", effective_regions.edit_path('/'), class: 'btn btn-primary', 'data-no-turbolink': true, 'data-turbolinks': false, target: '_blank'
11
-
12
- - if defined?(EffectiveRoles)
13
- %h2 Menu Items
14
-
15
- - if @menu.menu_items.length > 1
16
- %table.table
17
- %thead
18
- %th Menu Item
19
- %th.text-center Public
20
- %th.text-center Signed In
21
- - EffectiveRoles.roles.each do |role|
22
- %th.text-center= ":#{role}"
23
-
24
- %tbody
25
- - stack = [@menu.menu_items.first]
26
- - @menu.menu_items.each_with_index do |menu_item, index|
27
- - next if index == 0
28
- - stack.pop while menu_item.rgt > stack.last.rgt if stack.size > 1
29
- %tr
30
- %td
31
- = ("&nbsp;&nbsp;" * (stack.size-1)).html_safe
32
- = (menu_item.divider? ? ':divider' : menu_item.title)
33
- %td.text-center= visible_badge(menu_item, stack, Proc.new { |item| item.roles_mask == nil || item.roles_mask == -1 })
34
- %td.text-center= visible_badge(menu_item, stack, Proc.new { |item| item.roles_mask == nil || item.roles_mask == 0 })
35
- - EffectiveRoles.roles.each do |role|
36
- %td.text-center= visible_badge(menu_item, stack, Proc.new { |item| item.visible_for?(role) })
37
- - stack.push(menu_item)
38
- - else
39
- %p No menu items.
@@ -1,7 +0,0 @@
1
- = dropdown(variation: :dropleft) do
2
- = dropdown_link_to 'Edit', effective_pages.edit_admin_page_path(page)
3
- = dropdown_link_to 'Edit Content', effective_regions.edit_path(page), 'data-no-turbolink': true, 'data-turbolinks': false, target: '_blank'
4
- = dropdown_link_to 'View', effective_pages.page_path(page), 'data-no-turbolink': true, 'data-turbolinks': false, target: '_blank'
5
-
6
- = dropdown_link_to "Delete #{page}", effective_pages.admin_page_path(page),
7
- data: { method: :delete, confirm: "Really delete #{page}?" }
@@ -1 +0,0 @@
1
- = f.checks :roles, EffectiveRoles.roles_collection(f.object), hint: '* leave blank for a regular public page that anyone can view'
@@ -1,3 +0,0 @@
1
- %h1.effective-admin-heading= @page_title
2
-
3
- = render partial: 'form', as: :page, object: @page
@@ -1,6 +0,0 @@
1
- %h1.effective-admin-heading= @page_title
2
-
3
- %p.text-right.effective-admin-actions
4
- = link_to 'New Page', effective_pages.new_admin_page_path, class: 'btn btn-primary'
5
-
6
- = render_datatable(@datatable)
@@ -1,3 +0,0 @@
1
- %h1.effective-admin-heading= @page_title
2
-
3
- = render partial: 'form', as: :page, object: @page