aerogel-pages 1.4.12

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 (169) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +14 -0
  6. data/Rakefile +1 -0
  7. data/aerogel-pages.gemspec +26 -0
  8. data/app/helpers/README.md +7 -0
  9. data/app/helpers/decorators.rb +74 -0
  10. data/app/helpers/pages.rb +32 -0
  11. data/app/routes/admin-pages.rb +150 -0
  12. data/app/routes/pages.rb +16 -0
  13. data/assets/javascripts/admin-pages/pages-widget.js.coffee +83 -0
  14. data/assets/javascripts/admin-pages/pane-preview.js.coffee +37 -0
  15. data/assets/javascripts/admin-pages/pane-tree.js.coffee +105 -0
  16. data/assets/javascripts/admin-pages-edit/admin-modal-select.js.coffee +63 -0
  17. data/assets/javascripts/admin-pages-edit/datetime-picker-field.js.coffee +36 -0
  18. data/assets/javascripts/admin-pages-edit/page-blocks.js.coffee +71 -0
  19. data/assets/javascripts/admin-pages-edit/page-content-tabs.js.coffee +40 -0
  20. data/assets/javascripts/admin-pages-utils/attached-footer.js.coffee +62 -0
  21. data/assets/javascripts/admin-pages-utils/autofixed-height.js.coffee +15 -0
  22. data/assets/javascripts/admin-pages-utils/two-pane-widget.js.coffee +78 -0
  23. data/assets/javascripts/aerogel-pages.js.coffee +3 -0
  24. data/assets/javascripts/controllers/admin-pages-edit.js.coffee +33 -0
  25. data/assets/javascripts/controllers/admin-pages.js.coffee +17 -0
  26. data/assets/stylesheets/admin-pages/_admin-pages-alert.css.scss +14 -0
  27. data/assets/stylesheets/admin-pages/_pages-widget.css.scss +113 -0
  28. data/assets/stylesheets/admin-pages/_pane-tree.css.scss +15 -0
  29. data/assets/stylesheets/admin-pages/_preview.css.scss +35 -0
  30. data/assets/stylesheets/admin-pages/_two-pane-widget.css.scss +103 -0
  31. data/assets/stylesheets/admin-pages-common/_admin-modals-select.css.scss +34 -0
  32. data/assets/stylesheets/admin-pages-common/_form-details.css.scss +11 -0
  33. data/assets/stylesheets/admin-pages-common/_nav-tabs.css.scss +6 -0
  34. data/assets/stylesheets/admin-pages-common/_page-blocks.css.scss +18 -0
  35. data/assets/stylesheets/admin-pages-common/_panels.css.scss +11 -0
  36. data/assets/stylesheets/admin-pages-common/_publication-states.css.scss +11 -0
  37. data/assets/stylesheets/admin-pages-common/_smart-links.css.scss +9 -0
  38. data/assets/stylesheets/admin-pages-common/_smart-tree-table-icons.css.scss +42 -0
  39. data/assets/stylesheets/admin-pages-edit/breadcrumbs.css.scss +11 -0
  40. data/assets/stylesheets/admin-pages-edit/form.css.scss +23 -0
  41. data/assets/stylesheets/admin-pages-edit/page-blocks.css.scss +88 -0
  42. data/assets/stylesheets/admin-pages-edit/page-footer.css.scss +21 -0
  43. data/assets/stylesheets/admin-pages-edit/page-header.css.scss +15 -0
  44. data/assets/stylesheets/admin-pages-edit/page.css.scss +30 -0
  45. data/assets/stylesheets/admin-pages-edit/tabs.css.scss +20 -0
  46. data/assets/stylesheets/aerogel-pages.css.scss +20 -0
  47. data/assets/stylesheets/controllers/admin-pages-edit.css.scss +7 -0
  48. data/assets/stylesheets/controllers/admin-pages.css.scss +5 -0
  49. data/assets/stylesheets/pages/_body.css.scss +3 -0
  50. data/assets/stylesheets/pages/_footer.css.scss +13 -0
  51. data/assets/stylesheets/pages/_header.css.scss +5 -0
  52. data/assets/stylesheets/pages/_image.css.scss +18 -0
  53. data/assets/stylesheets/pages/_layout-sticky-footer.css.scss +27 -0
  54. data/assets/stylesheets/pages/_menu.css.scss +45 -0
  55. data/assets/stylesheets/pages/_page-content.css.scss +3 -0
  56. data/assets/vendor/jquery.history.js +1 -0
  57. data/assets/vendor/smart-links.js.coffee +42 -0
  58. data/config/README.md +3 -0
  59. data/config/development/.keep +0 -0
  60. data/config/production/.keep +0 -0
  61. data/db/model/page.rb +137 -0
  62. data/db/model/page_node.rb +43 -0
  63. data/db/model/page_type.rb +15 -0
  64. data/db/model/pages/block.rb +38 -0
  65. data/db/model/pages/blocks/hr.rb +9 -0
  66. data/db/model/pages/blocks/image.rb +16 -0
  67. data/db/model/pages/blocks/pages_list.rb +41 -0
  68. data/db/model/pages/blocks/text.rb +9 -0
  69. data/db/seed/development/.keep +0 -0
  70. data/db/seed/development/01_page_types.seed +8 -0
  71. data/db/seed/development/02_root_page_node.seed +8 -0
  72. data/db/seed/development/03_root_pages.seed +10 -0
  73. data/db/seed/development/04_news_page_node.seed +15 -0
  74. data/db/seed/development/05_news_pages.seed +10 -0
  75. data/db/seed/production/.keep +0 -0
  76. data/db/seed/production/01_page_types.seed +8 -0
  77. data/db/seed/production/02_root_page_node.seed +8 -0
  78. data/db/seed/production/03_root_pages.seed +10 -0
  79. data/db/seed/seed.template +42 -0
  80. data/lib/aerogel/pages/core.rb +37 -0
  81. data/lib/aerogel/pages/traversal.rb +30 -0
  82. data/lib/aerogel/pages/version.rb +5 -0
  83. data/lib/aerogel/pages.rb +19 -0
  84. data/locales/actions.en.yml +11 -0
  85. data/locales/actions.ru.yml +11 -0
  86. data/locales/admin.en.yml +11 -0
  87. data/locales/admin.ru.yml +11 -0
  88. data/locales/models.en.yml +18 -0
  89. data/locales/models.ru.yml +19 -0
  90. data/locales/views.en.yml +38 -0
  91. data/locales/views.ru.yml +39 -0
  92. data/public/README.md +1 -0
  93. data/rake/README.md +3 -0
  94. data/views/admin/pages/_edit_form.html.erb +23 -0
  95. data/views/admin/pages/_page-DISABLED.html.erb +5 -0
  96. data/views/admin/pages/append.html.erb +4 -0
  97. data/views/admin/pages/delete.html.erb +28 -0
  98. data/views/admin/pages/edit/_block.html.erb +16 -0
  99. data/views/admin/pages/edit/_block_header.html.erb +66 -0
  100. data/views/admin/pages/edit/_breadcrumbs.html.erb +13 -0
  101. data/views/admin/pages/edit/_page.html.erb +63 -0
  102. data/views/admin/pages/edit/_page_footer.html.erb +55 -0
  103. data/views/admin/pages/edit/_page_header.html.erb +65 -0
  104. data/views/admin/pages/edit/_page_node.html.erb +79 -0
  105. data/views/admin/pages/edit/block/_default.html.erb +3 -0
  106. data/views/admin/pages/edit/block/_hr.html.erb +5 -0
  107. data/views/admin/pages/edit/block/_image.html.erb +20 -0
  108. data/views/admin/pages/edit/block/_pages_list.html.erb +53 -0
  109. data/views/admin/pages/edit/block/_text.html.erb +3 -0
  110. data/views/admin/pages/edit/select_page.html.erb +59 -0
  111. data/views/admin/pages/edit/select_template.html.erb +50 -0
  112. data/views/admin/pages/edit.html.erb +4 -0
  113. data/views/admin/pages/index/_pane_preview.html.erb +23 -0
  114. data/views/admin/pages/index/_pane_tree.html.erb +50 -0
  115. data/views/admin/pages/index/_pane_tree_tabs.html.erb +26 -0
  116. data/views/admin/pages/index.html.erb +26 -0
  117. data/views/admin/pages/insert.html.erb +4 -0
  118. data/views/admin/pages/preview/_block.html.erb +7 -0
  119. data/views/admin/pages/preview/_breadcrumbs.html.erb +11 -0
  120. data/views/admin/pages/preview/block/_default.html.erb +5 -0
  121. data/views/admin/pages/preview/block/_hr.html.erb +1 -0
  122. data/views/admin/pages/preview/block/_image.html.erb +8 -0
  123. data/views/admin/pages/preview/block/_pages_list.html.erb +14 -0
  124. data/views/admin/pages/preview/block/_text.html.erb +1 -0
  125. data/views/admin/pages/preview.html.erb +30 -0
  126. data/views/admin/table_builder/smart-list-table/_table_column.html.erb +3 -0
  127. data/views/admin/table_builder/smart-list-table/_table_row.html.erb +9 -0
  128. data/views/admin/table_builder/smart-list-table/table.html.erb +10 -0
  129. data/views/admin/table_builder/smart-tree-table/_table_column.html.erb +3 -0
  130. data/views/admin/table_builder/smart-tree-table/_table_row.html.erb +14 -0
  131. data/views/admin/table_builder/smart-tree-table/table.html.erb +10 -0
  132. data/views/admin/tabs_builder/pages-tree-tabs/_tab.html.erb +5 -0
  133. data/views/admin/tabs_builder/pages-tree-tabs/tabs.html.erb +3 -0
  134. data/views/form_builder/admin-pages-edit/field.erb +31 -0
  135. data/views/form_builder/admin-pages-edit/field_datetime.erb +19 -0
  136. data/views/form_builder/admin-pages-edit/field_default.erb +5 -0
  137. data/views/form_builder/admin-pages-edit/field_radio_buttons.erb +22 -0
  138. data/views/form_builder/admin-pages-edit/field_text_addon.erb +17 -0
  139. data/views/form_builder/admin-pages-edit/field_textarea.erb +28 -0
  140. data/views/form_builder/admin-pages-edit/field_title.erb +5 -0
  141. data/views/form_builder/admin-pages-edit/fieldset.erb +4 -0
  142. data/views/form_builder/admin-pages-edit-block/field.erb +31 -0
  143. data/views/form_builder/admin-pages-edit-block/field_default.erb +5 -0
  144. data/views/form_builder/admin-pages-edit-block/field_media-file.erb +60 -0
  145. data/views/form_builder/admin-pages-edit-block/field_media-image.erb +67 -0
  146. data/views/form_builder/admin-pages-edit-block/field_radio_buttons.erb +22 -0
  147. data/views/form_builder/admin-pages-edit-block/field_select_page.erb +34 -0
  148. data/views/form_builder/admin-pages-edit-block/field_select_template.erb +32 -0
  149. data/views/form_builder/admin-pages-edit-block/field_text_inline.erb +5 -0
  150. data/views/form_builder/admin-pages-edit-block/field_textarea.erb +2 -0
  151. data/views/form_builder/admin-pages-edit-block/fieldset.erb +4 -0
  152. data/views/layouts/admin/pages/preview.html.erb +9 -0
  153. data/views/layouts/application.html.erb +62 -0
  154. data/views/layouts/pages/_breadcrumbs.html.erb +20 -0
  155. data/views/layouts/pages/_flashes.html.erb +9 -0
  156. data/views/layouts/pages/_menu.html.erb +37 -0
  157. data/views/layouts/pages/_menu_item.html.erb +15 -0
  158. data/views/layouts/pages/_menu_user.html.erb +8 -0
  159. data/views/pages/_block.html.erb +7 -0
  160. data/views/pages/block/_default.html.erb +5 -0
  161. data/views/pages/block/_hr.html.erb +1 -0
  162. data/views/pages/block/_image.html.erb +8 -0
  163. data/views/pages/block/_pages_list.html.erb +13 -0
  164. data/views/pages/block/_text.html.erb +1 -0
  165. data/views/pages/list/_default.html.erb +7 -0
  166. data/views/pages/list/_table.html.erb +12 -0
  167. data/views/pages/list/_ul.html.erb +7 -0
  168. data/views/pages/view.html.erb +4 -0
  169. metadata +267 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8e26c560b6efb0c21e672cdec8a7ff2ebf041c1b
4
+ data.tar.gz: eb661e738d4d57d2d5808c7ae1b16f7f7d53ab1d
5
+ SHA512:
6
+ metadata.gz: 7877fad07008c646599daff5ad77adc06d5e6f589e3dc2911c06f3bf7cd6789f61cad45d58907bc61f8553cf95abd51a1ea8ffba700c712b1e5378c4d721d83d
7
+ data.tar.gz: 076ff583a35fabd307a3edf87cad5a1956875f20919998d00af042c14c2b7788f7f7a61f9926e56581527d577c7876a025a52ce120bc9a50e6b323602243a2c3
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in aerogel-module123.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Alex Kukushkin
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # aerogel-pages
2
+
3
+ Page editing/publishing for aerogel CMS.
4
+
5
+ ## Usage
6
+
7
+ Module is included in 'aerogel' gem.
8
+
9
+ In your application's config.ru:
10
+ ```ruby
11
+ require 'aerogel'
12
+
13
+ run Aerogel::Application.load
14
+ ```
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aerogel/pages/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "aerogel-pages"
8
+ spec.version = Aerogel::Pages::VERSION
9
+ spec.authors = ["Alex Kukushkin"]
10
+ spec.email = ["alex@kukushk.in"]
11
+ spec.description = %q{Page editing/publishing module for aerogel CMS}
12
+ spec.summary = %q{Page editing/publishing module for aerogel CMS}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "aerogel-core", "~> 1.4"
22
+ spec.add_dependency "aerogel-admin", "~> 1.4"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,7 @@
1
+ Module helpers go there. Suggested format is:
2
+
3
+ ```ruby
4
+ def my_helper_name1
5
+ ...
6
+ end
7
+ ```
@@ -0,0 +1,74 @@
1
+ # Returns publication state as icon,
2
+ # unless it is :published, in which case nothing is rendered.
3
+ #
4
+ def admin_pages_publication_state_as_icon( page_node, lang )
5
+ page = page_node.page( lang )
6
+ state = page.try(:publication_state) || :not_published
7
+ case state.to_sym
8
+ when :published then '' # icon 'fa-check'
9
+ when :hidden then icon 'fa-eye', title: 'hidden'
10
+ else
11
+ icon 'fa-times', title: 'not published'
12
+ end
13
+ end
14
+
15
+ # Returns page title for given +lang+, with respect to publication state.
16
+ #
17
+ def admin_pages_title_as_text( page_node, lang )
18
+ page = page_node.page( lang )
19
+ if page.nil?
20
+ publication_state = :not_published
21
+ other_page = page_node.pages.first
22
+ if other_page.nil?
23
+ return "<span class='nodata'>no translation</span>"
24
+ end
25
+ return "<span class='nodata'>#{other_page.lang}: #{h other_page.title}</span>"
26
+ end
27
+ case page.publication_state.to_sym
28
+ when :published then h page.title
29
+ when :hidden then "<span class='state-hidden'>#{h page.title}</span>"
30
+ else
31
+ "<span class='state-not-published'>#{h page.title}</span>"
32
+ end
33
+ end
34
+
35
+ # Returns title and publication state as icon and text.
36
+ #
37
+ def admin_pages_title_as_icon_and_text( page_node, lang )
38
+ admin_pages_publication_state_as_icon( page_node, lang )+" "+admin_pages_title_as_text( page_node, lang )
39
+ end
40
+
41
+
42
+ # Returns link to a page for given +lang+, with respect to publication state.
43
+ #
44
+ def admin_pages_link_as_text( page_node, lang )
45
+ page = page_node.page( lang )
46
+ return "<span class='nodata'>no content</span>" if page.blank?
47
+ case page.publication_state.to_sym
48
+ when :published then h( page.link )
49
+ when :hidden then "<span class='state-hidden'>#{h page.link}</span>"
50
+ else
51
+ "<span class='state-not-published'>#{h page.link}</span>"
52
+ end
53
+ end
54
+
55
+ # Returns link and publication state as icon and text.
56
+ #
57
+ def admin_pages_link_as_icon_and_text( page_node, lang )
58
+ admin_pages_publication_state_as_icon( page_node, lang )+" "+admin_pages_link_as_text( page_node, lang )
59
+ end
60
+
61
+ # Returns full path to current page in given +lang+,
62
+ # links are generated as icon and text
63
+ #
64
+ def admin_pages_url_as_text( page_node, lang )
65
+ return '' if page_node.nil?
66
+ page_node.ancestors_and_self.sort_by(&:depth).map do |pn|
67
+ if pn.root?
68
+ icon 'fa-home'
69
+ else
70
+ admin_pages_link_as_icon_and_text pn, lang
71
+ end
72
+ end.join(" / ")
73
+ end
74
+
@@ -0,0 +1,32 @@
1
+ # Returns root page in current lang
2
+ #
3
+ def page_root
4
+ @current_page_root ||= Page.root( current_locale )
5
+ end
6
+
7
+ # Returns or sets current Page object being served.
8
+ #
9
+ def current_page( page = nil )
10
+ @current_page = page if page.present?
11
+ @current_page
12
+ end
13
+
14
+ # Returns current page url, if Page is served,
15
+ # plain ULR otherwise.
16
+ #
17
+ # If opts[:locale] is specified, tries to find closest page in other lang.
18
+ #
19
+ def current_page_url( opts = {} )
20
+ if current_page.present?
21
+ if !opts.key?(:locale) || opts[:locale] == current_page.lang
22
+ current_page.url
23
+ else
24
+ # find this page in other lang
25
+ other_page = Aerogel::Pages::Traversal.find_closest_in_other_lang( current_page, opts[:locale] )
26
+ return nil unless other_page.present?
27
+ url_to( other_page.url, opts )
28
+ end
29
+ else
30
+ current_url opts
31
+ end
32
+ end
@@ -0,0 +1,150 @@
1
+ namespace "/admin/pages" do
2
+
3
+ admin_menu "/admin/pages/", icon: 'fa-file', label: :'aerogel.admin.panes.pages', priority: 10
4
+
5
+ get "/", "/:lang-" do
6
+ @page_nodes = PageNode.traverse
7
+ @lang = params[:lang] || I18n.default_locale
8
+ pass
9
+ end
10
+
11
+ namespace "/:lang-:id" do
12
+ before do
13
+ @lang = params[:lang]
14
+ @selected_page_node = PageNode.find( params[:id] ) or halt 404
15
+ end
16
+
17
+ get do
18
+ @page_nodes = PageNode.traverse
19
+ pass
20
+ end
21
+
22
+ get "/preview" do
23
+ layout "admin/pages/preview"
24
+ @page_node = @selected_page_node
25
+ pass
26
+ end
27
+
28
+ get "/append" do
29
+ @page_node = PageNode.new( parent_id: @selected_page_node.parent_id )
30
+ @page_node.page_type = PageType.where( type: :page ).first
31
+ pass
32
+ end
33
+
34
+ post "/append" do
35
+ @page_node = PageNode.new( params[:page_node] )
36
+ @page_node.parent_id = @selected_page_node.parent_id
37
+ pass unless @page_node.save
38
+ @page_node.move_below @selected_page_node
39
+ redirect "/admin/pages/#{@lang}-#{@page_node.id}"
40
+ end
41
+
42
+ get "/insert" do
43
+ @page_node = PageNode.new( parent_id: @selected_page_node.id )
44
+ @page_node.page_type = PageType.where( type: :page ).first
45
+ pass
46
+ end
47
+
48
+ post "/insert" do
49
+ @page_node = PageNode.new( params[:page_node] )
50
+ @page_node.parent_id = @selected_page_node.id
51
+ if @page_node.save
52
+ redirect "/admin/pages/#{@lang}-#{@page_node.id}"
53
+ end
54
+ # flash.now[:error] = t.aerogel.db.errors.failed_to_save( name: h( @page.id ),
55
+ # errors: @page.errors.full_messages.join(", ")
56
+ # )
57
+ pass
58
+ end
59
+
60
+ get "/delete" do
61
+ @page_node = @selected_page_node
62
+ pass
63
+ end
64
+
65
+ post "/delete" do
66
+ @page_node = @selected_page_node
67
+ # pass unless @page.save
68
+ parent_id = @page_node.parent_id
69
+ @page_node.destroy
70
+ redirect "/admin/pages/#{@lang}-#{parent_id}",
71
+ notice: "Page \"#{admin_pages_title_as_text @page_node, @lang}\" deleted."
72
+ end
73
+
74
+
75
+ get "/edit" do
76
+ @page_node = @selected_page_node
77
+ pass
78
+ end
79
+
80
+ post "/edit" do
81
+ # flash.now[:debug] = "params: #{params.inspect}"
82
+ @page_node = @selected_page_node
83
+ if @page_node.update_attributes params[:page_node].except( :page_type )
84
+ redirect "/admin/pages/#{@lang}-#{@page_node.id}" #, notice: "Page updated"
85
+ end
86
+ # flash.now[:error] = t.aerogel.db.errors.failed_to_save( name: h( @page.id ),
87
+ # errors: @page.errors.full_messages.join(", ")
88
+ #)
89
+ pass
90
+ end
91
+
92
+ get "/edit/page_block" do
93
+ # Find or Create page and page content with given ids
94
+ # and place the new block inside
95
+ #
96
+ page_node = PageNode.find( params[:page_block][:page_node_id] )
97
+ unless page_node.present?
98
+ page_node = PageNode.new
99
+ page_node._id = params[:page_block][:page_node_id]
100
+ end
101
+ page = page_node.pages.find params[:page_block][:page_id]
102
+ unless page.present?
103
+ page = page_node.pages.new lang: params[:page_block][:lang]
104
+ page._id = params[:page_block][:page_id]
105
+ end
106
+ page_block = page.create_page_block params[:page_block]
107
+ field_prefix = "page_node[pages_attributes][#{page.lang}][page_blocks_attributes][#{page_block.id}]"
108
+ opts = {
109
+ field_prefix: field_prefix,
110
+ style: 'admin-pages-edit-block'
111
+ }
112
+ fields = Aerogel::Forms::Fieldset.new page_block, nil, nil, opts do
113
+ partial "admin/pages/edit/block", scope: self, locals: { type: params[:page_block][:type] }
114
+ end
115
+ fields.render
116
+ end
117
+
118
+ get "/edit/select_page" do
119
+ @page_nodes = PageNode.traverse
120
+ @select_lang = params[:select_lang] || @lang
121
+ @select_page_node_id = params[:select_page_node_id] || nil
122
+ view "admin/pages/edit/select_page"
123
+ end
124
+
125
+ get "/edit/select_template" do
126
+ @select_template_name = params[:select_template_name] || nil
127
+ @select_template_prefix = params[:select_template_prefix] || nil
128
+ @templates = []
129
+ templates_wildcard = File.join( @select_template_prefix, '**/*.erb' )
130
+ template_entry = Struct.new :id, :module, :filename
131
+ Aerogel.get_resource_list( :views, templates_wildcard ) do |f, rf, path, base_path|
132
+ id = rf
133
+ filename = rf.sub(/^#{@select_template_prefix}/, '')
134
+ module_name = base_path[:module_name]
135
+ @templates << template_entry.new( id, module_name, filename )
136
+ end
137
+
138
+ view "admin/pages/edit/select_template"
139
+ end
140
+
141
+ end # namespace ":lang\::id"
142
+ #
143
+ # Common Pages controller routes
144
+ #
145
+ route :get, :post, ['/', '/:id', '/:id/:action'] do
146
+ action = params[:action] || 'index'
147
+ view "admin/pages/#{action}"
148
+ end
149
+
150
+ end
@@ -0,0 +1,16 @@
1
+
2
+ # Locate page by URL
3
+ #
4
+ get "/*" do
5
+ path = params[:splat].first.split "/" # .join "/"
6
+ @page = Aerogel::Pages::Traversal.find path, current_locale
7
+ pass if @page.nil?
8
+
9
+ current_page @page
10
+ page_title @page.try( :title )
11
+ view "pages/view"
12
+ end
13
+
14
+ error do
15
+ "Internal server error: #{h env['sinatra.error'].inspect}"
16
+ end
@@ -0,0 +1,83 @@
1
+ #
2
+ #
3
+ log = (msg) ->
4
+ console?.log "** admin/pages: #{msg}"
5
+
6
+
7
+ class @PagesWidget
8
+ two_pane_widget: null
9
+ current_state: {
10
+ lang: 'en'
11
+ }
12
+
13
+ constructor: ( @element, @pane_left, @pane_right ) ->
14
+ @two_pane_widget = new TwoPaneWidget @element, @pane_left, @pane_right
15
+ top_h = $("#top-menu").outerHeight()
16
+ foot_h = $("#footer").outerHeight()
17
+ @height_fixer = new AutofixedHeight @element, top_h+foot_h #, top_h+ foot_h
18
+ @current_title = document.title
19
+ History.Adapter.bind window, 'statechange', =>
20
+ @set_state History.getState().data
21
+
22
+ @element.on 'changed.two-pane', (e, left_middle_right) =>
23
+ @on_pane_open left_middle_right
24
+ log "initialized"
25
+
26
+ # Callback invoked by tree 'selected' event
27
+ on_page_selected: ( id, object ) =>
28
+ @current_state.page_node_id = id
29
+ # @current_state.page_attributes = object.attributes
30
+ @push_state()
31
+ log "on_page_selected: id:#{@current_state.page_node_id}"
32
+
33
+
34
+ # Callback invoked on pane open/close events
35
+ on_pane_open: ( left_middle_right ) =>
36
+ @current_state.open_pane = left_middle_right
37
+ @push_state()
38
+
39
+ # Go to page
40
+ goto_page: (id) ->
41
+ @current_state.page_node_id = id
42
+ @push_state()
43
+
44
+ push_state: ->
45
+ # push current state to history,
46
+ url = ''
47
+ if @current_state.page_node_id?
48
+ url = "#{@current_state.lang}-#{@current_state.page_node_id}"
49
+ log "setting url to '#{url}'"
50
+ log "setting lang '#{@current_state.lang}'"
51
+ History.pushState( @current_state, @current_title, url )
52
+
53
+
54
+ set_state: ( state ) ->
55
+ log "set_state: id:#{state.page_node_id}"
56
+ # console?.log state
57
+ @current_state = state
58
+ if state.page_node_id?
59
+ row = pane_tree.find_row_by_id state.page_node_id
60
+ @current_state.page_attributes = row.attributes
61
+ @update @current_state
62
+
63
+ update: ( state ) ->
64
+ log "calling update(): id=#{state.page_node_id}"
65
+ pane_tree.update state
66
+ pane_preview.update state
67
+ if state.open_pane == 'left'
68
+ @two_pane_widget.open_left( false )
69
+ else if state.open_pane == 'right'
70
+ @two_pane_widget.open_right( false )
71
+ else
72
+ @two_pane_widget.open_middle( false )
73
+
74
+ # Constructs url to +action+ on page specified by +lang+ and +id+
75
+ #
76
+ url_to: ( lang, id = '', action = null ) ->
77
+ if action? then "#{lang}-#{id}/#{action}" else "#{lang}-#{id}"
78
+
79
+
80
+ # Constructs url to +action+ on page specified by current state.
81
+ #
82
+ url_to_action: ( action ) ->
83
+ @url_to( @current_state.lang, @current_state.page_node_id, action )
@@ -0,0 +1,37 @@
1
+ log = (msg) ->
2
+ console?.log "** admin/pages:preview: #{msg}"
3
+
4
+ class @PanePreview
5
+ constructor: (@element) ->
6
+ @content = @element.find('.content').first()
7
+ @preview = @element.find('#preview').first()
8
+ @preview_empty = @element.find('#preview-empty').first()
9
+ @toolbar = @element.find('.bottom-toolbar').first()
10
+ @attached_footer = new AttachedFooter
11
+ target: @preview
12
+ footer: @toolbar
13
+ observe: @content
14
+ @current_page_node_id = null
15
+ log "initialized"
16
+ # ...
17
+ #
18
+ update: (state) ->
19
+ if state.page_node_id?
20
+ url_preview = pages_widget.url_to_action 'preview'
21
+ url_edit = pages_widget.url_to_action 'edit'
22
+ if @current_page_node_id != state.page_node_id
23
+ $.get url_preview, (data) =>
24
+ @preview.html data
25
+ @preview.show()
26
+ @preview_empty.hide()
27
+ @content.animate {scrollTop: 0} #, 'slow'
28
+ @toolbar.show()
29
+ @toolbar.find('.page-edit-link').attr 'href', url_edit
30
+ @attached_footer.update_footer()
31
+ else
32
+ @preview.hide()
33
+ @toolbar.hide()
34
+ @preview_empty.show()
35
+ @current_page_node_id = state.page_node_id
36
+
37
+
@@ -0,0 +1,105 @@
1
+ # Left pane (tree) widget
2
+ #
3
+ tree_selector = "#tree"
4
+ tree_column = 3
5
+
6
+ log = (msg) ->
7
+ console?.log "** admin/pages:tree: #{msg}"
8
+
9
+ class @PaneTree
10
+ constructor: (@element) ->
11
+ @tree_table = new SmartTreeTable @element.find( tree_selector ).first(),
12
+ column: tree_column
13
+ on_select: @on_tree_item_selected
14
+ prefix:
15
+ branch:
16
+ expanded: '<i class="prefix-expanded fa fa-caret-down"></i>'
17
+ collapsed: '<i class="prefix-collapsed fa fa-caret-right"></i>'
18
+ dragAndDrop:
19
+ enabled: false
20
+ dropTarget:
21
+ overlay:
22
+ before: '<i class="fa fa-long-arrow-up"></i>'
23
+ into: '<i class="fa fa-long-arrow-right"></i>'
24
+ after: '<i class="fa fa-long-arrow-down"></i>'
25
+
26
+ @select null
27
+
28
+ @attached_footer = new AttachedFooter
29
+ target: $(tree_selector)
30
+ footer: @bottom_toolbar()
31
+ observe: $('.pane-tree .content')
32
+
33
+ log "initialized"
34
+
35
+ # Updates pane tree widget
36
+ #
37
+ update: (state) ->
38
+ @tree_table.select state.page_node_id, false
39
+ @scroll_to_view state.page_node_id
40
+ @update_bottom_toolbar state
41
+ @update_top_toolbar state
42
+
43
+ select: (id) ->
44
+ @tree_table.select id, false
45
+
46
+ expand: (id) ->
47
+ @tree_table.expand id
48
+
49
+ scroll_to_view: (id) ->
50
+ return unless id?
51
+ row = @tree_table.rows[id]
52
+ return unless row?
53
+ el = row.el
54
+ el_t = el.position().top
55
+ el_b = el_t + el.height()
56
+ if el_t < 0 || $('.pane-tree .content').height() < el_b
57
+ origin_to = @tree_table.table.position().top
58
+ scroll_to = el.position().top
59
+ # console?.log "** pane-tree: scrolling to selected: #{scroll_to}: #{origin_to}"
60
+ @element.find('.content').animate { scrollTop: scroll_to - origin_to } #, 'slow'
61
+
62
+
63
+ # Callback to be invoked when page (tree item) is selected
64
+ #
65
+ on_tree_item_selected: (id, object, el) =>
66
+ pages_widget.on_page_selected id, object
67
+
68
+
69
+ # Returns row object specified by given +id+
70
+ #
71
+ find_row_by_id: (id) ->
72
+ @tree_table.rows[id]
73
+
74
+ # Returns action buttons elements, or elements within buttons specified by +selector+
75
+ #
76
+ bottom_toolbar: (selector = '') ->
77
+ @element.find(".bottom-toolbar #{selector}")
78
+
79
+ # Updates action buttons state and labels
80
+ #
81
+ update_bottom_toolbar: (state) ->
82
+ unless state.page_node_id?
83
+ @bottom_toolbar().hide()
84
+ return
85
+ object = @find_row_by_id state.page_node_id
86
+ @bottom_toolbar().show()
87
+ @bottom_toolbar('.page-append-link').attr 'href', pages_widget.url_to_action 'append'
88
+ @bottom_toolbar('.page-insert-link').attr 'href', pages_widget.url_to_action 'insert'
89
+ @bottom_toolbar('.page-delete-link').attr 'href', pages_widget.url_to_action 'delete'
90
+ @bottom_toolbar(' .page-name').text object.contents
91
+ @attached_footer.update_footer()
92
+
93
+ # Returns top toolbar element, or elements within buttons specified by +selector+
94
+ #
95
+ top_toolbar: (selector = '') ->
96
+ @element.find(".top-toolbar #{selector}")
97
+
98
+ # Updates top toolbar buttons and links
99
+ #
100
+ update_top_toolbar: (state) ->
101
+ @top_toolbar('.lang-select-link').each ->
102
+ lang = $(@).attr 'data-lang-id'
103
+ $(@).attr 'href', pages_widget.url_to( lang, state.page_node_id )
104
+
105
+
@@ -0,0 +1,63 @@
1
+ # Modal dialogs for page and template/layout selection.
2
+ #
3
+
4
+ modal_result = null
5
+
6
+ @admin_modal_select_and_close = ( result ) ->
7
+ console?.log "** amdin modal select and close: #{result}"
8
+ modal_result = result
9
+ $("#adminModal").modal 'hide'
10
+
11
+ @admin_modal_select_page_clear = (e) ->
12
+ field = $(e.currentTarget).closest('.field-select-page')
13
+ field.find('.page-node-id').val ''
14
+ field.find('.page-label').val ''
15
+
16
+ @admin_modal_select_page_select = (e) ->
17
+ field = $(e.currentTarget).closest('.field-select-page')
18
+ modal_result = null
19
+ select_lang = field.data 'lang'
20
+ select_page_node_id = field.find(".page-node-id").val()
21
+ $("#adminModal").modal
22
+ remote: "edit/select_page?select_lang=#{select_lang}&select_page_node_id=#{select_page_node_id}"
23
+ $("#adminModal").on 'hidden.bs.modal', ->
24
+ if modal_result?
25
+ console?.log "** select page: selected result: #{modal_result.page_id}, #{modal_result.page_label}"
26
+ field.find('.page-node-id').val modal_result.page_node_id
27
+ html_result = $.parseHTML(modal_result.page_label)
28
+ text_result = $(html_result).text().replace(/^\s+|\s+$/g, '')
29
+ field.find('.page-label').val text_result
30
+ # on_select()
31
+ $("#adminModal").off 'hidden.bs.modal'
32
+
33
+ @admin_modal_select_template_clear = (e) ->
34
+ field = $(e.currentTarget).closest('.field-select-template')
35
+ field.find('.template-id').val ''
36
+ field.find('.template-label').val ''
37
+
38
+ @admin_modal_select_template_select = (e) ->
39
+ field = $(e.currentTarget).closest('.field-select-template')
40
+ modal_result = null
41
+ select_template_prefix = field.data 'prefix'
42
+ select_template_id = field.find(".template-id").val()
43
+ $("#adminModal").modal
44
+ remote: "edit/select_template?select_template_prefix=#{select_template_prefix}&select_template_name=#{select_template_id}"
45
+ $("#adminModal").on 'hidden.bs.modal', ->
46
+ if modal_result?
47
+ console?.log "** select template: selected result: #{modal_result.template_id}"
48
+ field.find('.template-id').val modal_result.template_id
49
+ html_result = $.parseHTML(modal_result.template_label)
50
+ text_result = $(html_result).text().replace(/^\s+|\s+$/g, '')
51
+ field.find('.template-label').val text_result
52
+ # on_select()
53
+ $("#adminModal").off 'hidden.bs.modal'
54
+
55
+
56
+ # Install event handlers on select-page fields
57
+ $ ->
58
+ $("body").on 'click', '.field-select-page .btn-clear', admin_modal_select_page_clear
59
+ $("body").on 'click', '.field-select-page .btn-select', admin_modal_select_page_select
60
+ $("body").on 'click', '.field-select-template .btn-clear', admin_modal_select_template_clear
61
+ $("body").on 'click', '.field-select-template .btn-select', admin_modal_select_template_select
62
+
63
+ console?.log "** select page fields installed"