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.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +11 -70
- data/app/controllers/admin/menus_controller.rb +6 -48
- data/app/controllers/admin/pages_controller.rb +11 -102
- data/app/controllers/effective/pages_controller.rb +14 -8
- data/app/datatables/effective_pages_datatable.rb +20 -2
- data/app/datatables/effective_pages_menu_datatable.rb +38 -0
- data/app/helpers/effective_menus_helper.rb +31 -136
- data/app/helpers/effective_pages_helper.rb +4 -2
- data/app/models/effective/page.rb +65 -22
- data/app/views/admin/menus/index.html.haml +10 -2
- data/app/views/admin/pages/_form.html.haml +20 -25
- data/app/views/admin/pages/_form_access.html.haml +10 -0
- data/app/views/admin/pages/_form_content.html.haml +3 -0
- data/app/views/admin/pages/_form_menu.html.haml +16 -0
- data/app/views/admin/pages/_form_page.html.haml +31 -0
- data/app/views/admin/pages/_rich_text_areas.html.haml +2 -0
- data/app/views/effective/pages/_menu.html.haml +20 -0
- data/config/effective_pages.rb +9 -38
- data/config/routes.rb +6 -9
- data/db/migrate/01_create_effective_pages.rb.erb +12 -30
- data/lib/effective_pages.rb +17 -61
- data/lib/effective_pages/version.rb +1 -1
- data/lib/generators/effective_pages/install_generator.rb +1 -1
- data/lib/generators/templates/example.html.haml +4 -5
- data/lib/tasks/effective_pages_tasks.rake +1 -1
- metadata +11 -38
- data/app/datatables/effective_menus_datatable.rb +0 -16
- data/app/helpers/effective_breadcrumbs_helper.rb +0 -41
- data/app/helpers/effective_menus_admin_helper.rb +0 -8
- data/app/models/effective/access_denied.rb +0 -17
- data/app/models/effective/menu.rb +0 -172
- data/app/models/effective/menu_item.rb +0 -78
- data/app/views/admin/menu_items/_actions.html.haml +0 -4
- data/app/views/admin/menu_items/_expand.html.haml +0 -2
- data/app/views/admin/menu_items/_item.html.haml +0 -13
- data/app/views/admin/menu_items/_new.html.haml +0 -3
- data/app/views/admin/menus/_actions.html.haml +0 -2
- data/app/views/admin/menus/_form.html.haml +0 -4
- data/app/views/admin/menus/edit.html.haml +0 -3
- data/app/views/admin/menus/new.html.haml +0 -3
- data/app/views/admin/menus/show.html.haml +0 -39
- data/app/views/admin/pages/_actions.html.haml +0 -7
- data/app/views/admin/pages/_roles.html.haml +0 -1
- data/app/views/admin/pages/edit.html.haml +0 -3
- data/app/views/admin/pages/index.html.haml +0 -6
- 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,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,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
|
-
= (" " * (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'
|