effective_pages 3.3.2 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -4
- data/app/controllers/admin/carousel_items_controller.rb +13 -0
- data/app/controllers/admin/page_banners_controller.rb +13 -0
- data/app/datatables/effective_carousel_items_datatable.rb +35 -0
- data/app/datatables/effective_page_banners_datatable.rb +25 -0
- data/app/datatables/effective_page_sections_datatable.rb +1 -1
- data/app/datatables/effective_pages_datatable.rb +2 -0
- data/app/helpers/effective_carousels_helper.rb +23 -0
- data/app/helpers/effective_page_banners_helper.rb +23 -0
- data/app/models/effective/carousel_item.rb +73 -0
- data/app/models/effective/page.rb +36 -26
- data/app/models/effective/page_banner.rb +49 -0
- data/app/models/effective/page_section.rb +5 -6
- data/app/views/admin/carousel_items/_form.html.haml +7 -0
- data/app/views/admin/carousel_items/_form_carousel_item.html.haml +21 -0
- data/app/views/admin/carousel_items/index.html.haml +11 -0
- data/app/views/admin/page_banners/_form.html.haml +7 -0
- data/app/views/admin/page_banners/_form_page_banner.html.haml +12 -0
- data/app/views/admin/page_sections/_form_page_section.html.haml +3 -4
- data/app/views/admin/pages/_form_page.html.haml +11 -0
- data/app/views/effective/carousels/_carousel.html.haml +27 -0
- data/config/effective_pages.rb +12 -0
- data/config/routes.rb +2 -0
- data/db/migrate/01_create_effective_pages.rb.erb +32 -5
- data/lib/effective_pages/engine.rb +2 -0
- data/lib/effective_pages/version.rb +1 -1
- data/lib/effective_pages.rb +20 -2
- data/lib/generators/effective_pages/install_generator.rb +3 -0
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87905a09b84f0b8cf820024a81ea1066e5f213cd8e6b445f7cafc2d24eb86398
|
4
|
+
data.tar.gz: 7bcd83be6059d46ee284e80420683eeb273df7d2f3788b1b84e0b5c6bb06d1c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3ec4c9bb169cba79542e2d7d5d6db7d2e04bd3cc69b6e46848542e78cbd7cae0d57b8976e812be8309bb6116cfc6b9745e85f960bc8a8b95876c48b72f87430
|
7
|
+
data.tar.gz: be88b345621ea1f0ee7f31e07a08a44392be1a34706463551b9548be2730bcf6fa77a698ace3ac0237af76290a310639a5521cce745bd8d602c8b715c4c1476f
|
data/README.md
CHANGED
@@ -172,12 +172,17 @@ All authorization checks are handled via the effective_resources gem found in th
|
|
172
172
|
The permissions you actually want to define are as follows (using CanCan):
|
173
173
|
|
174
174
|
```ruby
|
175
|
-
can
|
175
|
+
can :index, Effective::Page
|
176
|
+
can(:show, Effective::Page) { |page| page.roles_permit?(user) }
|
176
177
|
|
177
178
|
if user.is?(:admin)
|
178
|
-
can :
|
179
|
-
|
180
|
-
can
|
179
|
+
can :admin, :effective_pages
|
180
|
+
|
181
|
+
can(crud, Efective::Page)
|
182
|
+
can(crud - [:new, :create, :destroy], Effective::PageSection)
|
183
|
+
|
184
|
+
can(crud - [:destroy], Effective::PageBanner)
|
185
|
+
can(:destroy, Effective::PageBanner) { |pb| pb.pages.length == 0 }
|
181
186
|
end
|
182
187
|
```
|
183
188
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Admin
|
2
|
+
class CarouselItemsController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_pages) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
def permitted_params
|
9
|
+
params.require(:effective_carousel_item).permit!
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Admin
|
2
|
+
class PageBannersController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_pages) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
def permitted_params
|
9
|
+
params.require(:effective_page_banner).permit!
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class EffectiveCarouselItemsDatatable < Effective::Datatable
|
2
|
+
|
3
|
+
datatable do
|
4
|
+
reorder :position
|
5
|
+
|
6
|
+
col :id, visible: false
|
7
|
+
col :updated_at, visible: false
|
8
|
+
|
9
|
+
col :carousel
|
10
|
+
col :title
|
11
|
+
|
12
|
+
col :title
|
13
|
+
col :rich_text_body, label: 'Content'
|
14
|
+
|
15
|
+
col :file, label: 'Image' do |carousel_item|
|
16
|
+
image_tag(carousel_item.file, style: 'max-height: 100px;')
|
17
|
+
end
|
18
|
+
|
19
|
+
col :link_label, visible: false
|
20
|
+
col :link_url, visible: false
|
21
|
+
col :caption, visible: false
|
22
|
+
|
23
|
+
actions_col
|
24
|
+
end
|
25
|
+
|
26
|
+
collection do
|
27
|
+
Effective::CarouselItem.deep.all.where(carousel: carousel)
|
28
|
+
end
|
29
|
+
|
30
|
+
def carousel
|
31
|
+
carousel = EffectivePages.carousels.find { |carousel| carousel.to_s == attributes[:carousel].to_s }
|
32
|
+
carousel || raise("unexpected carousel: #{attributes[:carousel] || 'none'}")
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class EffectivePageBannersDatatable < Effective::Datatable
|
2
|
+
|
3
|
+
datatable do
|
4
|
+
order :name, :asc
|
5
|
+
length :all
|
6
|
+
|
7
|
+
col :id, visible: false
|
8
|
+
col :updated_at, visible: false
|
9
|
+
|
10
|
+
col :name
|
11
|
+
|
12
|
+
col :file
|
13
|
+
col :caption
|
14
|
+
|
15
|
+
col :rich_text_body, visible: false
|
16
|
+
col :pages
|
17
|
+
|
18
|
+
actions_col
|
19
|
+
end
|
20
|
+
|
21
|
+
collection do
|
22
|
+
Effective::PageBanner.deep.all
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -33,6 +33,8 @@ class EffectivePagesDatatable < Effective::Datatable
|
|
33
33
|
col :menu_parent, search: { collection: admin_menu_parent_collection(), grouped: true }
|
34
34
|
col :menu_position, visible: false
|
35
35
|
|
36
|
+
col :page_banner
|
37
|
+
|
36
38
|
col :authenticate_user, visible: false
|
37
39
|
col :roles, visible: false
|
38
40
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module EffectiveCarouselsHelper
|
3
|
+
|
4
|
+
def render_carousel(name, options = {}, &block)
|
5
|
+
name = name.to_s
|
6
|
+
carousel = Array(EffectivePages.carousels).find { |carousel| carousel.to_s == name }
|
7
|
+
|
8
|
+
if carousel.blank?
|
9
|
+
raise("unable to find carousel #{name}. Please add it to config/initializers/effective_pages.rb")
|
10
|
+
end
|
11
|
+
|
12
|
+
carousel_items = Effective::CarouselItem.sorted.where(carousel: carousel)
|
13
|
+
return if carousel_items.blank?
|
14
|
+
|
15
|
+
if block_given?
|
16
|
+
yield(carousel_items); nil
|
17
|
+
else
|
18
|
+
render('effective/carousels/carousel', carousel: carousel, carousel_items: carousel_items, carousel_options: options)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EffectivePageBannersHelper
|
4
|
+
|
5
|
+
def render_page_banner(page, opts = {}, &block)
|
6
|
+
raise('expected a page') unless page.kind_of?(Effective::Page)
|
7
|
+
|
8
|
+
# Do nothing if page.banner is false
|
9
|
+
return unless page.banner?
|
10
|
+
|
11
|
+
page_banner = page.page_banner
|
12
|
+
page_banner ||= Effective::PageBanner.random.first if page.banner_random?
|
13
|
+
|
14
|
+
raise("unable to find page banner for page #{page}") unless page_banner.present?
|
15
|
+
|
16
|
+
if block_given?
|
17
|
+
yield(page_banner); nil
|
18
|
+
else
|
19
|
+
image_tag(page_banner.file, alt: page_banner.caption, **opts)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Carousels are configured in the config/initializers/effective_pages.rb
|
2
|
+
# Kind of like a menu, they are predefined and cannot be edited by admin
|
3
|
+
# The carousel items belong to a carousel through the string field
|
4
|
+
module Effective
|
5
|
+
class CarouselItem < ActiveRecord::Base
|
6
|
+
attr_accessor :current_user
|
7
|
+
|
8
|
+
# For the body
|
9
|
+
has_many_rich_texts
|
10
|
+
|
11
|
+
# For the image attachment
|
12
|
+
has_one_attached :file
|
13
|
+
|
14
|
+
log_changes if respond_to?(:log_changes)
|
15
|
+
|
16
|
+
self.table_name = EffectivePages.carousel_items_table_name.to_s
|
17
|
+
|
18
|
+
effective_resource do
|
19
|
+
carousel :string # The hardcoded carousel I render underneath
|
20
|
+
|
21
|
+
title :string
|
22
|
+
caption :string
|
23
|
+
|
24
|
+
link_label :string
|
25
|
+
link_url :string
|
26
|
+
|
27
|
+
position :integer
|
28
|
+
|
29
|
+
timestamps
|
30
|
+
end
|
31
|
+
|
32
|
+
scope :deep, -> { with_attached_file.includes(:rich_texts) }
|
33
|
+
scope :sorted, -> { order(:position, :id) }
|
34
|
+
|
35
|
+
before_validation(if: -> { carousel.present? }) do
|
36
|
+
self.position ||= (self.class.where(carousel: carousel).pluck(:position).compact.max || -1) + 1
|
37
|
+
end
|
38
|
+
|
39
|
+
validates :carousel, presence: true
|
40
|
+
|
41
|
+
validates :title, presence: true, length: { maximum: 255 }
|
42
|
+
validates :file, presence: true
|
43
|
+
validates :position, presence: true
|
44
|
+
|
45
|
+
validates :link_url, presence: true, if: -> { link_label.present? }
|
46
|
+
validates :link_url, absence: true, if: -> { link_label.blank? }
|
47
|
+
|
48
|
+
validate(if: -> { carousel.present? && EffectivePages.carousels? }) do
|
49
|
+
unless (carousels = EffectivePages.carousels).find { |c| c.to_s == carousel.to_s }.present?
|
50
|
+
self.errors.add(:carousel, "must be one of #{carousels.to_sentence}")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
validate(if: -> { file.attached? }) do
|
55
|
+
self.errors.add(:file, 'must be an image') unless file.image?
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
persisted? ? [carousel, number].join(' ') : 'carousel item'
|
60
|
+
end
|
61
|
+
|
62
|
+
# As per has_many_rich_texts
|
63
|
+
def body
|
64
|
+
rich_text_body
|
65
|
+
end
|
66
|
+
|
67
|
+
def number
|
68
|
+
'#' + position.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -3,6 +3,8 @@ module Effective
|
|
3
3
|
attr_accessor :current_user
|
4
4
|
attr_accessor :menu_root_level
|
5
5
|
|
6
|
+
belongs_to :page_banner, optional: true
|
7
|
+
|
6
8
|
# These parent / children are for the menu as well
|
7
9
|
belongs_to :menu_parent, class_name: 'Effective::Page', optional: true
|
8
10
|
|
@@ -28,7 +30,7 @@ module Effective
|
|
28
30
|
|
29
31
|
slug :string
|
30
32
|
|
31
|
-
#
|
33
|
+
# Menus
|
32
34
|
menu :boolean # Should this be displayed on the menu at all?
|
33
35
|
menu_name :string # When I'm a root level item, this is the menu I render underneath
|
34
36
|
menu_group :string # Used for design. Group by menu_group to display full dropdowns.
|
@@ -37,6 +39,10 @@ module Effective
|
|
37
39
|
menu_url :string # Redirect to this url instead of the page url
|
38
40
|
menu_position :integer # Position in the menu
|
39
41
|
|
42
|
+
# Banners
|
43
|
+
banner :boolean # Should we display a banner?
|
44
|
+
banner_random :boolean # Display a random banner
|
45
|
+
|
40
46
|
# Access
|
41
47
|
roles_mask :integer
|
42
48
|
authenticate_user :boolean
|
@@ -44,31 +50,7 @@ module Effective
|
|
44
50
|
timestamps
|
45
51
|
end
|
46
52
|
|
47
|
-
|
48
|
-
self.menu_position = (self.class.where(menu_parent: menu_parent).maximum(:menu_position) || -1) + 1
|
49
|
-
end
|
50
|
-
|
51
|
-
validate(if: -> { menu_url.present? }) do
|
52
|
-
unless menu_url.start_with?('http://') || menu_url.start_with?('https://') || menu_url.start_with?('/')
|
53
|
-
self.errors.add(:menu_url, "must start with http(s):// or /")
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
validates :title, presence: true, length: { maximum: 255 }
|
58
|
-
validates :meta_description, presence: true, length: { maximum: 150 }
|
59
|
-
|
60
|
-
validates :layout, presence: true
|
61
|
-
validates :template, presence: true
|
62
|
-
|
63
|
-
validates :menu_name, presence: true, if: -> { menu_root? && EffectivePages.menus.present? }
|
64
|
-
|
65
|
-
# Doesn't make sense for a top level item to have a menu group
|
66
|
-
validates :menu_group, absence: true, if: -> { menu_root? && EffectivePages.menus.present? }
|
67
|
-
|
68
|
-
# validates :menu_position, if: -> { menu? },
|
69
|
-
# presence: true, uniqueness: { scope: [:menu_name, :menu_parent_id] }
|
70
|
-
|
71
|
-
scope :deep, -> { includes(:menu_parent, menu_children: :menu_parent) }
|
53
|
+
scope :deep, -> { includes(:page_banner, :menu_parent, menu_children: :menu_parent) }
|
72
54
|
|
73
55
|
scope :draft, -> { where(draft: true) }
|
74
56
|
scope :published, -> { where(draft: false) }
|
@@ -93,6 +75,34 @@ module Effective
|
|
93
75
|
published.where(menu: false).or(published.where(menu: true).where.not(id: menu_root_with_children))
|
94
76
|
}
|
95
77
|
|
78
|
+
before_validation(if: -> { menu? && menu_position.blank? }) do
|
79
|
+
self.menu_position = (self.class.where(menu_parent: menu_parent).maximum(:menu_position) || -1) + 1
|
80
|
+
end
|
81
|
+
|
82
|
+
validate(if: -> { menu_url.present? }) do
|
83
|
+
unless menu_url.start_with?('http://') || menu_url.start_with?('https://') || menu_url.start_with?('/')
|
84
|
+
self.errors.add(:menu_url, "must start with http(s):// or /")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
validates :title, presence: true, length: { maximum: 255 }
|
89
|
+
validates :meta_description, presence: true, length: { maximum: 150 }
|
90
|
+
|
91
|
+
validates :layout, presence: true
|
92
|
+
validates :template, presence: true
|
93
|
+
|
94
|
+
validates :menu_name, presence: true, if: -> { menu_root? && EffectivePages.menus.present? }
|
95
|
+
|
96
|
+
# Doesn't make sense for a top level item to have a menu group
|
97
|
+
validates :menu_group, absence: true, if: -> { menu_root? && EffectivePages.menus.present? }
|
98
|
+
|
99
|
+
validate(if: -> { banner? && EffectivePages.banners? }) do
|
100
|
+
unless (page_banner.present? ^ banner_random?) # xor
|
101
|
+
self.errors.add(:page_banner_id, "please select a page banner or random")
|
102
|
+
self.errors.add(:banner_random, "please select a page banner or random")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
96
106
|
def to_s
|
97
107
|
title
|
98
108
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Banners can be
|
2
|
+
module Effective
|
3
|
+
class PageBanner < ActiveRecord::Base
|
4
|
+
attr_accessor :current_user
|
5
|
+
|
6
|
+
# Not used
|
7
|
+
has_many_rich_texts
|
8
|
+
|
9
|
+
# Can be displayed on multiple pages
|
10
|
+
has_many :pages
|
11
|
+
|
12
|
+
# For the image attachment
|
13
|
+
has_one_attached :file
|
14
|
+
|
15
|
+
log_changes if respond_to?(:log_changes)
|
16
|
+
|
17
|
+
self.table_name = EffectivePages.page_banners_table_name.to_s
|
18
|
+
|
19
|
+
effective_resource do
|
20
|
+
name :string # Unique name of this page banner. Just used for reference.
|
21
|
+
|
22
|
+
caption :string
|
23
|
+
|
24
|
+
timestamps
|
25
|
+
end
|
26
|
+
|
27
|
+
scope :deep, -> { with_attached_file.includes(:rich_texts) }
|
28
|
+
scope :sorted, -> { order(:name) }
|
29
|
+
scope :random, -> { order('RANDOM()') }
|
30
|
+
|
31
|
+
validates :name, presence: true, uniqueness: true, length: { maximum: 255 }
|
32
|
+
validates :file, presence: true
|
33
|
+
|
34
|
+
validate(if: -> { file.attached? }) do
|
35
|
+
self.errors.add(:file, 'must be an image') unless file.image?
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
name.presence || 'page banner'
|
40
|
+
end
|
41
|
+
|
42
|
+
# As per has_many_rich_texts
|
43
|
+
def body
|
44
|
+
rich_text_body
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
+
# Page sections are only created by seeds / a developer
|
2
|
+
# They are referenced by name
|
3
|
+
# The admin user can only edit/update content
|
1
4
|
module Effective
|
2
5
|
class PageSection < ActiveRecord::Base
|
3
6
|
attr_accessor :current_user
|
4
7
|
|
5
|
-
# Not used
|
6
|
-
belongs_to :owner, polymorphic: true, optional: true
|
7
|
-
|
8
8
|
has_many_rich_texts
|
9
9
|
has_one_attached :file
|
10
10
|
|
@@ -13,7 +13,8 @@ module Effective
|
|
13
13
|
self.table_name = EffectivePages.page_sections_table_name.to_s
|
14
14
|
|
15
15
|
effective_resource do
|
16
|
-
name :string #
|
16
|
+
name :string # Set by developer. The unique name of this page section
|
17
|
+
hint :text # Set by developer. A hint to display to user.
|
17
18
|
|
18
19
|
title :string
|
19
20
|
caption :string
|
@@ -21,8 +22,6 @@ module Effective
|
|
21
22
|
link_label :string
|
22
23
|
link_url :string
|
23
24
|
|
24
|
-
hint :text
|
25
|
-
|
26
25
|
timestamps
|
27
26
|
end
|
28
27
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
= effective_form_with(model: [:admin, carousel_item], engine: true) do |f|
|
2
|
+
- if (carousels = EffectivePages.carousels).length > 1
|
3
|
+
= f.select :carousel, carousels, label: 'Carousel item in this carousel'
|
4
|
+
- else
|
5
|
+
= f.hidden_field :carousel, value: carousels.first
|
6
|
+
|
7
|
+
= f.text_field :title
|
8
|
+
|
9
|
+
- if defined?(EffectiveArticleEditor)
|
10
|
+
= f.article_editor :rich_text_body, label: 'Body', hint: 'The main content'
|
11
|
+
- else
|
12
|
+
= f.rich_text_area :rich_text_body, label: 'Body', hint: 'The main content'
|
13
|
+
|
14
|
+
.row
|
15
|
+
.col= f.text_field :link_label
|
16
|
+
.col= f.url_field :link_url
|
17
|
+
|
18
|
+
= f.file_field :file, label: 'Image Attachment', hint: 'The image to display on this carousel item'
|
19
|
+
= f.text_field :caption, hint: 'Displayed alongside the image'
|
20
|
+
|
21
|
+
= effective_submit(f)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
%h1= @page_title
|
2
|
+
|
3
|
+
%p
|
4
|
+
Click Reorder to drag & drop reorder carousel items.
|
5
|
+
Edit an item to change its content.
|
6
|
+
|
7
|
+
- EffectivePages.carousels.each do |carousel|
|
8
|
+
%h3 #{carousel.to_s.titleize} Carousel
|
9
|
+
- datatable = EffectiveCarouselItemsDatatable.new(carousel: carousel)
|
10
|
+
= render_datatable(datatable, simple: true, inline: true)
|
11
|
+
%hr.my-5
|
@@ -0,0 +1,12 @@
|
|
1
|
+
= effective_form_with(model: [:admin, page_banner], engine: true) do |f|
|
2
|
+
= f.text_field :name, hint: 'The name of this banner. Used for reference only'
|
3
|
+
|
4
|
+
= f.file_field :file, label: 'Image Attachment', hint: 'Upload an image to display on this banner'
|
5
|
+
= f.text_field :caption, hint: 'Displayed alongside the image'
|
6
|
+
|
7
|
+
-# - if defined?(EffectiveArticleEditor)
|
8
|
+
-# = f.article_editor :rich_text_body, label: 'Body', hint: 'The main content'
|
9
|
+
-# - else
|
10
|
+
-# = f.rich_text_area :rich_text_body, label: 'Body', hint: 'The main content'
|
11
|
+
|
12
|
+
= effective_submit(f)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
= effective_form_with(model: [:admin, page_section], engine: true) do |f|
|
2
2
|
- if f.object.new_record?
|
3
|
-
= f.text_field :name, hint: 'The name of this
|
3
|
+
= f.text_field :name, hint: 'The name of this page section'
|
4
4
|
- else
|
5
5
|
= f.static_field :name
|
6
6
|
|
@@ -18,8 +18,7 @@
|
|
18
18
|
.col= f.text_field :link_label
|
19
19
|
.col= f.url_field :link_url
|
20
20
|
|
21
|
-
= f.file_field :file, label: 'Attachment'
|
22
|
-
|
23
|
-
= f.text_field :caption
|
21
|
+
= f.file_field :file, label: 'Attachment', hint: 'Upload an image to display on this page section'
|
22
|
+
= f.text_field :caption, hint: 'Displayed alongside the image'
|
24
23
|
|
25
24
|
= effective_submit(f)
|
@@ -23,6 +23,17 @@
|
|
23
23
|
- current_url = (effective_pages.page_url(f.object) rescue nil)
|
24
24
|
= f.text_field :slug, hint: "The slug controls this page's internet address. Be careful, changing the slug will break links that other websites may have to the old address.<br>#{('This page is currently reachable via ' + link_to(current_url.gsub(f.object.slug, '<strong>' + f.object.slug + '</strong>').html_safe, current_url)) if current_url }".html_safe
|
25
25
|
|
26
|
+
- if EffectivePages.banners?
|
27
|
+
= f.check_box :banner, label: 'Yes, display a page banner on this page'
|
28
|
+
|
29
|
+
= f.show_if(:banner, true) do
|
30
|
+
= card('Page Banner') do
|
31
|
+
%p.text-muted Please visit #{link_to('Page Banners', effective_pages.admin_page_banners_path)} to add or update the page banners.
|
32
|
+
|
33
|
+
= f.select :page_banner_id, Effective::PageBanner.sorted.all, label: 'Display this page banner'
|
34
|
+
%p - or -
|
35
|
+
= f.check_box :banner_random, label: 'Display a random page banner each time the page is refreshed'
|
36
|
+
|
26
37
|
= render partial: '/admin/pages/additional_fields', locals: { page: page, form: f, f: f }
|
27
38
|
|
28
39
|
- if f.object.persisted? && f.object.menu_root_with_children?
|
@@ -0,0 +1,27 @@
|
|
1
|
+
- uid = "effective-carousel-#{carousel}-#{Time.zone.now.to_i}"
|
2
|
+
- options = carousel_options
|
3
|
+
|
4
|
+
- raise('expected one or more carousel items') unless carousel_items.present?
|
5
|
+
|
6
|
+
%div.carousel.slide{id: uid, 'data-ride': 'carousel', **options}
|
7
|
+
%ol.carousel-indicators
|
8
|
+
- carousel_items.each_with_index do |item, index|
|
9
|
+
%li{'data-target': '#' + uid, 'data-slide-to': index, class: ('active' if index == 0)}
|
10
|
+
|
11
|
+
%div.carousel-inner
|
12
|
+
- carousel_items.each_with_index do |item, index|
|
13
|
+
%div.carousel-item{class: ('active' if index == 0)}
|
14
|
+
- if item.caption.blank?
|
15
|
+
= image_tag(item.file, class: 'd-block w-100', alt: "Slide #{index+1}")
|
16
|
+
- else
|
17
|
+
= image_tag(item.file, alt: item.caption)
|
18
|
+
%div.carousel-caption.d-none.d-md-block
|
19
|
+
%p= item.caption
|
20
|
+
|
21
|
+
%a.carousel-control-prev{href: '#' + uid, role: 'button', 'data-slide': 'prev'}
|
22
|
+
%span.carousel-control-prev-icon{'aria-hidden': true}
|
23
|
+
%span.sr-only Previous
|
24
|
+
|
25
|
+
%a.carousel-control-next{href: '#' + uid, role: 'button', 'data-slide': 'next'}
|
26
|
+
%span.carousel-control-next-icon{'aria-hidden': true}
|
27
|
+
%span.sr-only Next
|
data/config/effective_pages.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
EffectivePages.setup do |config|
|
2
2
|
config.pages_table_name = :pages
|
3
3
|
config.page_sections_table_name = :page_sections
|
4
|
+
config.page_banners_table_name = :page_banners
|
5
|
+
config.carousel_items_table_name = :carousel_items
|
4
6
|
|
5
7
|
# The menu names a page can belong to
|
6
8
|
config.menus = [:main, :footer]
|
@@ -57,4 +59,14 @@ EffectivePages.setup do |config|
|
|
57
59
|
# Only 2 or 3 are supported right now
|
58
60
|
config.max_menu_depth = 2
|
59
61
|
|
62
|
+
# Page Banners
|
63
|
+
# Allow a page banner to be selected on the Admin::Pages#edit screen
|
64
|
+
# Banners can be CRUD by the admin
|
65
|
+
config.banners = false
|
66
|
+
|
67
|
+
# Page Carousels
|
68
|
+
# The menu names a page can belong to
|
69
|
+
config.carousels = false
|
70
|
+
# config.carousels = [:home, :secondary]
|
71
|
+
|
60
72
|
end
|
data/config/routes.rb
CHANGED
@@ -4,7 +4,9 @@ EffectivePages::Engine.routes.draw do
|
|
4
4
|
namespace :admin do
|
5
5
|
resources :pages, except: [:show]
|
6
6
|
resources :page_sections, only: [:index, :edit, :update]
|
7
|
+
resources :page_banners, except: [:show]
|
7
8
|
resources :menus, only: [:index]
|
9
|
+
resources :carousel_items, except: [:show]
|
8
10
|
end
|
9
11
|
|
10
12
|
scope module: 'effective' do
|
@@ -1,6 +1,8 @@
|
|
1
1
|
class CreateEffectivePages < ActiveRecord::Migration[4.2]
|
2
2
|
def self.up
|
3
3
|
create_table <%= @pages_table_name %> do |t|
|
4
|
+
t.integer :page_banner_id
|
5
|
+
|
4
6
|
t.string :title
|
5
7
|
t.string :meta_description
|
6
8
|
|
@@ -25,17 +27,27 @@ class CreateEffectivePages < ActiveRecord::Migration[4.2]
|
|
25
27
|
t.string :menu_url
|
26
28
|
t.integer :menu_position
|
27
29
|
|
30
|
+
t.boolean :banner, default: false
|
31
|
+
t.boolean :banner_random, default: false
|
32
|
+
|
28
33
|
t.datetime :updated_at
|
29
34
|
t.datetime :created_at
|
30
35
|
end
|
31
36
|
|
32
37
|
add_index <%= @pages_table_name %>, :slug, :unique => true
|
33
38
|
|
34
|
-
create_table <%= @
|
35
|
-
t.string :
|
36
|
-
t.
|
39
|
+
create_table <%= @page_banners_table_name %> do |t|
|
40
|
+
t.string :name
|
41
|
+
t.string :caption
|
42
|
+
|
43
|
+
t.timestamps
|
44
|
+
end
|
45
|
+
|
46
|
+
add_index <%= @page_banners_table_name %>, :name, :unique => true
|
37
47
|
|
48
|
+
create_table <%= @page_sections_table_name %> do |t|
|
38
49
|
t.string :name
|
50
|
+
t.text :hint
|
39
51
|
|
40
52
|
t.string :title
|
41
53
|
t.string :caption
|
@@ -43,18 +55,33 @@ class CreateEffectivePages < ActiveRecord::Migration[4.2]
|
|
43
55
|
t.string :link_label
|
44
56
|
t.string :link_url
|
45
57
|
|
46
|
-
t.text :hint
|
47
|
-
|
48
58
|
t.datetime :updated_at
|
49
59
|
t.datetime :created_at
|
50
60
|
end
|
51
61
|
|
52
62
|
add_index <%= @page_sections_table_name %>, :name, :unique => true
|
63
|
+
|
64
|
+
create_table <%= @carousel_items_table_name %> do |t|
|
65
|
+
t.string :carousel
|
66
|
+
|
67
|
+
t.string :title
|
68
|
+
t.string :caption
|
69
|
+
|
70
|
+
t.string :link_label
|
71
|
+
t.string :link_url
|
72
|
+
|
73
|
+
t.integer :position
|
74
|
+
|
75
|
+
t.timestamps
|
76
|
+
end
|
77
|
+
|
53
78
|
end
|
54
79
|
|
55
80
|
def self.down
|
56
81
|
drop_table <%= @pages_table_name %>
|
82
|
+
drop_table <%= @page_banners_table_name %>
|
57
83
|
drop_table <%= @page_sections_table_name %>
|
84
|
+
drop_table <%= @carousel_items_table_name %>
|
58
85
|
end
|
59
86
|
|
60
87
|
end
|
@@ -7,7 +7,9 @@ module EffectivePages
|
|
7
7
|
app.config.to_prepare do
|
8
8
|
ActiveSupport.on_load :action_controller_base do
|
9
9
|
helper EffectivePagesHelper
|
10
|
+
helper EffectiveCarouselsHelper
|
10
11
|
helper EffectivePageSectionsHelper
|
12
|
+
helper EffectivePageBannersHelper
|
11
13
|
helper EffectiveMenusHelper
|
12
14
|
end
|
13
15
|
end
|
data/lib/effective_pages.rb
CHANGED
@@ -7,12 +7,18 @@ require 'effective_pages/version'
|
|
7
7
|
module EffectivePages
|
8
8
|
def self.config_keys
|
9
9
|
[
|
10
|
-
:pages_table_name, :page_sections_table_name,
|
10
|
+
:pages_table_name, :page_sections_table_name, :page_banners_table_name, :carousel_items_table_name,
|
11
11
|
:pages_path, :excluded_pages, :layouts_path, :excluded_layouts,
|
12
12
|
:site_og_image, :site_og_image_width, :site_og_image_height,
|
13
13
|
:site_title, :site_title_suffix, :fallback_meta_description,
|
14
14
|
:silence_missing_page_title_warnings, :silence_missing_meta_description_warnings, :silence_missing_canonical_url_warnings,
|
15
|
-
:use_effective_roles, :
|
15
|
+
:use_effective_roles, :layout, :max_menu_depth,
|
16
|
+
|
17
|
+
# Booleans
|
18
|
+
:banners,
|
19
|
+
|
20
|
+
# Hashes
|
21
|
+
:menus, :carousels
|
16
22
|
]
|
17
23
|
end
|
18
24
|
|
@@ -49,4 +55,16 @@ module EffectivePages
|
|
49
55
|
depth
|
50
56
|
end
|
51
57
|
|
58
|
+
def self.banners?
|
59
|
+
!!banners
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.carousels?
|
63
|
+
carousels.kind_of?(Array)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.menus?
|
67
|
+
menus.kind_of?(Array)
|
68
|
+
end
|
69
|
+
|
52
70
|
end
|
@@ -22,6 +22,9 @@ module EffectivePages
|
|
22
22
|
def create_migration_file
|
23
23
|
@pages_table_name = ':' + EffectivePages.pages_table_name.to_s
|
24
24
|
@page_sections_table_name = ':' + EffectivePages.page_sections_table_name.to_s
|
25
|
+
@page_banners_table_name = ':' + EffectivePages.page_banners_table_name.to_s
|
26
|
+
@carousel_items_table_name = ':' + EffectivePages.carousel_items_table_name.to_s
|
27
|
+
|
25
28
|
migration_template ('../' * 3) + 'db/migrate/01_create_effective_pages.rb.erb', 'db/migrate/create_effective_pages.rb'
|
26
29
|
end
|
27
30
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_pages
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
@@ -75,19 +75,32 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- MIT-LICENSE
|
77
77
|
- README.md
|
78
|
+
- app/controllers/admin/carousel_items_controller.rb
|
78
79
|
- app/controllers/admin/menus_controller.rb
|
80
|
+
- app/controllers/admin/page_banners_controller.rb
|
79
81
|
- app/controllers/admin/page_sections_controller.rb
|
80
82
|
- app/controllers/admin/pages_controller.rb
|
81
83
|
- app/controllers/effective/pages_controller.rb
|
84
|
+
- app/datatables/effective_carousel_items_datatable.rb
|
85
|
+
- app/datatables/effective_page_banners_datatable.rb
|
82
86
|
- app/datatables/effective_page_sections_datatable.rb
|
83
87
|
- app/datatables/effective_pages_datatable.rb
|
84
88
|
- app/datatables/effective_pages_menu_datatable.rb
|
89
|
+
- app/helpers/effective_carousels_helper.rb
|
85
90
|
- app/helpers/effective_menus_helper.rb
|
91
|
+
- app/helpers/effective_page_banners_helper.rb
|
86
92
|
- app/helpers/effective_page_sections_helper.rb
|
87
93
|
- app/helpers/effective_pages_helper.rb
|
94
|
+
- app/models/effective/carousel_item.rb
|
88
95
|
- app/models/effective/page.rb
|
96
|
+
- app/models/effective/page_banner.rb
|
89
97
|
- app/models/effective/page_section.rb
|
98
|
+
- app/views/admin/carousel_items/_form.html.haml
|
99
|
+
- app/views/admin/carousel_items/_form_carousel_item.html.haml
|
100
|
+
- app/views/admin/carousel_items/index.html.haml
|
90
101
|
- app/views/admin/menus/index.html.haml
|
102
|
+
- app/views/admin/page_banners/_form.html.haml
|
103
|
+
- app/views/admin/page_banners/_form_page_banner.html.haml
|
91
104
|
- app/views/admin/page_sections/_form.html.haml
|
92
105
|
- app/views/admin/page_sections/_form_page_section.html.haml
|
93
106
|
- app/views/admin/pages/_additional_fields.html.haml
|
@@ -96,6 +109,7 @@ files:
|
|
96
109
|
- app/views/admin/pages/_form_menu.html.haml
|
97
110
|
- app/views/admin/pages/_form_page.html.haml
|
98
111
|
- app/views/admin/pages/_rich_text_areas.html.haml
|
112
|
+
- app/views/effective/carousels/_carousel.html.haml
|
99
113
|
- app/views/effective/pages/_menu.html.haml
|
100
114
|
- app/views/effective/pages/_page_menu.html.haml
|
101
115
|
- config/effective_pages.rb
|