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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -4
  3. data/app/controllers/admin/carousel_items_controller.rb +15 -0
  4. data/app/controllers/admin/menus_controller.rb +3 -0
  5. data/app/controllers/admin/page_banners_controller.rb +13 -0
  6. data/app/datatables/effective_carousel_items_datatable.rb +35 -0
  7. data/app/datatables/effective_page_banners_datatable.rb +25 -0
  8. data/app/datatables/effective_page_sections_datatable.rb +2 -2
  9. data/app/datatables/effective_pages_datatable.rb +2 -0
  10. data/app/helpers/effective_carousels_helper.rb +23 -0
  11. data/app/helpers/effective_page_banners_helper.rb +23 -0
  12. data/app/models/effective/carousel_item.rb +73 -0
  13. data/app/models/effective/page.rb +36 -26
  14. data/app/models/effective/page_banner.rb +49 -0
  15. data/app/models/effective/page_section.rb +5 -6
  16. data/app/views/admin/carousel_items/_form.html.haml +7 -0
  17. data/app/views/admin/carousel_items/_form_carousel_item.html.haml +21 -0
  18. data/app/views/admin/carousel_items/index.html.haml +5 -0
  19. data/app/views/admin/menus/index.html.haml +4 -10
  20. data/app/views/admin/page_banners/_form.html.haml +7 -0
  21. data/app/views/admin/page_banners/_form_page_banner.html.haml +11 -0
  22. data/app/views/admin/page_sections/_form_page_section.html.haml +5 -5
  23. data/app/views/admin/pages/_form_page.html.haml +11 -0
  24. data/app/views/effective/carousels/_carousel.html.haml +27 -0
  25. data/config/effective_pages.rb +14 -0
  26. data/config/routes.rb +2 -0
  27. data/db/migrate/01_create_effective_pages.rb.erb +32 -5
  28. data/lib/effective_pages/engine.rb +2 -0
  29. data/lib/effective_pages/version.rb +1 -1
  30. data/lib/effective_pages.rb +20 -2
  31. data/lib/generators/effective_pages/install_generator.rb +3 -0
  32. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3ef36f0fae90cb4172cbc5541abbac53d632e611024fc1b3febd6fc8476cafd
4
- data.tar.gz: ed784ec8c9575641c5803450d5664b5d11cf90aab89d73163c4d86e28448f66e
3
+ metadata.gz: 33c7720dd14a75e375dffed5ae8c21e7390cfd93727886785c72d574fbe23376
4
+ data.tar.gz: 40ab7326b18be3a3a728461f604c4e2cfd827d75bacef55b2cd7bada79f5d513
5
5
  SHA512:
6
- metadata.gz: 6afc63a6a120d7b67d872ab985f990d0db4117b12a7e0ae1bf79a2451c00fdcf89e18e8c2a3c58d22344f3a0190e0fc9cf11589b11c01e57f8fbf7798fee12cb
7
- data.tar.gz: 38786d89a2341773f87bb122d9b64f26e7778d23c97dee10ee04d1b846b09331e9266acc7b156e6e8bd62dd249d58af64d465454d564d8cca958688ca8ca753c
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 [:show], Effective::Page
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 :manage, Effective::Page
179
- can :manage, Effective::Menu
180
- can :admin, :effective_pages # Can access the admin screens
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 :files
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
- # Menu stuff
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
- before_validation(if: -> { menu? && menu_position.blank? }) do
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 # Unique name of this page section
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,7 @@
1
+ = tabs do
2
+ = tab 'Carousel Item' do
3
+ = render '/admin/carousel_items/form_carousel_item', carousel_item: carousel_item
4
+
5
+ - if carousel_item.persisted?
6
+ = tab 'Logs' do
7
+ = render_datatable(carousel_item.log_changes_datatable, inline: true, namespace: :admin)
@@ -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)
@@ -0,0 +1,5 @@
1
+ - EffectivePages.carousels.each do |carousel|
2
+ .bg-white.my-5.p-3.rounded
3
+ %h3.mb-0 #{carousel.to_s.titleize} Carousel
4
+ - datatable = EffectiveCarouselItemsDatatable.new(carousel: carousel)
5
+ = render_datatable(datatable, simple: true, inline: true)
@@ -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
- %h3 #{menu.to_s.titleize} Menu
9
- - datatable = EffectivePagesMenuDatatable.new(menu: menu)
10
- = render_datatable(datatable, simple: true, inline: true)
11
- %hr.my-5
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,7 @@
1
+ = tabs do
2
+ = tab 'Page Banner' do
3
+ = render '/admin/page_banners/form_page_banner', page_banner: page_banner
4
+
5
+ - if page_banner.persisted?
6
+ = tab 'Logs' do
7
+ = render_datatable(page_banner.log_changes_datatable, inline: true, namespace: :admin)
@@ -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 region must be unique'
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
- .mb-4= f.object.hint.html_safe
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
@@ -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 <%= @page_sections_table_name %> do |t|
35
- t.string :owner_type
36
- t.integer :owner_id
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
@@ -1,3 +1,3 @@
1
1
  module EffectivePages
2
- VERSION = '3.3.2'.freeze
2
+ VERSION = '3.4.1'.freeze
3
3
  end
@@ -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, :menus, :layout, :max_menu_depth
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.3.2
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 00:00:00.000000000 Z
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