blueberry_cms 0.1.0 → 0.1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -0
  3. data/app/assets/javascripts/blueberry_cms/multilingual-tabs.coffee +0 -0
  4. data/app/assets/javascripts/blueberry_cms/sortable-page-blocks.coffee +14 -0
  5. data/app/assets/javascripts/blueberry_cms/sortable-pages.coffee +17 -0
  6. data/app/assets/javascripts/blueberry_cms.coffee +3 -0
  7. data/app/assets/stylesheets/blueberry_cms/components.sass +39 -0
  8. data/app/assets/stylesheets/blueberry_cms/multilingual-tabs.sass +44 -0
  9. data/app/assets/stylesheets/blueberry_cms.sass +1 -0
  10. data/app/controllers/blueberry_cms/admin/menus_controller.rb +50 -0
  11. data/app/controllers/blueberry_cms/admin/pages_controller.rb +22 -16
  12. data/app/controllers/blueberry_cms/root_controller.rb +2 -1
  13. data/app/decorators/block_decorator.rb +13 -0
  14. data/app/decorators/blueberry_cms/link_decorator.rb +15 -0
  15. data/app/decorators/blueberry_cms/page_block_decorator.rb +46 -0
  16. data/app/decorators/blueberry_cms/page_decorator.rb +7 -0
  17. data/app/helpers/blueberry_cms/menus_helper.rb +27 -0
  18. data/app/helpers/blueberry_cms/pages_helper.rb +11 -0
  19. data/app/models/blueberry_cms/image.rb +19 -0
  20. data/app/models/blueberry_cms/link.rb +28 -0
  21. data/app/models/blueberry_cms/menu.rb +19 -0
  22. data/app/models/blueberry_cms/menu_link.rb +36 -0
  23. data/app/models/blueberry_cms/page.rb +62 -11
  24. data/app/models/blueberry_cms/page_block.rb +29 -8
  25. data/app/models/blueberry_cms/page_blocks/faq.rb +19 -0
  26. data/app/models/blueberry_cms/page_blocks/gallery.rb +12 -12
  27. data/app/models/blueberry_cms/page_blocks/links.rb +15 -0
  28. data/app/models/blueberry_cms/page_blocks/rich_text.rb +4 -15
  29. data/app/models/blueberry_cms/page_blocks/shared.rb +25 -0
  30. data/app/models/blueberry_cms/page_blocks/tabs.rb +17 -0
  31. data/app/models/blueberry_cms/page_blocks/video_gallery.rb +13 -0
  32. data/app/models/blueberry_cms/question.rb +11 -0
  33. data/app/models/blueberry_cms/tab.rb +13 -0
  34. data/app/models/blueberry_cms/video.rb +70 -0
  35. data/app/models/concerns/blueberry_cms/sortable.rb +25 -0
  36. data/app/models/custom_render.rb +3 -3
  37. data/app/views/blueberry_cms/admin/menus/_empty.html.slim +2 -0
  38. data/app/views/blueberry_cms/admin/menus/_form.html.slim +6 -0
  39. data/app/views/blueberry_cms/admin/menus/_link_fields.html.slim +30 -0
  40. data/app/views/blueberry_cms/admin/menus/_menu.html.slim +18 -0
  41. data/app/views/blueberry_cms/admin/menus/edit.html.slim +15 -0
  42. data/app/views/blueberry_cms/admin/menus/index.html.slim +26 -0
  43. data/app/views/blueberry_cms/admin/menus/new.html.slim +15 -0
  44. data/app/views/blueberry_cms/admin/page_blocks/_faq.html.slim +15 -0
  45. data/app/views/blueberry_cms/admin/page_blocks/_faq_questions_fields.slim +24 -0
  46. data/app/views/blueberry_cms/admin/page_blocks/_form.html.slim +18 -0
  47. data/app/views/blueberry_cms/admin/page_blocks/_gallery.html.slim +16 -0
  48. data/app/views/blueberry_cms/admin/page_blocks/_gallery_images_fields.html.slim +14 -0
  49. data/app/views/blueberry_cms/admin/page_blocks/_links.html.slim +25 -0
  50. data/app/views/blueberry_cms/admin/page_blocks/_links_links_fields.slim +23 -0
  51. data/app/views/blueberry_cms/admin/page_blocks/_richtext.html.slim +30 -0
  52. data/app/views/blueberry_cms/admin/page_blocks/_shared.html.slim +8 -0
  53. data/app/views/blueberry_cms/admin/page_blocks/_tabs.html.slim +11 -0
  54. data/app/views/blueberry_cms/admin/page_blocks/_tabs_tabs_fields.html.slim +24 -0
  55. data/app/views/blueberry_cms/admin/page_blocks/_videogallery.html.slim +15 -0
  56. data/app/views/blueberry_cms/admin/page_blocks/_videos_fields.slim +17 -0
  57. data/app/views/blueberry_cms/admin/pages/_block_fields.html.slim +53 -3
  58. data/app/views/blueberry_cms/admin/pages/_custom_fields.html.slim +0 -0
  59. data/app/views/blueberry_cms/admin/pages/_empty.html.slim +2 -0
  60. data/app/views/blueberry_cms/admin/pages/_form.html.slim +47 -11
  61. data/app/views/blueberry_cms/admin/pages/_page.html.slim +33 -0
  62. data/app/views/blueberry_cms/admin/pages/edit.html.slim +12 -3
  63. data/app/views/blueberry_cms/admin/pages/index.html.slim +6 -27
  64. data/app/views/blueberry_cms/admin/pages/new.html.slim +9 -1
  65. data/app/views/blueberry_cms/admin/partials/_form_errors.html.slim +5 -0
  66. data/app/views/blueberry_cms/page_blocks/_faq.html.slim +19 -0
  67. data/app/views/blueberry_cms/page_blocks/_form.html.slim +19 -0
  68. data/app/views/blueberry_cms/page_blocks/_gallery.html.slim +22 -0
  69. data/app/views/blueberry_cms/page_blocks/_links.html.slim +52 -0
  70. data/app/views/blueberry_cms/page_blocks/_richtext.html.slim +10 -0
  71. data/app/views/blueberry_cms/page_blocks/_tabs.html.slim +8 -0
  72. data/app/views/blueberry_cms/page_blocks/_videogallery.html.slim +27 -0
  73. data/app/views/blueberry_cms/pages/_blocks.html.slim +5 -0
  74. data/app/views/blueberry_cms/pages/show.html.slim +9 -8
  75. data/config/locales/cs.enum.yml +10 -0
  76. data/config/locales/cs.mongoid.yml +49 -0
  77. data/config/locales/cs.yml +79 -13
  78. data/config/routes.rb +6 -2
  79. data/lib/blueberry_cms/engine.rb +12 -0
  80. data/lib/blueberry_cms/liquid_tags/page_link.rb +3 -1
  81. data/lib/blueberry_cms/liquid_tags/page_url.rb +18 -0
  82. data/lib/blueberry_cms/version.rb +1 -1
  83. data/lib/blueberry_cms.rb +9 -3
  84. data/lib/generators/blueberry/templates/image_uploader.rb +31 -0
  85. data/lib/generators/blueberry/uploader_generator.rb +9 -0
  86. metadata +184 -10
  87. data/app/assets/javascripts/blueberry_cms.js +0 -1
  88. data/app/assets/stylesheets/blueberry_cms/application.css +0 -15
  89. data/app/models/blueberry_cms/page_blocks/text.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61c283d61a1921f2eb7b8cd93004a7c37340b3a0
4
- data.tar.gz: c1a01ea065df6e7307b24ca2ee94bd7e2acaa8ac
3
+ metadata.gz: e91d2118e7044a75f384a362dc3276491ec99c78
4
+ data.tar.gz: 9bb48bd2b149ce3b97ab6d1d4ac3c49e4fe9adca
5
5
  SHA512:
6
- metadata.gz: 51b875bae9db0d15bfc5304088ff730db7a8e99594ff7180f92a5189ab1ed9ee2b84614ae459fa9c5f489aa576d39d7ea1dbe89bc555240b7762804f1eb3f720
7
- data.tar.gz: c629268cf0c723f2af56135f04fbb89ed3609895cc040e24b0a521bba716cbde5a46239022cc38f314b05a285cb0eca18d579c87975064df1e3cd5c41f4116dd
6
+ metadata.gz: 4a2ecd4ba705b32796d8ac2dd78fc68ed8efe6b20e45eed6a6399840948c87a2953fbc7e74cba79964362255d530acf51a5edf40fa33d07bfc4f4a9ebf6734c5
7
+ data.tar.gz: 42600c8ab70c5fbb54d346f952929fb952a27f4c6c7be534baf18dea7d483e946598699056f51b5efb896686d87539577bd7f1d15f0c77d989d295da03ddae60
data/README.md CHANGED
@@ -11,6 +11,18 @@ Add this line to your application's Gemfile:
11
11
  gem 'blueberry_cms'
12
12
  ```
13
13
 
14
+ Add this line to your application's sass:
15
+
16
+ ```sass
17
+ @import blueberry_cms
18
+ ```
19
+
20
+ Add this line to your application's coffeescript:
21
+
22
+ ```coffee
23
+ #= require blueberry_cms
24
+ ```
25
+
14
26
  And then execute:
15
27
  ```bash
16
28
  $ bundle
@@ -20,6 +32,28 @@ Or install it yourself as:
20
32
  ```bash
21
33
  $ gem install blueberry_cms
22
34
  ```
35
+ ## BlueberryCMS::Page custom fields
36
+ ```ruby
37
+ # config/initializers/blueberry_cms.rb
38
+
39
+ module BreadcrumbLeft
40
+ extend ActiveSupport::Concern
41
+
42
+ included do
43
+ field :breadcrumb_left, type: Boolean, default: false
44
+ end
45
+ end
46
+
47
+ ActiveSupport::Reloader.to_prepare do
48
+ BlueberryCMS::Page.send(:include, BreadcrumbLeft)
49
+ end
50
+ ```
51
+
52
+ ```slim
53
+ # app/views/blueberry_cms/admin/pages/_custom_fields.html.slim
54
+
55
+ = f.input :breadcrumb_left
56
+ ```
23
57
 
24
58
  ## Contributing
25
59
  Contribution directions go here.
@@ -0,0 +1,14 @@
1
+ initSortable = ->
2
+ sortable(
3
+ '#blocks',
4
+ handle: 'i.glyphicon-resize-vertical',
5
+ forcePlaceholderSize: true
6
+ )
7
+
8
+ initSortable()
9
+ $('#blocks').on 'cocoon:after-insert', ->
10
+ initSortable()
11
+
12
+ $('#blocks').on 'sortupdate', (e) ->
13
+ $('> .nested-fields', this).map (position) ->
14
+ $(this).find('input[id$=_position]').val(position)
@@ -0,0 +1,17 @@
1
+ $ ->
2
+ action = $('.pages-tree').data('url')
3
+
4
+ sortable(
5
+ 'ul.pages',
6
+ handle: 'i.glyphicon-resize-vertical',
7
+ forcePlaceholderSize: true
8
+ )
9
+
10
+ $('ul.pages').on 'sortupdate', (e) ->
11
+ item = $(e.detail.item)
12
+
13
+ $.ajax
14
+ url: action + "/#{item.data('id')}",
15
+ dataType: 'json'
16
+ method: 'PUT',
17
+ data: { page: { position: item.index() } }
@@ -0,0 +1,3 @@
1
+ #= require 'cocoon'
2
+ #= require 'html.sortable'
3
+ #= require_tree './blueberry_cms'
@@ -0,0 +1,39 @@
1
+ .form-layout
2
+ .form-group
3
+ display: flex
4
+ align-items: flex-start
5
+ +render-to(xs, ms)
6
+ display: block
7
+
8
+ label
9
+ min-width: rem(220)
10
+ margin-top: rem(13)
11
+ text-align: right
12
+ +render-to(xs, ms)
13
+ width: 100%
14
+ min-width: auto
15
+ text-align: left
16
+
17
+ .form-control-wrapper
18
+ margin-left: rem(15)
19
+ margin-right: 25%
20
+ flex-grow: 2
21
+ +render-to(xs, ms, sm, md)
22
+ margin-right: 0
23
+
24
+ +render-to(xs, ms)
25
+ margin-left: 0
26
+
27
+ .form-control-wrapper
28
+ margin-right: 0
29
+ margin-left: 0
30
+
31
+ .box-footer
32
+ text-align: right
33
+
34
+ .for-horizontal-form
35
+ padding-left: 0
36
+
37
+ .pages-tree__row
38
+ &:hover
39
+ background-color: #F4F6FA
@@ -0,0 +1,44 @@
1
+ .multilingual-tabs-section
2
+ .tab-content,
3
+ input[type="radio"]
4
+ display: none
5
+
6
+ .tab-label
7
+ position: relative
8
+ padding: 10px 15px
9
+ margin-bottom: -1px
10
+ margin-right: 2px
11
+ text-transform: uppercase
12
+ font-weight: normal
13
+ line-height: 20px
14
+ display: inline-block
15
+ color: #1aabd5
16
+ cursor: pointer
17
+ border-radius: rem(4) rem(4) 0 0
18
+ border: 1px solid transparent;
19
+
20
+ &:hover
21
+ border-color: #dcdcdc #dcdcdc #ddd;
22
+ color: #444;
23
+ background: #f7f7f7;
24
+ border: 1px solid #ddd;
25
+ border-bottom-color: transparent;
26
+
27
+ .tab-content
28
+ border-top: 1px solid #ddd;
29
+ padding-top: rem(25)
30
+
31
+ //all available languages
32
+ #cs-tab:checked ~ .multilingual-tabs-labels #cs-tab,
33
+ #en-tab:checked ~ .multilingual-tabs-labels #en-tab,
34
+ #ru-tab:checked ~ .multilingual-tabs-labels #ru-tab
35
+ color: #d2d6de;
36
+ background-color: #f4f6fa;
37
+ border: 1px solid #ddd;
38
+ border-bottom-color: transparent;
39
+ cursor: default;
40
+
41
+ #cs-tab:checked ~ .multilingual-content-section .cs-content,
42
+ #en-tab:checked ~ .multilingual-content-section .en-content,
43
+ #ru-tab:checked ~ .multilingual-content-section .ru-content
44
+ display: block;
@@ -0,0 +1 @@
1
+ @import 'blueberry_cms/*'
@@ -0,0 +1,50 @@
1
+ module BlueberryCMS
2
+ module Admin
3
+ class MenusController < BlueberryCMS.page_admin_controller.constantize
4
+ helper BlueberryCMS::PagesHelper
5
+ before_action :find_menu, only: %i(edit update destroy)
6
+
7
+ def index
8
+ @menus = Menu.ordered
9
+ end
10
+
11
+ def new
12
+ @menu = Menu.new
13
+ end
14
+
15
+ def create
16
+ @menu = Menu.new(menu_params)
17
+ if @menu.save
18
+ redirect_to(params[:continue] ? [:edit, :admin, @menu] : [:admin, :menus])
19
+ else
20
+ render :new
21
+ end
22
+ end
23
+
24
+ def edit; end
25
+
26
+ def update
27
+ if @menu.update(menu_params)
28
+ redirect_to(params[:continue] ? [:edit, :admin, @menu] : [:admin, :menus])
29
+ else
30
+ render :edit
31
+ end
32
+ end
33
+
34
+ def destroy
35
+ @menu.destroy
36
+ redirect_to [:admin, :menus]
37
+ end
38
+
39
+ private
40
+
41
+ def menu_params
42
+ params.require(:menu).permit!
43
+ end
44
+
45
+ def find_menu
46
+ @menu = Menu.find(params[:id])
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,8 +1,13 @@
1
1
  module BlueberryCMS
2
2
  module Admin
3
3
  class PagesController < BlueberryCMS.page_admin_controller.constantize
4
+ include Wisper::Publisher
5
+ helper BlueberryCMS::PagesHelper
6
+
7
+ after_action :refresh_sitemap, only: %i(update create destroy)
8
+
4
9
  def index
5
- @pages = Page.all
10
+ @pages = Page.roots
6
11
  end
7
12
 
8
13
  def new
@@ -13,7 +18,7 @@ module BlueberryCMS
13
18
  def create
14
19
  @page = Page.new(page_params)
15
20
  if @page.save
16
- redirect_to [:admin, :pages]
21
+ redirect_to(params[:continue] ? [:edit, :admin, @page] : [:admin, :pages])
17
22
  else
18
23
  render :new
19
24
  end
@@ -25,11 +30,18 @@ module BlueberryCMS
25
30
 
26
31
  def update
27
32
  @page = Page.find(params[:id])
28
- p page_params.to_hash
29
33
  if @page.update_attributes(page_params)
30
- redirect_to [:admin, :pages]
34
+ respond_to do |format|
35
+ format.html {
36
+ redirect_to(params[:continue] ? [:edit, :admin, @page] : [:admin, :pages])
37
+ }
38
+ format.js { head :ok }
39
+ end
31
40
  else
32
- render :edit
41
+ respond_to do |format|
42
+ format.html { render :edit }
43
+ format.js { head :unprocessable_entity }
44
+ end
33
45
  end
34
46
  end
35
47
 
@@ -45,17 +57,11 @@ module BlueberryCMS
45
57
  private
46
58
 
47
59
  def page_params
48
- params.
49
- require(:page).
50
- permit(
51
- :parent_id, :name,
52
- slug_translations: [:cs, :en],
53
- blocks_attributes: [
54
- :_destroy, :id, :_type, :urls,
55
- page_ids: [],
56
- content_translations: [:cs, :en],
57
- ]
58
- )
60
+ params.require(:page).permit!
61
+ end
62
+
63
+ def refresh_sitemap
64
+ broadcast(:refresh_sitemap)
59
65
  end
60
66
  end
61
67
  end
@@ -1,7 +1,8 @@
1
1
  module BlueberryCMS
2
2
  class RootController < ApplicationController
3
3
  def index
4
- redirect_to I18n.with_locale(I18n.default_locale) { Page.root.to_path }
4
+ page = BlueberryCMS::Page.find_by!(path: "/#{params[:path]}")
5
+ redirect_to I18n.with_locale(I18n.default_locale) { page.to_path }
5
6
  end
6
7
  end
7
8
  end
@@ -0,0 +1,13 @@
1
+ class BlockDecorator < Draper::Decorator
2
+ delegate_all
3
+
4
+ def css_class
5
+ array = [object.css_class]
6
+ array << 'block--centered-reverse' if right?
7
+ array.join(' ')
8
+ end
9
+
10
+ def process_markdown(string)
11
+ h.sanitize Markdown.new(string).to_html, tags: %w(strong em)
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module BlueberryCMS
2
+ class LinkDecorator < BaseDecorator
3
+ def link_background
4
+ "background-image: url(#{image.url(:content)})" if image?
5
+ end
6
+
7
+ def link_url
8
+ page ? page.to_path : url
9
+ end
10
+
11
+ def link_title
12
+ page ? page.name : title
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,46 @@
1
+ module BlueberryCMS
2
+ class PageBlockDecorator < BaseDecorator
3
+ def block_object
4
+ is_a?(BlueberryCMS::PageBlocks::Shared) ? block.decorate : self
5
+ end
6
+
7
+ def computed_classes
8
+ array = [css_class]
9
+ array << "block--mt-#{top_margin}" if top_margin?
10
+ array << "block--mt-#{top_margin_xs}-mobile" if top_margin_xs?
11
+
12
+ array << "block--mb-#{bottom_margin}" if bottom_margin?
13
+ array << "block--mb-#{bottom_margin_xs}-mobile" if bottom_margin_xs?
14
+ array << "block--gallery-text-#{orientation}" if respond_to?(:orientation)
15
+ array << 'block--bg-fractals white' if try(:red_background)
16
+
17
+ if object.is_a?(BlueberryCMS::PageBlocks::VideoGallery)
18
+ array << 'block--bg-fractals white block--videogallery'
19
+ end
20
+
21
+ array.join(' ')
22
+ end
23
+
24
+ def label
25
+ text = if object.respond_to?(:name)
26
+ object.name
27
+ elsif object.respond_to?(:title)
28
+ object.title
29
+ elsif object.respond_to?(:content)
30
+ h.strip_tags(object.content)
31
+ elsif object.is_a?(BlueberryCMS::PageBlocks::Shared)
32
+ [object.block&.page&.name, object.block&.decorate&.label].compact.join(' | ')
33
+ end
34
+
35
+ [object.model_name.human, h.truncate(text, length: 90)].compact.join(' - ')
36
+ end
37
+
38
+ def name
39
+ process_markdown(object.name) if object.name.present?
40
+ end
41
+
42
+ def title
43
+ process_markdown(object.title) if object.title.present?
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ module BlueberryCMS
2
+ class PageDecorator < BaseDecorator
3
+ def name
4
+ process_markdown(object.name) if object.name.present?
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ module BlueberryCMS
2
+ module MenusHelper
3
+ def render_menu(slug)
4
+ menu = BlueberryCMS::Menu.find_by(slugs: slug)
5
+ safe_join(menu_links(menu.links)) if menu.links.any?
6
+ end
7
+
8
+ private
9
+
10
+ def link(link)
11
+ name = link.name.presence || link.page.name
12
+ url = link.page&.to_path || link.url
13
+
14
+ active_link_to name, anchored_link(url, link.anchor.presence), class: link.css_class.presence, active: :exclusive, target: link.new_window ? '_blank' : '_self'
15
+ end
16
+
17
+ def menu_links(links)
18
+ links.map do |link|
19
+ content_tag(:li, link(link))
20
+ end
21
+ end
22
+
23
+ def anchored_link(link, anchor)
24
+ [link, anchor.presence].compact.join('#')
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ module BlueberryCMS
2
+ module PagesHelper
3
+ def nested_set_options(klass, current_page = nil)
4
+ @cache ||= {}
5
+ @cache[klass] ||= klass.traverse(:depth_first)
6
+ @cache[klass].map do |page|
7
+ ["#{'–' * page.depth} #{page.name}", page.id, disabled: page == current_page ]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module BlueberryCMS
2
+ class Image
3
+ include Mongoid::Document
4
+
5
+ field :href, type: String
6
+ field :name, localize: true
7
+
8
+ mount_uploader :image, ImageUploader
9
+
10
+ def self.find(id)
11
+ _id = BSON::ObjectId.from_string(id)
12
+ page = BlueberryCMS::Page.find_by('blocks.images._id' => _id)
13
+ gallery = page.blocks.find_by('images._id' => _id)
14
+ gallery.images.find_by('_id' => _id)
15
+ end
16
+
17
+ embedded_in :attachable, polymorphic: true
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ module BlueberryCMS
2
+ class Link
3
+ include Mongoid::Document
4
+
5
+ field :css_class, type: String
6
+ field :title, type: String
7
+ field :description, type: String
8
+ field :url, type: String
9
+ field :page_id, type: BSON::ObjectId
10
+ field :image_tmp, type: String
11
+ field :percentage, type: String
12
+
13
+ embedded_in :links, class_name: 'BlueberryCMS::PageBlocks::Links'
14
+
15
+ mount_uploader :image, ImageUploader
16
+
17
+ def self.find(id)
18
+ _id = BSON::ObjectId.from_string(id)
19
+ page = BlueberryCMS::Page.find_by('blocks.links._id' => _id)
20
+ links = page.blocks.find_by('links._id' => _id)
21
+ links.links.find_by('_id' => _id)
22
+ end
23
+
24
+ def page
25
+ Page.find(page_id) if page_id
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ module BlueberryCMS
2
+ class Menu
3
+ include Mongoid::Document
4
+ include Mongoid::Slug
5
+
6
+ field :name, type: String
7
+ validates :name, presence: true
8
+
9
+ slug :name
10
+
11
+ embeds_many :links, class_name: 'BlueberryCMS::MenuLink',
12
+ cascade_callbacks: true,
13
+ order: :position.asc
14
+
15
+ accepts_nested_attributes_for :links, allow_destroy: true
16
+
17
+ scope :ordered, -> { order(name: :asc) }
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ module BlueberryCMS
2
+ class MenuLink
3
+ include Mongoid::Document
4
+
5
+ field :anchor, localize: true
6
+ field :css_class
7
+ field :name, localize: true
8
+ field :page_id, type: BSON::ObjectId
9
+ field :position, type: Integer
10
+ field :new_window, type: Boolean
11
+ field :url, type: String, localize: true
12
+
13
+ embedded_in :menu, class_name: 'BlueberryCMS::Menu'
14
+
15
+ before_save :assign_default_position, if: :assign_default_position?
16
+
17
+ def page
18
+ Page.find(page_id) if page_id
19
+ end
20
+
21
+ private
22
+
23
+ def assign_default_position
24
+ links = menu.links
25
+ self.position = if links.where(:position.ne => nil).any?
26
+ links.where(:position.ne => nil).last.position + 1
27
+ else
28
+ 0
29
+ end
30
+ end
31
+
32
+ def assign_default_position?
33
+ position.nil?
34
+ end
35
+ end
36
+ end
@@ -2,42 +2,93 @@ module BlueberryCMS
2
2
  class Page
3
3
  include Mongoid::Document
4
4
  include Mongoid::Tree
5
+ include Mongoid::Tree::Traversal
5
6
  include Mongoid::Tree::Ordering
7
+ include Mongoid::Slug
8
+ include BlueberryCMS::Sortable
6
9
 
7
- field :name
8
- field :published_at, type: DateTime
9
- field :meta_title, localize: true
10
+ field :active, localize: true, type: Boolean
11
+ field :custom_slug, localize: true
10
12
  field :meta_description, localize: true
11
- field :meta_keywordds, localize: true, type: Array
12
- field :slug, localize: true
13
+ field :meta_keywords, localize: true, type: Array
14
+ field :meta_title, localize: true
15
+ field :name, localize: true
13
16
  field :path, localize: true
17
+ field :published_at, type: DateTime
18
+ field :show_in_footer, type: Boolean
19
+ field :show_in_menu, type: Boolean
20
+ field :slug, localize: true
21
+
22
+ embeds_many :blocks, class_name: 'BlueberryCMS::PageBlock',
23
+ cascade_callbacks: true,
24
+ order: :position.asc
25
+
26
+ slug :slug_source, localize: true
14
27
 
15
- embeds_many :blocks, class_name: 'BlueberryCMS::PageBlock'
16
28
  accepts_nested_attributes_for :blocks, allow_destroy: true
17
29
 
18
30
  validates :path, uniqueness: true
31
+ validates :name, presence: true
32
+
33
+ after_save :rebuild_children_paths
19
34
 
35
+ before_destroy :ensure_root, :move_children_to_parent
20
36
  after_rearrange :rebuild_path
21
37
 
22
- before_destroy :move_children_to_parent
38
+ scope :active, -> { where(active: true) }
39
+ scope :in_menu, -> { where(show_in_menu: true) }
40
+ scope :in_footer, -> { where(show_in_footer: true) }
41
+ scope :ordered, lambda {
42
+ order(name: :asc).collation(locale: 'cs', strength: 1)
43
+ }
23
44
 
24
- def path
25
- root? ? '' : super
45
+ def slug_source
46
+ custom_slug.presence || name
47
+ end
48
+
49
+ def rebuild_children_paths
50
+ if %i[custom_slug name].any? { |f| attribute_changed? f.to_s }
51
+ children.each(&:save)
52
+ end
26
53
  end
27
54
 
28
55
  def to_path
29
56
  "/#{I18n.locale}#{path}"
30
57
  end
31
58
 
59
+ def name_translations=(attributes)
60
+ attributes.stringify_keys!
61
+ primary_locale_name = attributes[I18n.default_locale.to_s]
62
+ empty_locale_keys = attributes.select { |_, v| v.blank? || v.empty? }.keys
63
+
64
+ empty_locale_keys.each do |locale|
65
+ attributes[locale] = primary_locale_name
66
+ end
67
+
68
+ super
69
+ end
70
+
32
71
  private
33
72
 
73
+ def ensure_root
74
+ if root?
75
+ errors.add(:base, :invalid)
76
+ throw :abort
77
+ end
78
+ end
79
+
34
80
  def rebuild_path
35
81
  self.path_translations = I18n.available_locales.each_with_object({}) do |locale, translations|
36
82
  I18n.with_locale(locale) do
37
- pages = self.ancestors_and_self.collect(&:slug).select(&:present?)
38
- translations[locale] = '/' + pages.join('/')
83
+ translations[locale] = generate_path
39
84
  end
40
85
  end
41
86
  end
87
+
88
+ def generate_path
89
+ return '/' if root?
90
+
91
+ [parent.path, slug_builder.to_url].join('/').gsub('//', '/')
92
+ end
42
93
  end
43
94
  end