effective_pages 3.3.2 → 3.4.1
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/README.md +9 -4
- data/app/controllers/admin/carousel_items_controller.rb +15 -0
- data/app/controllers/admin/menus_controller.rb +3 -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 +2 -2
- 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 +5 -0
- data/app/views/admin/menus/index.html.haml +4 -10
- data/app/views/admin/page_banners/_form.html.haml +7 -0
- data/app/views/admin/page_banners/_form_page_banner.html.haml +11 -0
- data/app/views/admin/page_sections/_form_page_section.html.haml +5 -5
- 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 +14 -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 +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33c7720dd14a75e375dffed5ae8c21e7390cfd93727886785c72d574fbe23376
|
4
|
+
data.tar.gz: 40ab7326b18be3a3a728461f604c4e2cfd827d75bacef55b2cd7bada79f5d513
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b9359a7b5c76c694ded55b524981df67e85f01e080c6ca2ae17c895762a52438d72d2c3b1ee508ff89d370eda0b921ea526af6b53800a353a8ad4ac5f79228e
|
7
|
+
data.tar.gz: 5ccdeb32c10e7920fa017a4f6d0d5ca8ba6416290de99d202a4f972092e20b3e18cb53dc4c1d26d6e38aafbeae6135073382d0029a9717d6aae61c99112adf89
|
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,15 @@
|
|
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
|
+
page_title 'Carousels'
|
9
|
+
|
10
|
+
def permitted_params
|
11
|
+
params.require(:effective_carousel_item).permit!
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -3,8 +3,11 @@ module Admin
|
|
3
3
|
before_action(:authenticate_user!) if defined?(Devise)
|
4
4
|
before_action { EffectiveResources.authorize!(self, :admin, :effective_pages) }
|
5
5
|
|
6
|
+
|
6
7
|
include Effective::CrudController
|
7
8
|
|
9
|
+
page_title 'Menus'
|
10
|
+
|
8
11
|
resource_scope -> { Effective::Page.all }
|
9
12
|
|
10
13
|
if (config = EffectivePages.layout)
|
@@ -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
|
@@ -8,13 +8,13 @@ class EffectivePageSectionsDatatable < Effective::Datatable
|
|
8
8
|
col :updated_at, visible: false
|
9
9
|
|
10
10
|
col :name
|
11
|
-
col :hint
|
12
11
|
|
13
12
|
col :title
|
14
13
|
col :rich_text_body
|
15
14
|
|
16
|
-
col :
|
15
|
+
col :file
|
17
16
|
|
17
|
+
col :hint, visible: false
|
18
18
|
col :link_label, visible: false
|
19
19
|
col :link_url, visible: false
|
20
20
|
col :caption, visible: false
|
@@ -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'
|
11
|
+
- else
|
12
|
+
= f.rich_text_area :rich_text_body, label: 'Body'
|
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: EffectivePages.carousels_hint_text
|
19
|
+
= f.text_field :caption, hint: 'Optional'
|
20
|
+
|
21
|
+
= effective_submit(f)
|
@@ -1,11 +1,5 @@
|
|
1
|
-
%h1= @page_title
|
2
|
-
|
3
|
-
%p
|
4
|
-
Click Reorder to drag & drop reorder menu items.
|
5
|
-
Edit an item to reorder its children items.
|
6
|
-
|
7
1
|
- EffectivePages.menus.each do |menu|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
2
|
+
.bg-white.my-5.p-3.rounded
|
3
|
+
%h3.mb-0 #{menu.to_s.titleize} Menu
|
4
|
+
- datatable = EffectivePagesMenuDatatable.new(menu: menu)
|
5
|
+
= render_datatable(datatable, simple: true, inline: true)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
= effective_form_with(model: [:admin, page_banner], engine: true) do |f|
|
2
|
+
= f.text_field :name, hint: 'The name of this banner, used only for reference'
|
3
|
+
= f.file_field :file, label: 'Image attachment', hint: EffectivePages.banners_hint_text
|
4
|
+
= f.text_field :caption, hint: 'Optional. Displayed alongside the image'
|
5
|
+
|
6
|
+
-# - if defined?(EffectiveArticleEditor)
|
7
|
+
-# = f.article_editor :rich_text_body, label: 'Body', hint: 'The main content'
|
8
|
+
-# - else
|
9
|
+
-# = f.rich_text_area :rich_text_body, label: 'Body', hint: 'The main content'
|
10
|
+
|
11
|
+
= effective_submit(f)
|
@@ -1,11 +1,12 @@
|
|
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
|
|
7
7
|
- if f.object.hint.present?
|
8
|
-
.
|
8
|
+
%h4.mt-0 Instructions
|
9
|
+
%p= f.object.hint.html_safe
|
9
10
|
|
10
11
|
= f.text_field :title
|
11
12
|
|
@@ -18,8 +19,7 @@
|
|
18
19
|
.col= f.text_field :link_label
|
19
20
|
.col= f.url_field :link_url
|
20
21
|
|
21
|
-
= f.file_field :file, label: 'Attachment'
|
22
|
-
|
23
|
-
= f.text_field :caption
|
22
|
+
= f.file_field :file, label: 'Attachment', hint: 'Upload an image to display on this page section'
|
23
|
+
= f.text_field :caption, hint: 'Displayed alongside the image'
|
24
24
|
|
25
25
|
= 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,16 @@ 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
|
+
config.banners_hint_text = 'Hint text that includes required image dimensions'
|
67
|
+
|
68
|
+
# Page Carousels
|
69
|
+
# The menu names a page can belong to
|
70
|
+
config.carousels = false
|
71
|
+
# config.carousels = [:home, :secondary]
|
72
|
+
config.carousels_hint_text = 'Hint text that includes required image dimensions'
|
73
|
+
|
60
74
|
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, :banners_hint_text, :carousels_hint_text,
|
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,14 +1,14 @@
|
|
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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -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
|