seiten 0.0.7 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +5 -5
  2. data/Rakefile +1 -0
  3. data/app/controllers/seiten/pages_controller.rb +2 -19
  4. data/config/initializers/seiten.rb +1 -1
  5. data/lib/seiten/errors/base_error.rb +4 -0
  6. data/lib/seiten/errors/page_error.rb +4 -0
  7. data/lib/seiten/errors/routing_error.rb +7 -0
  8. data/lib/seiten/helpers/backend.rb +23 -0
  9. data/lib/seiten/helpers/current.rb +33 -0
  10. data/lib/seiten/helpers/frontend.rb +19 -0
  11. data/lib/seiten/html/breadcrumb.rb +41 -0
  12. data/lib/seiten/html/helpers.rb +32 -0
  13. data/lib/seiten/html/navigation.rb +39 -0
  14. data/lib/seiten/navigation.rb +43 -0
  15. data/lib/seiten/page.rb +71 -49
  16. data/lib/seiten/page_collection.rb +54 -0
  17. data/lib/seiten/page_collection_builder.rb +63 -0
  18. data/lib/seiten/railtie.rb +7 -0
  19. data/lib/seiten/routes_helper.rb +16 -11
  20. data/lib/seiten/slug_builder.rb +32 -0
  21. data/lib/seiten/version.rb +1 -1
  22. data/lib/seiten.rb +63 -13
  23. data/test/controllers/helper_methods_test.rb +25 -0
  24. data/test/controllers/pages_controller_test.rb +9 -0
  25. data/test/controllers/posts_controller_test.rb +12 -0
  26. data/test/controllers/seiten/pages_controller_test.rb +39 -0
  27. data/test/dummy/app/controllers/application_controller.rb +10 -0
  28. data/test/dummy/app/controllers/pages_controller.rb +1 -1
  29. data/test/dummy/app/controllers/posts_controller.rb +10 -0
  30. data/test/dummy/app/helpers/application_helper.rb +1 -0
  31. data/test/dummy/app/pages/{de → application/de}/produkte.html.erb +0 -0
  32. data/test/dummy/app/pages/{en/about/our-team/switzerland.html.erb → application/en/about/our-team/italy.html.erb} +0 -0
  33. data/test/dummy/app/pages/{en/about/works.html.erb → application/en/about/our-team/switzerland.html.erb} +0 -0
  34. data/test/dummy/app/pages/application/en/about/our-team.html.erb +2 -0
  35. data/test/dummy/app/pages/application/en/about/partners.html.erb +1 -0
  36. data/test/dummy/app/pages/{en/contact.html.erb → application/en/about/works.html.erb} +0 -0
  37. data/test/dummy/app/pages/{en/about/our-team/italy.html.erb → application/en/about.html.erb} +0 -0
  38. data/test/dummy/app/pages/{en/products/logo-design.html.erb → application/en/contact.html.erb} +0 -0
  39. data/test/dummy/app/pages/{en → application/en}/home.html.erb +0 -0
  40. data/test/dummy/app/pages/{en/products/web-development.html.erb → application/en/products/hire-us.html.erb} +0 -0
  41. data/test/dummy/{db/test.sqlite3 → app/pages/application/en/products/logo-design.html.erb} +0 -0
  42. data/test/dummy/app/pages/application/en/products/web-development.html.erb +0 -0
  43. data/test/dummy/app/pages/{en → application/en}/products.html.erb +0 -0
  44. data/test/dummy/app/pages/{localization.html.erb → application/localization.html.erb} +0 -0
  45. data/test/dummy/app/pages/help/en/home.html.erb +0 -0
  46. data/test/dummy/app/pages/help/en/logging-in.html.erb +0 -0
  47. data/test/dummy/app/views/layouts/application.html.erb +1 -1
  48. data/test/dummy/app/views/layouts/home.html.erb +1 -1
  49. data/test/dummy/app/views/pages/secret.html.erb +1 -1
  50. data/test/dummy/app/views/posts/index.html.erb +1 -0
  51. data/test/dummy/config/application.rb +4 -41
  52. data/test/dummy/config/boot.rb +2 -9
  53. data/test/dummy/config/cable.yml +9 -0
  54. data/test/dummy/config/environments/development.rb +26 -21
  55. data/test/dummy/config/environments/production.rb +3 -0
  56. data/test/dummy/config/environments/test.rb +15 -19
  57. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  58. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  59. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  60. data/test/dummy/config/initializers/inflections.rb +6 -5
  61. data/test/dummy/config/initializers/mime_types.rb +0 -1
  62. data/test/dummy/config/initializers/new_framework_defaults.rb +20 -0
  63. data/test/dummy/config/initializers/session_store.rb +1 -6
  64. data/test/dummy/config/initializers/wrap_parameters.rb +5 -5
  65. data/test/dummy/config/{navigation/de.yml → navigations/application.de.yml} +5 -5
  66. data/test/dummy/config/{navigation.yml → navigations/application.en.yml} +21 -5
  67. data/test/dummy/config/navigations/help.en.yml +17 -0
  68. data/test/dummy/config/routes.rb +6 -3
  69. data/test/dummy/config/secrets.yml +22 -0
  70. data/test/dummy/log/development.log +1716 -4558
  71. data/test/dummy/log/test.log +43833 -13898
  72. data/test/fixtures/breadcrumb.html +1 -0
  73. data/test/fixtures/navigation.html +1 -0
  74. data/test/integration/layout_test.rb +10 -11
  75. data/test/integration/navigation_test.rb +50 -50
  76. data/test/lib/seiten/helpers/frontend_test.rb +37 -0
  77. data/test/lib/seiten/html/breadcrumb_test.rb +29 -0
  78. data/test/lib/seiten/html/helpers_test.rb +55 -0
  79. data/test/lib/seiten/html/navigation_test.rb +29 -0
  80. data/test/lib/seiten/navigation_test.rb +45 -0
  81. data/test/lib/seiten/page_collection_builder_test.rb +141 -0
  82. data/test/lib/seiten/page_collection_test.rb +59 -0
  83. data/test/lib/seiten/page_test.rb +188 -0
  84. data/test/lib/seiten/slug_builder_test.rb +47 -0
  85. data/test/lib/seiten_test.rb +16 -0
  86. data/test/test_helper.rb +2 -8
  87. metadata +147 -93
  88. data/app/helpers/seiten_helper.rb +0 -46
  89. data/lib/seiten/controllers/helpers.rb +0 -16
  90. data/lib/seiten/page_store.rb +0 -160
  91. data/test/dummy/app/assets/javascripts/application.js +0 -15
  92. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  93. data/test/dummy/app/pages/en/about/our-team.html.erb +0 -2
  94. data/test/dummy/app/pages/en/about/partners.html.erb +0 -1
  95. data/test/dummy/config/navigation/en.yml +0 -37
  96. data/test/dummy/db/development.sqlite3 +0 -0
  97. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  98. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  99. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  100. data/test/dummy/tmp/pids/server.pid +0 -1
  101. data/test/integration/i18n_test.rb +0 -31
  102. data/test/integration/redirect_test.rb +0 -15
  103. data/test/page_store_test.rb +0 -28
  104. data/test/page_test.rb +0 -98
  105. data/test/seiten_test.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: aac1c7e2cff18662cca1155e49a8f43b13df73f7
4
- data.tar.gz: c6e449e0518a93591b26832d3c3dfa94aacef1c9
2
+ SHA256:
3
+ metadata.gz: 83d788eadd214b82c9e91e8da1a0d72d050a7d1bb46c635db58aefffd5f48712
4
+ data.tar.gz: 469118c143991e25fcb35e5f5e8d55e58a6255a412e5d5cc40aad031e99f8ff1
5
5
  SHA512:
6
- metadata.gz: 117b93f29193643c09bdaff2e2b663c9e636907c6e18ec6f300302fbe51bfca58ac69d0f14ca05a73b0bfdf759368e14973da4a24426367887e1b0b887bd2903
7
- data.tar.gz: dee87d889d81b4d9698dd14c1e2453f1a1a4c5dcda62798d9f8b7c3841d8e4876ab5ee8c075b222058f4ace35ef0d31b8a25148c5da4fb1154dcd0bc33c1b20f
6
+ metadata.gz: 6e1a3a500817fed2ee4f2a9498f8369f0b721e7cc3ce34c4982578cc397f972bb783fa5b964fd9dcce40f0da64954903ac8f77d4fe1b2bb0120bddc9514f90ba
7
+ data.tar.gz: da0aeed08ad91cee1183e7a3266f213d047d84a1ebf0ac0c99f240504865ad31f38709e1e6d72ef0be5c37a3952b5df94dd68359b36a5a1051703742580c3897
data/Rakefile CHANGED
@@ -26,6 +26,7 @@ Rake::TestTask.new(:test) do |t|
26
26
  t.libs << 'test'
27
27
  t.pattern = 'test/**/*_test.rb'
28
28
  t.verbose = false
29
+ t.warning = false
29
30
  end
30
31
 
31
32
 
@@ -1,26 +1,9 @@
1
1
  module Seiten
2
2
  class PagesController < ::ApplicationController
3
+ include Seiten::Helpers::Backend
3
4
 
4
5
  def show
5
- if current_page.nil?
6
- raise ActionController::RoutingError.new("Page /#{params[:page]} not found")
7
- else
8
- @title = current_page.title
9
-
10
- if params[:page]
11
- filename = params[:page]
12
- else
13
- filename = Seiten.config[:root_page_filename]
14
- end
15
-
16
- file = Seiten::PageStore.current.file_path(filename: filename)
17
-
18
- if current_page.layout
19
- render file: file, layout: current_page.layout
20
- else
21
- render file: file
22
- end
23
- end
6
+ render_seiten_page
24
7
  end
25
8
  end
26
9
  end
@@ -1 +1 @@
1
- Seiten::PageStore.initialize_page_stores
1
+ Seiten.initialize_navigations
@@ -0,0 +1,4 @@
1
+ module Seiten::Errors
2
+ class BaseError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Seiten::Errors
2
+ class PageError < BaseError
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Seiten::Errors
2
+ class RoutingError < BaseError
3
+ def backtrace
4
+ []
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ module Seiten
2
+ module Helpers
3
+ # Those helpers are convenience methods added to Seiten::PagesController or useful for building your own.
4
+ module Backend
5
+ extend ActiveSupport::Concern
6
+
7
+ def self.included(base)
8
+ base.prepend_view_path Seiten.config[:pages_dir]
9
+ base.before_action :raise_seiten_routing_error, unless: :current_page
10
+ end
11
+
12
+ private
13
+
14
+ def raise_seiten_routing_error
15
+ raise Seiten::Errors::RoutingError.new("Page /#{params[:slug]} not found")
16
+ end
17
+
18
+ def render_seiten_page
19
+ render current_page.template_path, layout: current_page.layout
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ module Seiten
2
+ module Helpers
3
+ # Those helpers are convenience methods added to ApplicationController.
4
+ module Current
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ if respond_to?(:helper_method)
9
+ helper_method :current_navigation
10
+ helper_method :current_page
11
+ end
12
+ end
13
+
14
+ def current_navigation
15
+ @current_navigation ||= set_current_navigation
16
+ end
17
+
18
+ def current_page
19
+ @current_page ||= set_current_page
20
+ end
21
+
22
+ private
23
+
24
+ def set_current_navigation
25
+ Seiten::Navigation.find_by(name: params[:navigation_id] || 'application', locale: params[:locale] || I18n.locale.to_s)
26
+ end
27
+
28
+ def set_current_page
29
+ current_navigation&.pages&.find_by(slug: params[:slug]) if params[:slug]
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Seiten
4
+ module Helpers
5
+ module Frontend
6
+ def link_to_seiten_page(page)
7
+ link_to page.title, page.path
8
+ end
9
+
10
+ def seiten_navigation(navigation = current_navigation, parent_id: nil, deep: 2, html: {})
11
+ Seiten::HTML::Navigation.new(self, navigation: navigation, parent_id: parent_id, current_page: current_page, deep: deep, html: html).body
12
+ end
13
+
14
+ def seiten_breadcrumb(separator: '>', html: {})
15
+ Seiten::HTML::Breadcrumb.new(self, page: current_page, separator: separator, html: html).body
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ module Seiten
2
+ module HTML
3
+ class Breadcrumb
4
+ attr_reader :body
5
+
6
+ def initialize(view_context, page:, separator: '>', html: {})
7
+ @view_context = view_context
8
+ @current_page = page
9
+ @separator = separator
10
+ @html_options = Seiten.config[:html].deep_merge(html || {})
11
+ @body = build_navigation if @current_page
12
+ end
13
+
14
+ private
15
+
16
+ def build_navigation
17
+ classes = Seiten::HTML::Helpers.build_classes(class_options: @html_options[:breadcrumb], modifier_options: @html_options[:modifier])
18
+ @view_context.content_tag(:ul, class: classes) do
19
+ pages = @current_page.breadcrumbs.each_with_index.map do |page, index|
20
+ build_page_element(page, index)
21
+ end
22
+ @view_context.safe_join(pages)
23
+ end
24
+ end
25
+
26
+ def build_page_element(page, index)
27
+ modifiers = page == @current_page ? [:current] : []
28
+ classes = Seiten::HTML::Helpers.build_classes(:item, modifiers: modifiers, class_options: @html_options[:breadcrumb], modifier_options: @html_options[:modifier])
29
+
30
+ @view_context.content_tag :li, class: classes do
31
+ if @separator && index.positive?
32
+ sep_class = Seiten::HTML::Helpers.build_classes(:separator, class_options: @html_options[:breadcrumb])
33
+ span = @view_context.content_tag(:span, @separator, class: sep_class)
34
+ end
35
+ link = @view_context.link_to_seiten_page(page)
36
+ @view_context.safe_join([span, link])
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ module Seiten
2
+ module HTML
3
+ module Helpers
4
+ def self.build_page_modifiers(page, current_page)
5
+ modifiers = []
6
+ modifiers << :parent if page.children?
7
+ if page.active?(current_page)
8
+ modifiers << :active
9
+ modifiers << (page == current_page ? :current : :expanded)
10
+ end
11
+ modifiers
12
+ end
13
+
14
+ def self.build_classes(element = nil, class_options:, modifier_options: [], modifiers: [], merge: nil)
15
+ classes = []
16
+
17
+ klass = class_options[element || :base]
18
+ classes << klass
19
+
20
+ if modifiers.any?
21
+ base = (modifier_options[:base].presence || klass)
22
+ modifiers.each do |modifier|
23
+ classes << "#{base}#{modifier_options[:separator]}#{modifier_options[modifier]}"
24
+ end
25
+ end
26
+
27
+ classes << merge if merge
28
+ classes.join(' ')
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,39 @@
1
+ module Seiten
2
+ module HTML
3
+ class Navigation
4
+ attr_reader :body
5
+
6
+ def initialize(view_context, navigation:, parent_id: nil, current_page: nil, deep: 2, html: {})
7
+ @view_context = view_context
8
+ @start_depth = deep
9
+ @html_options = Seiten.config[:html].deep_merge(html || {})
10
+ @current_page = current_page
11
+ @body = build_navigation(navigation, parent_id: parent_id, deep: deep)
12
+ end
13
+
14
+ private
15
+
16
+ def build_navigation(navigation, parent_id:, deep:)
17
+ wrapper_class = @start_depth != deep ? :nodes : nil
18
+
19
+ return unless deep.positive?
20
+
21
+ @view_context.content_tag(:ul, class: Seiten::HTML::Helpers.build_classes(wrapper_class, class_options: @html_options[:navigation], modifier_options: @html_options[:modifier])) do
22
+ pages = navigation.pages.where(parent_id: parent_id).map do |page|
23
+ children = build_navigation(navigation, parent_id: page.id, deep: deep - 1) if page.children?
24
+ build_page_element(page, children)
25
+ end
26
+ @view_context.safe_join(pages)
27
+ end
28
+ end
29
+
30
+ def build_page_element(page, children)
31
+ modifiers = Seiten::HTML::Helpers.build_page_modifiers(page, @current_page)
32
+ classes = Seiten::HTML::Helpers.build_classes(:item, modifiers: modifiers, merge: page.html_options[:class], class_options: @html_options[:navigation], modifier_options: @html_options[:modifier])
33
+ @view_context.content_tag(:li, page.html_options.merge(class: classes)) do
34
+ @view_context.safe_join([@view_context.link_to_seiten_page(page), children])
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,43 @@
1
+ module Seiten
2
+ class Navigation
3
+ attr_accessor :name, :locale, :config, :dir, :page_collection
4
+
5
+ def initialize(options={})
6
+ @name = options[:name].to_s
7
+ @locale = options[:locale].to_s
8
+ @config = options[:config] || File.join(Rails.root, Seiten.config[:config_dir], "#{id}.yml")
9
+ @dir = options[:dir] || File.join(Rails.root, Seiten.config[:pages_dir], @name, @locale)
10
+ @page_collection = Seiten::PageCollection.new(navigation_id: id)
11
+ end
12
+
13
+ class << self
14
+ def find_by(params={})
15
+ where(params).first
16
+ end
17
+
18
+ def where(params={})
19
+ Seiten.navigations.select do |navigation|
20
+ params.all? do |param|
21
+ navigation.send(param[0]) == param[1]
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def id
28
+ "%s.%s" % [name, locale]
29
+ end
30
+
31
+ def pages
32
+ page_collection
33
+ end
34
+
35
+ def pages=(pages_array)
36
+ page_collection.pages = pages_array.map { |page| page.navigation_id = id; page }
37
+ # return page_collection
38
+ # NOTE: This doesn't work and just returns page_array.
39
+ # I think because page_collection#pages= attr_accessor is called first
40
+ # and thus why our return call is ignored.
41
+ end
42
+ end
43
+ end
data/lib/seiten/page.rb CHANGED
@@ -1,54 +1,27 @@
1
- module Seiten
1
+ # frozen_string_literal: true
2
2
 
3
+ module Seiten
3
4
  class Page
4
-
5
- attr_accessor :id, :parent_id, :title, :children, :slug, :redirect, :layout
5
+ attr_accessor :navigation_id, :id, :parent_id, :title, :slug, :refer, :data, :html_options
6
+ attr_writer :layout
6
7
 
7
8
  # initialize Page object with attributes
8
9
  def initialize(options={})
9
- @id = options[:id]
10
- @parent_id = options[:parent_id]
11
- @title = options[:title]
12
- @slug = options[:slug]
13
- @external = options[:external]
14
- @redirect = options[:redirect]
15
- @layout = options[:layout]
10
+ @navigation_id = options[:navigation_id]
11
+ @id = options[:id]
12
+ @parent_id = options[:parent_id]
13
+ @title = options[:title]
14
+ @slug = options[:slug]
15
+ @refer = options[:refer]
16
+ @layout = options[:layout]
17
+ @data = options[:data].each_with_object({}){|(k,v), h| h[k.to_sym] = v} if options[:data]
18
+ @data ||= {}
19
+ @html_options = options[:html].each_with_object({}){|(k,v), h| h[k.to_sym] = v} if options[:html]
20
+ @html_options ||= {}
16
21
  end
17
22
 
18
- class << self
19
-
20
- def all
21
- Seiten::PageStore.current.pages
22
- end
23
-
24
- # find page by id
25
- def find(id)
26
- all.select { |page| page.id == id }.first
27
- end
28
-
29
- # find all pages by parent_id
30
- def find_by_parent_id(parent_id)
31
- all.select { |page| page.parent_id == parent_id }
32
- end
33
-
34
- # find a page by slug
35
- def find_by_slug(slug)
36
- if slug
37
- slug = slug[1..-1] if slug[0] == "/"
38
- end
39
- all.select { |page| page.slug == slug }.first
40
- end
41
-
42
- # get breadcrumb of given page (reversed)
43
- def get_breadcrumb(page)
44
- pages ||= []
45
- pages << page
46
- if page.parent
47
- pages << get_breadcrumb(page.parent)
48
- end
49
- pages.flatten
50
- end
51
-
23
+ def navigation
24
+ Seiten::Navigation.find_by(id: navigation_id)
52
25
  end
53
26
 
54
27
  # returns true if slug starts with http:// or https://
@@ -58,18 +31,41 @@ module Seiten
58
31
 
59
32
  # get parent of page
60
33
  def parent
61
- Page.find(parent_id)
34
+ navigation.pages.find(parent_id)
62
35
  end
63
36
 
64
37
  def parent?
65
38
  parent.present?
66
39
  end
67
40
 
68
- # TODO: Find a better name for this
41
+ def ancestors
42
+ return @ancestors unless @ancestors.nil?
43
+
44
+ @ancestors = []
45
+ return @ancestors unless parent?
46
+
47
+ ancestor = parent
48
+ loop do
49
+ @ancestors << ancestor
50
+ ancestor = ancestor.parent
51
+ break if ancestor.nil?
52
+ end
53
+
54
+ @ancestors
55
+ end
56
+
57
+ def self_and_ancestors
58
+ @self_and_ancestors ||= ancestors.insert(0, self)
59
+ end
60
+
61
+ def breadcrumbs
62
+ @breadcrumbs ||= self_and_ancestors.reverse
63
+ end
64
+
69
65
  # get root page of current page branch
70
- def branch_root
66
+ def root
71
67
  if self.parent?
72
- self.parent.branch_root
68
+ self.parent.root
73
69
  else
74
70
  self
75
71
  end
@@ -77,7 +73,11 @@ module Seiten
77
73
 
78
74
  # get children of page
79
75
  def children
80
- Page.all.select { |page| page.parent_id == id }
76
+ navigation.pages.where(parent_id: id)
77
+ end
78
+
79
+ def children?
80
+ navigation.pages.find_by(parent_id: id).present?
81
81
  end
82
82
 
83
83
  # true if child is children of page
@@ -104,5 +104,27 @@ module Seiten
104
104
  end
105
105
  end
106
106
  end
107
+
108
+ def template_path
109
+ [
110
+ navigation_id.gsub(/\./, '/'),
111
+ slug.present? ? slug : Seiten.config[:root_page]
112
+ ].join('/')
113
+ end
114
+ alias_method :to_s, :template_path
115
+
116
+ def path
117
+ return refer if refer
118
+ return '#' if slug.nil?
119
+ return slug if external?
120
+
121
+ navigation_name = navigation.name == 'application' ? nil : navigation.name
122
+
123
+ [:seiten, navigation_name.try(:to_sym), :page, { slug: slug }]
124
+ end
125
+
126
+ def layout
127
+ @layout || Seiten.config[:default_layout]
128
+ end
107
129
  end
108
130
  end
@@ -0,0 +1,54 @@
1
+ module Seiten
2
+ class PageCollection
3
+ attr_accessor :navigation_id, :pages
4
+
5
+ def initialize(options = {})
6
+ @navigation_id = options[:navigation_id]
7
+ @pages = options[:pages] || []
8
+ end
9
+
10
+ def navigation
11
+ Seiten::Navigation.find_by(id: navigation_id)
12
+ end
13
+
14
+ def build(options = {})
15
+ Seiten::PageCollectionBuilder.call(self, options)
16
+ end
17
+
18
+ def all
19
+ pages.to_a
20
+ end
21
+
22
+ def find(id)
23
+ find_by(id: id)
24
+ end
25
+
26
+ def find_by(params)
27
+ @find_by ||= {}
28
+ return @find_by[params] if @find_by.key?(params)
29
+
30
+ @find_by[params] = pages.find do |page|
31
+ params.all? do |k, v|
32
+ page.send(k) == v
33
+ end
34
+ end
35
+ end
36
+
37
+ def where(params)
38
+ @where ||= {}
39
+ return @where[params] if @where.key?(params)
40
+
41
+ @where[params] = pages.select do |page|
42
+ params.all? do |k, v|
43
+ page.send(k) == v
44
+ end
45
+ end
46
+ end
47
+
48
+ def new(params = {})
49
+ page = Seiten::Page.new(params.merge(navigation_id: navigation_id))
50
+ pages << page
51
+ page
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,63 @@
1
+ module Seiten
2
+ class PageCollectionBuilder
3
+ def self.call(page_collection, options={})
4
+ pages = options[:pages]
5
+ parent_id = options[:parent_id] # || nil
6
+ layout = options[:layout]
7
+ prefix_url = options[:prefix_url] || ""
8
+
9
+ @id ||= 1
10
+ @parsed_pages ||= []
11
+
12
+ pages.each_index do |i|
13
+
14
+ # Load page and set parent_id and generated page id
15
+ page = pages[i]
16
+ page["id"] = @id
17
+ page["parent_id"] = parent_id
18
+ page["layout"] ||= layout
19
+
20
+ # Increment generated id
21
+ @id += 1
22
+
23
+ # Build slug
24
+ raise Errors::PageError, "The `url` option can not be an external path. Use the `refer` option to link to external resources." if page["url"] && !!(page["url"].match(/^https?:\/\/.+/))
25
+ slug = Seiten::SlugBuilder.call(page, prefix_url) unless page['url'].is_a?(FalseClass)
26
+
27
+ # Set refer
28
+ if page["refer"]
29
+ if page["refer"].is_a?(TrueClass)
30
+ page["refer"] = "/" + Seiten::SlugBuilder.call(page["nodes"].first, page["slug"])
31
+ end
32
+ raise Errors::PageError, "The `refer` option must be `true` or an absolute or external path" if page["refer"] != true && page["refer"][0] != "/" && !(page["refer"].match(/^https?:\/\/.+/))
33
+ else
34
+ page["slug"] = slug
35
+ end
36
+
37
+ # Set layout
38
+ if page["layout"]
39
+ if page["layout"].is_a?(String)
40
+ inherited_layout = page["layout"]
41
+ elsif page["layout"].is_a?(Hash)
42
+ if page["layout"]["inherit"]
43
+ inherited_layout = page["layout"]
44
+ else
45
+ inherited_layout = nil
46
+ end
47
+ page["layout"] = page["layout"]["name"]
48
+ end
49
+ end
50
+
51
+ # Load children
52
+ if page["nodes"]
53
+ self.call(page_collection, pages: page["nodes"], parent_id: page["id"], prefix_url: slug, layout: inherited_layout, external: page["external"])
54
+ end
55
+
56
+ page_params = page.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
57
+ @parsed_pages << page_collection.new(page_params)
58
+ end
59
+
60
+ @parsed_pages
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,7 @@
1
+ module Seiten
2
+ class Railtie < Rails::Railtie
3
+ config.action_dispatch.rescue_responses.merge!(
4
+ 'Seiten::Errors::RoutingError' => :not_found
5
+ )
6
+ end
7
+ end
@@ -1,16 +1,21 @@
1
1
  class ActionDispatch::Routing::Mapper
2
+ def seiten(*resources)
3
+ options = resources.extract_options!
4
+ options[:to] ||= 'seiten/pages#show'
2
5
 
3
- def seiten_resources
4
- Seiten::PageStore.storages.each do |page_store|
5
- page_store.pages.each do |page|
6
- if page.redirect
7
- get page.slug, to: redirect { |p, req|
8
- Rails.application.routes.url_helpers.seiten_page_path(page: page.redirect, locale: p[:locale])
9
- }, as: nil
10
- end
11
- end
12
- end
6
+ resources.each do |resource|
7
+ resource_options = options.dup
8
+
9
+ resource_options[:as] ||= resource == :application ? :seiten_page : "seiten_#{resource}_page"
10
+
11
+ resource_options[:defaults] ||= {}
12
+ resource_options[:defaults][:navigation_id] = resource.to_s unless resource == :application
13
+ resource_options[:defaults][:slug] = ''
13
14
 
14
- get "(*page)" => "seiten/pages#show", as: :seiten_page
15
+ # NOTE: See https://github.com/rails/rails/issues/31228
16
+ resource_options[:constraints] ||= ->(req) { req.path.exclude? 'rails/active_storage' }
17
+
18
+ get '(*slug)', resource_options
19
+ end
15
20
  end
16
21
  end
@@ -0,0 +1,32 @@
1
+ module Seiten
2
+ class SlugBuilder
3
+
4
+ def self.call(page_options, prefix_url='')
5
+ page_options = page_options.with_indifferent_access
6
+ title = page_options['title']
7
+ url = page_options['url']
8
+ root = page_options['root']
9
+
10
+ # if url is nil parameterize title otherwise just use url
11
+ slug = url.nil? ? title.parameterize : url
12
+
13
+ # prepend prefix_url if slug is not root or external url
14
+ unless slug[0] == "/" || !!(slug.match(/^https?:\/\/.+/)) || !prefix_url.present?
15
+ slug = "#{prefix_url}/#{slug}"
16
+ end
17
+
18
+ # return empty string if page slug is /
19
+ if slug == "/" || root == true
20
+ slug = ""
21
+ end
22
+
23
+ # remove leading slash if present
24
+ if slug
25
+ slug = slug[1..-1] if slug[0] == "/"
26
+ end
27
+
28
+ slug
29
+ end
30
+
31
+ end
32
+ end
@@ -1,3 +1,3 @@
1
1
  module Seiten
2
- VERSION = "0.0.7"
2
+ VERSION = "1.0.1"
3
3
  end