aerogel-pages 1.4.12

Sign up to get free protection for your applications and to get access to all the features.
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"