seiten 0.0.8 → 1.0.0

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 (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