seiten 0.0.8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +5 -5
  2. data/Rakefile +1 -0
  3. data/app/controllers/seiten/pages_controller.rb +2 -18
  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 +4 -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 -50
  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 -12
  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/en.yml → navigations/application.en.yml} +15 -7
  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 -4559
  71. data/test/dummy/log/test.log +43833 -16254
  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 +134 -78
  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 -165
  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.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/integration/i18n_test.rb +0 -31
  101. data/test/integration/redirect_test.rb +0 -15
  102. data/test/page_store_test.rb +0 -28
  103. data/test/page_test.rb +0 -104
  104. data/test/seiten_test.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 048ecf4f24e37168dfc694a467371919f46ce631
4
- data.tar.gz: 63c13ce42bc05f60039f5e0f437d3f9810f72e85
2
+ SHA256:
3
+ metadata.gz: 3e17a2fa52d374492d7a6598c5e88c4d81935b091158a60bb14d298fd83469be
4
+ data.tar.gz: 4cb163a2fc0399bd5ab1267790907c6fb356f7d55996dd9b08c6a90c0a51166f
5
5
  SHA512:
6
- metadata.gz: a123a3ecdbdb8d2e529169b352bf2a242abc8f52d0b89902a7a09af951423ef87aec1a8ac117c5eb1c93f4cb4a4b920eb764a9d81e71f5f699aaa0c0f80f3b30
7
- data.tar.gz: 2489e06d4d622e9ae121f50ef73f803600c6be8387afe4764931613395ca11e3aa55cfad861e0f08fc89d1ffeb780f1a31e7c1c8e51a801bfd5fbde8b69d2591
6
+ metadata.gz: 6d2e231683fa2bb4f8158211d8ab0b22f32093948792dce08e6dcff3011959deeaa61fc18d434a8dd73100b9e458dcb272a84c65fdd34d2c609b5442a03da8f9
7
+ data.tar.gz: a3f7f85d5196780920a259229c960d524176c127c102990c313ab161cdeb020f0f390e4a6130011528656562220f1ab5b34268507cf1ac9446c8602ade8bd281
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,25 +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
-
9
- if params[:page]
10
- filename = params[:page]
11
- else
12
- filename = Seiten.config[:root_page_filename]
13
- end
14
-
15
- file = Seiten::PageStore.current.file_path(filename: filename)
16
-
17
- if current_page.layout
18
- render file: file, layout: current_page.layout
19
- else
20
- render file: file
21
- end
22
- end
6
+ render_seiten_page
23
7
  end
24
8
  end
25
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,4 @@
1
+ module Seiten::Errors
2
+ class RoutingError < BaseError
3
+ end
4
+ 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,55 +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, :metadata
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]
16
- @metadata = options[:metadata].each_with_object({}){|(k,v), h| h[k.to_sym] = v} if options[:metadata]
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 ||= {}
17
21
  end
18
22
 
19
- class << self
20
-
21
- def all
22
- Seiten::PageStore.current.pages
23
- end
24
-
25
- # find page by id
26
- def find(id)
27
- all.select { |page| page.id == id }.first
28
- end
29
-
30
- # find all pages by parent_id
31
- def find_by_parent_id(parent_id)
32
- all.select { |page| page.parent_id == parent_id }
33
- end
34
-
35
- # find a page by slug
36
- def find_by_slug(slug)
37
- if slug
38
- slug = slug[1..-1] if slug[0] == "/"
39
- end
40
- all.select { |page| page.slug == slug }.first
41
- end
42
-
43
- # get breadcrumb of given page (reversed)
44
- def get_breadcrumb(page)
45
- pages ||= []
46
- pages << page
47
- if page.parent
48
- pages << get_breadcrumb(page.parent)
49
- end
50
- pages.flatten
51
- end
52
-
23
+ def navigation
24
+ Seiten::Navigation.find_by(id: navigation_id)
53
25
  end
54
26
 
55
27
  # returns true if slug starts with http:// or https://
@@ -59,18 +31,41 @@ module Seiten
59
31
 
60
32
  # get parent of page
61
33
  def parent
62
- Page.find(parent_id)
34
+ navigation.pages.find(parent_id)
63
35
  end
64
36
 
65
37
  def parent?
66
38
  parent.present?
67
39
  end
68
40
 
69
- # 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
+
70
65
  # get root page of current page branch
71
- def branch_root
66
+ def root
72
67
  if self.parent?
73
- self.parent.branch_root
68
+ self.parent.root
74
69
  else
75
70
  self
76
71
  end
@@ -78,7 +73,11 @@ module Seiten
78
73
 
79
74
  # get children of page
80
75
  def children
81
- 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?
82
81
  end
83
82
 
84
83
  # true if child is children of page
@@ -105,5 +104,27 @@ module Seiten
105
104
  end
106
105
  end
107
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
108
129
  end
109
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.8"
2
+ VERSION = "1.0.0"
3
3
  end