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