seiten 0.0.6 → 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 -23
  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 +82 -40
  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.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 +1632 -8652
  71. data/test/dummy/log/test.log +43833 -13664
  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 +136 -94
  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 -150
  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 -37
  102. data/test/integration/redirect_test.rb +0 -15
  103. data/test/page_test.rb +0 -74
  104. data/test/seiten_test.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c07bb134e2faeb0ba5dd11af57a067fef28ceeb2
4
- data.tar.gz: 94f0e43ea9839d4bf1598ef7c63e0c8bb39a590a
2
+ SHA256:
3
+ metadata.gz: 3e17a2fa52d374492d7a6598c5e88c4d81935b091158a60bb14d298fd83469be
4
+ data.tar.gz: 4cb163a2fc0399bd5ab1267790907c6fb356f7d55996dd9b08c6a90c0a51166f
5
5
  SHA512:
6
- metadata.gz: 341550a0f7cdd4b7e6a9a01b685c70796b6ec8007b13256482c5a028c95e0ada6d42e164994926c5cf4307d819d085944c10874e3e91ca2c9de95e10ef8defb6
7
- data.tar.gz: 6657f6f1f45308fcab547c3dff423355c8ac887a154178a545230647829a824ace2361d921c3d94e6739288fe3a99a52a4b9f36d8ad586ebddd9f498b913bcbf
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,30 +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
- if File.exists? Seiten::PageStore.current.file_path(filename: "#{filename}.html.erb", locale: I18n.locale)
17
- file = Seiten::PageStore.current.file_path(filename: filename, locale: I18n.locale)
18
- else
19
- file = Seiten::PageStore.current.file_path(filename: filename)
20
- end
21
-
22
- if current_page.layout
23
- render file: file, layout: current_page.layout
24
- else
25
- render file: file
26
- end
27
- end
6
+ render_seiten_page
28
7
  end
29
8
  end
30
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,63 +1,83 @@
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
- @redirect = options[:redirect]
14
- @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 ||= {}
15
21
  end
16
22
 
17
- class << self
23
+ def navigation
24
+ Seiten::Navigation.find_by(id: navigation_id)
25
+ end
18
26
 
19
- def all
20
- Seiten::PageStore.current.pages
21
- end
27
+ # returns true if slug starts with http:// or https://
28
+ def external?
29
+ !!(slug.match(/^https?:\/\/.+/))
30
+ end
22
31
 
23
- # find page by id
24
- def find(id)
25
- all.select { |page| page.id == id }.first
26
- end
32
+ # get parent of page
33
+ def parent
34
+ navigation.pages.find(parent_id)
35
+ end
27
36
 
28
- # find all pages by parent_id
29
- def find_by_parent_id(parent_id)
30
- all.select { |page| page.parent_id == parent_id }
31
- end
37
+ def parent?
38
+ parent.present?
39
+ end
32
40
 
33
- # find a page by slug
34
- def find_by_slug(slug)
35
- if slug
36
- slug = slug[1..-1] if slug[0] == "/"
37
- end
38
- all.select { |page| page.slug == slug }.first
39
- end
41
+ def ancestors
42
+ return @ancestors unless @ancestors.nil?
40
43
 
41
- # get breadcrumb of given page (reversed)
42
- def get_breadcrumb(page)
43
- pages ||= []
44
- pages << page
45
- if page.parent
46
- pages << get_breadcrumb(page.parent)
47
- end
48
- pages.flatten
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?
49
52
  end
50
53
 
54
+ @ancestors
51
55
  end
52
56
 
53
- # get parent of page
54
- def parent
55
- Page.find(parent_id)
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
+
65
+ # get root page of current page branch
66
+ def root
67
+ if self.parent?
68
+ self.parent.root
69
+ else
70
+ self
71
+ end
56
72
  end
57
73
 
58
74
  # get children of page
59
75
  def children
60
- 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?
61
81
  end
62
82
 
63
83
  # true if child is children of page
@@ -84,5 +104,27 @@ module Seiten
84
104
  end
85
105
  end
86
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
87
129
  end
88
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
- }
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.6"
2
+ VERSION = "1.0.0"
3
3
  end