effective_pages 2.0.8 → 3.0.2

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.
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