pages_core 3.4.3 → 3.5.1

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 (215) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +81 -15
  3. data/Rakefile +1 -1
  4. data/app/assets/javascripts/pages/admin.es6.jsx +19 -0
  5. data/app/assets/javascripts/pages/admin/components.es6.jsx +1 -0
  6. data/app/assets/javascripts/pages/admin/components/page_tree.es6.jsx +330 -0
  7. data/app/assets/javascripts/pages/admin/components/page_tree_actions.es6.jsx +8 -0
  8. data/app/assets/javascripts/pages/admin/components/page_tree_node.es6.jsx +374 -0
  9. data/app/assets/javascripts/pages/admin/components/page_tree_store.es6.jsx +161 -0
  10. data/app/assets/javascripts/pages/admin/features/content_tabs.es6.jsx +63 -0
  11. data/app/assets/javascripts/pages/admin/features/edit_page.es6.jsx +141 -0
  12. data/app/assets/javascripts/pages/admin/features/editable_image.es6.jsx +145 -0
  13. data/app/assets/javascripts/pages/admin/features/modal.es6.jsx +90 -0
  14. data/app/assets/javascripts/pages/admin/features/page_images.es6.jsx +338 -0
  15. data/app/assets/javascripts/pages/admin/features/rich_text.es6.jsx +124 -0
  16. data/app/assets/javascripts/pages/admin/features/tag_editor.es6.jsx +160 -0
  17. data/app/assets/javascripts/pages/admin/lib/ajax_extensions.es6.jsx +21 -0
  18. data/app/assets/javascripts/pages/admin/lib/center_on_screen.es6.jsx +22 -0
  19. data/app/assets/javascripts/pages/admin/lib/tree.es6.jsx +294 -0
  20. data/app/assets/javascripts/pages/login_form.es6.jsx +21 -0
  21. data/app/assets/stylesheets/pages/admin.scss +148 -0
  22. data/app/assets/stylesheets/pages/admin/components/buttons.scss +5 -0
  23. data/app/assets/stylesheets/pages/admin/{editable_image.css.erb → components/editable_image.scss} +7 -8
  24. data/app/assets/stylesheets/pages/admin/components/forms.scss +71 -0
  25. data/app/assets/stylesheets/pages/admin/components/header.scss +169 -0
  26. data/app/assets/stylesheets/pages/admin/{images.css.scss.erb → components/images.scss} +6 -11
  27. data/app/assets/stylesheets/pages/admin/components/layout.scss +44 -0
  28. data/app/assets/stylesheets/pages/admin/components/links.scss +43 -0
  29. data/app/assets/stylesheets/pages/admin/components/list_table.scss +58 -0
  30. data/app/assets/stylesheets/pages/admin/{login.css.scss.erb → components/login.scss} +1 -1
  31. data/app/assets/stylesheets/pages/admin/{modal.css.erb → components/modal.scss} +3 -2
  32. data/app/assets/stylesheets/pages/admin/components/page_tree.scss +173 -0
  33. data/app/assets/stylesheets/pages/admin/{pagination.css.scss → components/pagination.scss} +13 -4
  34. data/app/assets/stylesheets/pages/admin/components/sidebar.scss +25 -0
  35. data/app/assets/stylesheets/pages/admin/{tag_editor.css.scss.erb → components/tag_editor.scss} +6 -0
  36. data/app/assets/stylesheets/pages/admin/components/textarea.scss +76 -0
  37. data/app/assets/stylesheets/pages/admin/controllers/pages.scss +196 -0
  38. data/app/assets/stylesheets/pages/admin/controllers/{users.css.erb → users.scss} +0 -0
  39. data/app/assets/stylesheets/pages/admin/mixins/breakpoints.scss +21 -0
  40. data/app/assets/stylesheets/pages/admin/mixins/clearfix.scss +7 -0
  41. data/app/assets/stylesheets/pages/admin/mixins/gradients.scss +7 -0
  42. data/app/assets/stylesheets/pages/admin/{print.css.erb → print.scss} +0 -0
  43. data/app/assets/stylesheets/pages/admin/vars.scss +8 -0
  44. data/app/controllers/admin/invites_controller.rb +10 -6
  45. data/app/controllers/admin/page_files_controller.rb +6 -8
  46. data/app/controllers/admin/page_images_controller.rb +14 -19
  47. data/app/controllers/admin/pages_controller.rb +44 -97
  48. data/app/controllers/admin/password_resets_controller.rb +7 -2
  49. data/app/controllers/concerns/pages_core/add_comments_controller.rb +67 -0
  50. data/app/controllers/concerns/pages_core/admin/news_page_controller.rb +58 -0
  51. data/app/controllers/concerns/pages_core/authentication.rb +1 -1
  52. data/app/controllers/concerns/pages_core/exception_handler.rb +44 -21
  53. data/app/controllers/concerns/pages_core/policies_helper.rb +10 -6
  54. data/app/controllers/concerns/pages_core/preview_pages_controller.rb +43 -0
  55. data/app/controllers/concerns/pages_core/process_titler.rb +2 -2
  56. data/app/controllers/concerns/pages_core/rss_controller.rb +25 -0
  57. data/app/controllers/concerns/pages_core/search_pages_controller.rb +40 -0
  58. data/app/controllers/errors_controller.rb +14 -2
  59. data/app/controllers/pages_core/admin_controller.rb +7 -5
  60. data/app/controllers/pages_core/frontend/page_files_controller.rb +5 -7
  61. data/app/controllers/pages_core/frontend/pages_controller.rb +41 -219
  62. data/app/controllers/pages_core/frontend_controller.rb +8 -2
  63. data/app/controllers/pages_core/sitemaps_controller.rb +5 -4
  64. data/app/formatters/pages_core/html_formatter.rb +33 -23
  65. data/app/helpers/admin/menu_helper.rb +12 -9
  66. data/app/helpers/admin/pages_helper.rb +40 -28
  67. data/app/helpers/pages_core/admin/admin_helper.rb +58 -56
  68. data/app/helpers/pages_core/admin/labelled_field_helper.rb +6 -7
  69. data/app/helpers/pages_core/admin/tag_editor_helper.rb +11 -9
  70. data/app/helpers/pages_core/application_helper.rb +13 -26
  71. data/app/helpers/pages_core/form_builder.rb +71 -134
  72. data/app/helpers/pages_core/head_tags_helper.rb +26 -168
  73. data/app/helpers/pages_core/images_helper.rb +3 -3
  74. data/app/helpers/pages_core/meta_tags_helper.rb +96 -0
  75. data/app/helpers/pages_core/open_graph_tags_helper.rb +51 -0
  76. data/app/helpers/pages_core/page_path_helper.rb +40 -0
  77. data/app/mailers/admin_mailer.rb +14 -14
  78. data/app/models/autopublisher.rb +2 -2
  79. data/app/models/category.rb +8 -8
  80. data/app/models/concerns/pages_core/has_roles.rb +2 -2
  81. data/app/models/concerns/pages_core/humanizable_param.rb +5 -5
  82. data/app/models/concerns/pages_core/page_model/autopublishable.rb +25 -0
  83. data/app/models/concerns/pages_core/page_model/commentable.rb +29 -0
  84. data/app/models/concerns/pages_core/page_model/images.rb +50 -0
  85. data/app/models/concerns/pages_core/page_model/localizable.rb +29 -0
  86. data/app/models/concerns/pages_core/page_model/pathable.rb +115 -0
  87. data/app/models/concerns/pages_core/page_model/redirectable.rb +36 -0
  88. data/app/models/concerns/pages_core/page_model/searchable.rb +41 -0
  89. data/app/models/concerns/pages_core/page_model/sortable.rb +54 -0
  90. data/app/models/concerns/pages_core/page_model/status.rb +50 -0
  91. data/app/models/concerns/pages_core/page_model/templateable.rb +82 -0
  92. data/app/models/concerns/pages_core/page_model/tree.rb +108 -0
  93. data/app/models/page.rb +30 -212
  94. data/app/models/page_builder.rb +4 -6
  95. data/app/models/page_category.rb +7 -0
  96. data/app/models/page_comment.rb +1 -1
  97. data/app/models/page_file.rb +4 -6
  98. data/app/models/page_image.rb +6 -7
  99. data/app/models/page_path.rb +46 -0
  100. data/app/models/password_reset_token.rb +5 -5
  101. data/app/models/role.rb +1 -1
  102. data/app/models/tag.rb +14 -16
  103. data/app/models/tagging.rb +2 -1
  104. data/app/models/user.rb +6 -7
  105. data/app/policies/page_policy.rb +8 -4
  106. data/app/policies/user_policy.rb +1 -1
  107. data/app/serializers/page_tree_serializer.rb +15 -0
  108. data/app/views/admin/invites/new.html.erb +2 -1
  109. data/app/views/admin/invites/show.html.erb +3 -4
  110. data/app/views/admin/pages/_edit_comments.html.erb +22 -6
  111. data/app/views/admin/pages/_edit_content.html.erb +4 -2
  112. data/app/views/admin/pages/_edit_images.html.erb +86 -75
  113. data/app/views/admin/pages/_edit_metadata.html.erb +22 -0
  114. data/app/views/admin/pages/_edit_options.html.erb +23 -15
  115. data/app/views/admin/pages/_pagelisting.html.erb +6 -6
  116. data/app/views/admin/pages/edit.html.erb +11 -6
  117. data/app/views/admin/pages/index.html.erb +12 -53
  118. data/app/views/admin/pages/new.html.erb +3 -3
  119. data/app/views/admin/pages/news.html.erb +1 -1
  120. data/app/views/admin_mailer/invite.text.erb +1 -1
  121. data/app/views/admin_mailer/password_reset.text.erb +1 -1
  122. data/app/views/errors/422.html.erb +7 -0
  123. data/app/views/errors/500_critical.html.erb +1 -1
  124. data/app/views/layouts/admin.html.erb +36 -32
  125. data/app/views/layouts/admin/_header.html.erb +2 -2
  126. data/config/locales/en.yml +38 -1
  127. data/config/routes.rb +40 -23
  128. data/db/migrate/20111219033112_create_pages_tables.rb +25 -29
  129. data/db/migrate/20121010055412_drop_removed_tables.rb +3 -3
  130. data/db/migrate/20130823133208_update_page_redirect_to.rb +0 -13
  131. data/db/migrate/20140203183900_create_roles.rb +5 -2
  132. data/db/migrate/20140920231700_convert_images_to_dis.rb +4 -2
  133. data/db/migrate/20150401131300_localize_images.rb +7 -8
  134. data/db/migrate/20151002174800_create_page_paths.rb +10 -0
  135. data/db/migrate/20151021103400_drop_binaries_table.rb +7 -0
  136. data/db/migrate/20151204151000_remove_page_content_order.rb +5 -0
  137. data/db/migrate/20160330220900_rename_pages_categories.rb +6 -0
  138. data/db/migrate/20160405202700_change_localization_limit.rb +9 -0
  139. data/lib/pages_core.rb +22 -27
  140. data/lib/pages_core/admin_menu_item.rb +16 -3
  141. data/lib/pages_core/archive_finder.rb +40 -13
  142. data/lib/pages_core/cache_sweeper.rb +72 -45
  143. data/lib/pages_core/configuration.rb +2 -2
  144. data/lib/pages_core/configuration/base.rb +4 -8
  145. data/lib/pages_core/configuration/pages.rb +6 -3
  146. data/lib/pages_core/engine.rb +23 -1
  147. data/lib/pages_core/extensions.rb +2 -2
  148. data/lib/pages_core/file_embedder.rb +40 -0
  149. data/lib/pages_core/page_path_constraint.rb +23 -0
  150. data/lib/pages_core/pages_plugin.rb +11 -0
  151. data/lib/pages_core/paginates.rb +3 -3
  152. data/lib/pages_core/plugin.rb +14 -8
  153. data/lib/pages_core/templates.rb +6 -6
  154. data/lib/pages_core/templates/block_configuration.rb +1 -1
  155. data/lib/pages_core/templates/configuration.rb +23 -24
  156. data/lib/pages_core/templates/configuration_handler.rb +1 -1
  157. data/lib/pages_core/templates/configuration_proxy.rb +7 -11
  158. data/lib/pages_core/templates/template_configuration.rb +55 -61
  159. data/lib/pages_core/version.rb +1 -1
  160. data/lib/rails/generators/pages_core/install/install_generator.rb +22 -48
  161. data/lib/rails/generators/pages_core/install/templates/page_templates_initializer.rb +1 -1
  162. data/lib/rails/generators/pages_core/install/templates/pages_initializer.rb +6 -3
  163. data/lib/rails/generators/pages_core/rspec/rspec_generator.rb +4 -1
  164. data/lib/rails/generators/pages_core/rspec/templates/factories.rb +1 -1
  165. data/lib/tasks/pages.rake +4 -4
  166. data/lib/tasks/pages/page_paths.rake +12 -0
  167. data/template.rb +2 -2
  168. data/vendor/assets/javascripts/reflux.min.js +1 -0
  169. metadata +173 -85
  170. data/app/assets/images/pages/admin/description-bg.gif +0 -0
  171. data/app/assets/images/pages/admin/drag-handle.gif +0 -0
  172. data/app/assets/images/pages/admin/flash-error-bg.gif +0 -0
  173. data/app/assets/images/pages/admin/formelement-bg.gif +0 -0
  174. data/app/assets/images/pages/admin/header-tab-current-bg.gif +0 -0
  175. data/app/assets/images/pages/admin/list-table-td-bg.gif +0 -0
  176. data/app/assets/images/pages/admin/sidebar-bg.gif +0 -0
  177. data/app/assets/images/pages/admin/textarea_controls.gif +0 -0
  178. data/app/assets/javascripts/pages/admin.js.coffee +0 -54
  179. data/app/assets/javascripts/pages/admin/controllers/base.js.coffee +0 -4
  180. data/app/assets/javascripts/pages/admin/controllers/pages_controller.js.coffee +0 -139
  181. data/app/assets/javascripts/pages/admin/controllers/users_controller.js.coffee +0 -9
  182. data/app/assets/javascripts/pages/admin/features/content_tabs.js.coffee +0 -47
  183. data/app/assets/javascripts/pages/admin/features/editable_image.js.coffee.erb +0 -122
  184. data/app/assets/javascripts/pages/admin/features/modal.js.coffee +0 -66
  185. data/app/assets/javascripts/pages/admin/features/page_images.js +0 -329
  186. data/app/assets/javascripts/pages/admin/features/rich_text.js.coffee +0 -40
  187. data/app/assets/javascripts/pages/admin/features/tag_editor.js +0 -159
  188. data/app/assets/javascripts/pages/admin/lib/ajax_extensions.js.coffee +0 -17
  189. data/app/assets/javascripts/pages/admin/lib/center_on_screen.js.coffee +0 -21
  190. data/app/assets/javascripts/pages/admin/lib/jrichtextarea.js +0 -57
  191. data/app/assets/javascripts/pages/login_form.js.coffee +0 -17
  192. data/app/assets/stylesheets/pages/admin.css.erb +0 -404
  193. data/app/assets/stylesheets/pages/admin/buttons.css.erb +0 -5
  194. data/app/assets/stylesheets/pages/admin/controllers/artists.css.erb +0 -94
  195. data/app/assets/stylesheets/pages/admin/controllers/files.css.erb +0 -58
  196. data/app/assets/stylesheets/pages/admin/controllers/pages.css.scss.erb +0 -178
  197. data/app/assets/stylesheets/pages/admin/forms.css.scss.erb +0 -73
  198. data/app/assets/stylesheets/pages/admin/header.css.erb +0 -129
  199. data/app/assets/stylesheets/pages/admin/links.css.erb +0 -34
  200. data/app/assets/stylesheets/pages/admin/list_table.css.erb +0 -56
  201. data/app/assets/stylesheets/pages/admin/sidebar.css.erb +0 -39
  202. data/app/assets/stylesheets/pages/admin/sortable_images.css.erb +0 -18
  203. data/app/assets/stylesheets/pages/admin/textarea.css.erb +0 -55
  204. data/app/models/concerns/pages_core/page_tree.rb +0 -85
  205. data/app/models/concerns/pages_core/searchable_page.rb +0 -33
  206. data/app/models/concerns/pages_core/templateable.rb +0 -85
  207. data/app/models/localization.rb +0 -27
  208. data/db/migrate/20140515130100_remove_sphinx_deltas.rb +0 -15
  209. data/lib/pages_core/localizable.rb +0 -49
  210. data/lib/pages_core/localizable/active_record_extension.rb +0 -41
  211. data/lib/pages_core/localizable/class_methods.rb +0 -51
  212. data/lib/pages_core/localizable/configuration.rb +0 -50
  213. data/lib/pages_core/localizable/instance_methods.rb +0 -130
  214. data/lib/pages_core/localizable/localizer.rb +0 -72
  215. data/lib/pages_core/localizable/scope_extension.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 200e34fe559ba502528e3090ca7586c9f69bca8f
4
- data.tar.gz: 4a35d1688c4acbd7bf05fd7d5d723f8709d1629c
3
+ metadata.gz: ef5894c357778878106510d1f761a738f94b3bc7
4
+ data.tar.gz: bbf931791bc818a6f40eb1e6390421d42a655980
5
5
  SHA512:
6
- metadata.gz: 7a4ad5e9d16d73460d1f2140dd46338cd5f2c2fedc4e2db874a4f5bf54193a055bfba6b49342c284ced382a581acb2411ab524b205ce1a29ee71c91db923e4d0
7
- data.tar.gz: 993c77ec2473ac90dfad7deb9c851367cd1ef1456fc6dc1fccfe86b78d6604dfb72f4034869145c5823b5489e53eaa3247f0b02c7400a034daff492aff97270e
6
+ metadata.gz: 42242e9e14b24af3f7efc8c82e5433a59c11ec7b47a60b2aa569cc88133e3f0610f3bb4b2be3fcb8341ee6cfadbb38711cb6a367bf8b81c85063aaa4a72ccd1b
7
+ data.tar.gz: dd47f4402bd928c5cbfe787d6d33c689079cb5c0b940cbcdddb81dcacc47a84401c80b0b024ff2f326de4508be41a4f790412b984067c1075bd56ffa5fad1d18
data/README.md CHANGED
@@ -1,29 +1,95 @@
1
- # PagesCore
1
+ # Pages
2
2
 
3
- Pages is a CMS for Rails apps.
3
+ [![Build Status](https://travis-ci.org/kord-as/pages.svg?branch=master)](https://travis-ci.org/kord-as/pages) [![Code Climate](https://codeclimate.com/github/kord-as/pages/badges/gpa.svg)](https://codeclimate.com/github/kord-as/pages) [![Test Coverage](https://codeclimate.com/github/kord-as/pages/badges/coverage.svg)](https://codeclimate.com/github/kord-as/pages) [![Dependency Status](https://gemnasium.com/kord-as/pages.svg)](https://gemnasium.com/kord-as/pages)
4
4
 
5
- ## Installation
5
+ ## Dependencies
6
6
 
7
- ### Using the template
7
+ * Sphinx
8
8
 
9
- rails new [app name] -T -d mysql -m ~/Dev/gems/pages/template.rb
9
+ ## Getting started
10
10
 
11
- ### Using the generators
11
+ Pages is a Ruby on Rails-based CMS tailored for Rails developers.
12
12
 
13
- Add pages_core to your Gemfile:
13
+ The box does not include any themes or templates. Rather, it aims to
14
+ make it as easy as possible to build your site from scratch, harnessing
15
+ all the power of Rails and it's assets pipeline.
14
16
 
15
- gem 'pages_core', git: 'git@github.com:manualdesign/pages.git', branch: 'master'
17
+ To get started, you'll need a Rails app. A freshly generated one will
18
+ do. Add it to your Gemfile:
16
19
 
17
- Run Bundler:
20
+ ```ruby
21
+ gem "pages_core"
22
+ ```
18
23
 
19
- bundle install
24
+ Next, run the installer (which will ask you a few questions), and then
25
+ the migrations.
20
26
 
21
- And generate the config files:
27
+ ```sh
28
+ bin/rails g pages_core:install
29
+ bin/rake db:migrate
30
+ ```
22
31
 
23
- rails g pages_core:install
32
+ You'll also need a running Sphinx process:
24
33
 
25
- Now visit /admin and create your user account.
34
+ ```sh
35
+ bin/rake ts:configure
36
+ bin/rake ts:start
37
+ ```
26
38
 
27
- ## Upgrading
39
+ You should now be ready to fire up the server and visit /admin to
40
+ create your first user account.
28
41
 
29
- Review the [changelog](CHANGELOG.md) for breaking changes.
42
+ ## Quick tour
43
+
44
+ Pages is all about the `Page` model - a site is a tree of Pages. Every
45
+ page has a template (which corresponds to the files in
46
+ `app/views/pages/templates`). Here's a sample template:
47
+
48
+ ```html
49
+ <h1>
50
+ <%= @page.name %>
51
+ </h1>
52
+
53
+ <% if @page.excerpt? %>
54
+ <%= @page.excerpt.to_html %>
55
+ <% end %>
56
+
57
+ <% if @page.body? %>
58
+ <%= @page.body.to_html %>
59
+ <% end %>
60
+
61
+ <% if @page.pages.any? %>
62
+ <h2>
63
+ More stuff
64
+ </h2>
65
+ <ul>
66
+ <% @page.pages.each do |p| %>
67
+ <li>
68
+ <%= link_to p.name, page_path(locale, p) %>
69
+ </li>
70
+ <% end %>
71
+ </ul>
72
+ <% end %>
73
+ ```
74
+
75
+ Every template has one or more blocks of content, configured in
76
+ the `page_templates.rb` initializer. `name`, `excerpt` and `body`
77
+ in the example above are the defaults, but this is fully customizable
78
+ along with other optional features like images, file uploads, tags and more.
79
+
80
+ You'll also notice that the page links have a locale param. Pages does support
81
+ localizations:
82
+
83
+ ```ruby
84
+ @page.localize(:en).name # => "Hello"
85
+ @page.localize(:fr).name # => "Bonjour"
86
+ ```
87
+
88
+ All the helpers and controllers will automatically set the locale for
89
+ you and it propagates across relations, so you'll rarely end up
90
+ interacting with it directly in this fashion.
91
+
92
+ ## License
93
+
94
+ Pages is licensed under the
95
+ [MIT License](http://www.opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
3
 
4
- APP_RAKEFILE = "spec/internal/Rakefile"
4
+ APP_RAKEFILE = "spec/internal/Rakefile".freeze
5
5
  load "rails/tasks/engine.rake"
6
6
 
7
7
  RSpec::Core::RakeTask.new
@@ -0,0 +1,19 @@
1
+ // Gem assets
2
+ //= require jquery
3
+ //= require jquery_ujs
4
+ //= require jquery-ui
5
+ //= require jquery.Jcrop
6
+ //= require underscore
7
+ //= require react
8
+ //= require react_ujs
9
+ //= require reflux.min
10
+
11
+ // Vendored assets
12
+ //= require jquery.dimscreen
13
+ //= require jquery.fieldselection
14
+ //= require_self
15
+ //= require pages/login_form
16
+ //= require_tree ./admin/lib
17
+
18
+ //= require pages/admin/components
19
+ //= require_tree ./admin/features
@@ -0,0 +1 @@
1
+ //= require_tree ./components
@@ -0,0 +1,330 @@
1
+ /*
2
+ Based on react-ui-tree
3
+ https://github.com/pqx/react-ui-tree
4
+
5
+ The MIT License (MIT)
6
+
7
+ Copyright (c) 2015 pqx Limited
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+ */
27
+
28
+ class PageTree extends React.Component {
29
+ constructor(props) {
30
+ super(props);
31
+ this.state = this.init(this.props);
32
+
33
+ if (props.tree) {
34
+ PageTreeActions.init(this.props.tree);
35
+ }
36
+ }
37
+
38
+ componentDidMount() {
39
+ let self = this;
40
+ this.unsubscribe = PageTreeStore.listen(
41
+ newTree => self.setState({tree: newTree})
42
+ );
43
+ }
44
+
45
+ componentWillReceiveProps(nextProps) {
46
+ if (!this._updated) {
47
+ this.setState(this.init(nextProps));
48
+ if (nextProps.tree) {
49
+ PageTreeActions.init(this.props.tree);
50
+ }
51
+ } else {
52
+ this._updated = false;
53
+ }
54
+ }
55
+
56
+ componentWillUnmount() {
57
+ this.unsubscribe();
58
+ }
59
+
60
+ init(props) {
61
+ return {
62
+ dragging: this.initDragging()
63
+ };
64
+ }
65
+
66
+ initDragging() {
67
+ return {
68
+ id: null,
69
+ x: null,
70
+ y: null,
71
+ w: null,
72
+ h: null,
73
+ scrollTop: null,
74
+ scrollLeft: null
75
+ };
76
+ }
77
+
78
+ getDraggingDom() {
79
+ var tree = this.state.tree;
80
+ var dragging = this.state.dragging;
81
+ if (dragging && dragging.id) {
82
+ var draggingIndex = tree.getIndex(dragging.id);
83
+ var draggingStyles = {
84
+ top: dragging.y,
85
+ left: dragging.x,
86
+ width: dragging.w
87
+ };
88
+
89
+ return (
90
+ <div className="draggable" style={draggingStyles}>
91
+ <PageTreeNode
92
+ tree={tree}
93
+ index={draggingIndex}
94
+ paddingLeft={this.props.paddingLeft}
95
+ />
96
+ </div>
97
+ );
98
+ }
99
+
100
+ return null;
101
+ }
102
+
103
+ render() {
104
+ var self = this;
105
+ var tree = this.state.tree;
106
+ var dragging = this.state.dragging;
107
+
108
+ if (!tree) {
109
+ return (
110
+ <div className="page-tree">
111
+ {this.getDraggingDom()}
112
+ </div>
113
+ );
114
+ } else {
115
+ var root = tree.getIndex(1);
116
+ return (
117
+ <div className="page-tree">
118
+ {this.getDraggingDom()}
119
+ <PageTreeNode
120
+ tree={tree}
121
+ index={root}
122
+ key={root.id}
123
+ paddingLeft={this.props.paddingLeft}
124
+ addChild={id => this.addChild(id)}
125
+ onDragStart={(id, dom, e) => this.dragStart(id, dom, e)}
126
+ onCollapse={nodeId => this.toggleCollapse(nodeId)}
127
+ updatePage={(idx, attrs) => this.updatePage(idx, attrs)}
128
+ dragging={dragging && dragging.id}
129
+ />
130
+ </div>
131
+ );
132
+ }
133
+ }
134
+
135
+ addChild(parent) {
136
+ let newNode = {
137
+ name: "",
138
+ status: 0,
139
+ editing: true,
140
+ children: [],
141
+ published_at: new Date(),
142
+ pinned: false,
143
+ locale: parent.node.locale,
144
+ parent_page_id: parent.node.id
145
+ };
146
+ PageTreeActions.addChild(parent.id, newNode);
147
+ }
148
+
149
+ prevAddButtonCount(tree, index) {
150
+ var pointer = index;
151
+ var parentNodes = [];
152
+ while (pointer = tree.getIndex(pointer.parent)) {
153
+ parentNodes.push(pointer);
154
+ }
155
+
156
+ var pointer = index;
157
+ var count = 0;
158
+ while (pointer = tree.getNodeByTop(pointer.top - 1)) {
159
+ if (
160
+ parentNodes.indexOf(pointer) == -1 &&
161
+ !pointer.node.collapsed &&
162
+ pointer.node.children.filter(p => p.status != 4).length > 0
163
+ ) {
164
+ count += 1;
165
+ }
166
+ }
167
+
168
+ return count;
169
+ }
170
+
171
+ scrollOffset() {
172
+ let dragging = this.state.dragging;
173
+ return {
174
+ top: document.body.scrollTop - dragging.scrollTop,
175
+ left: document.body.scrollLeft - dragging.scrollLeft
176
+ };
177
+ }
178
+
179
+ drag(e) {
180
+ if (this._start) {
181
+ var distance = Math.abs(e.clientX - this._offsetX) +
182
+ Math.abs(e.clientY - this._offsetY);
183
+ if (distance >= 15) {
184
+ this.setState({
185
+ dragging: this.dragging
186
+ });
187
+ this._start = false;
188
+ } else {
189
+ return null;
190
+ }
191
+ }
192
+
193
+ var tree = this.state.tree;
194
+ var dragging = this.state.dragging;
195
+ var paddingLeft = this.props.paddingLeft;
196
+ var newIndex = null;
197
+ var index = tree.getIndex(dragging.id);
198
+ var collapsed = index.node.collapsed;
199
+
200
+ var _startX = this._startX;
201
+ var _startY = this._startY;
202
+ var _offsetX = this._offsetX;
203
+ var _offsetY = this._offsetY;
204
+
205
+ var pos = {
206
+ x: _startX + e.clientX - _offsetX + this.scrollOffset().left,
207
+ y: _startY + e.clientY - _offsetY + this.scrollOffset().top
208
+ };
209
+ dragging.x = pos.x;
210
+ dragging.y = pos.y;
211
+
212
+ var diffX = dragging.x - paddingLeft/2 - (index.left-2) * paddingLeft;
213
+ var diffY = dragging.y - dragging.h/2 - (index.top-2 + this.prevAddButtonCount(tree, index)) * dragging.h;
214
+
215
+ if (diffX < 0) {
216
+ // left
217
+ if (index.parent && !index.next) {
218
+ newIndex = tree.move(index.id, index.parent, 'after');
219
+ }
220
+ } else if (diffX > paddingLeft) {
221
+ // right
222
+ if (index.prev) {
223
+ var prev = tree.getIndex(index.prev);
224
+
225
+ if (!prev.node.leaf && !prev.node.collapsed) {
226
+ newIndex = tree.move(index.id, index.prev, 'append');
227
+ }
228
+ }
229
+ }
230
+
231
+ if (newIndex) {
232
+ index = newIndex;
233
+ newIndex.node.collapsed = collapsed;
234
+ dragging.id = newIndex.id;
235
+ }
236
+
237
+ if (diffY < (0 - dragging.h * 0.5)) {
238
+ // up
239
+ var above = tree.getNodeByTop(index.top-1);
240
+ newIndex = tree.move(index.id, above.id, 'before');
241
+ } else if (diffY > dragging.h * 1.5) {
242
+ // down
243
+ let below = index.next ?
244
+ tree.getIndex(index.next) :
245
+ tree.getNodeByTop(index.top + index.height);
246
+
247
+ if (below && below.parent !== index.id) {
248
+ if (below.children && below.children.length && !below.node.collapsed) {
249
+ newIndex = tree.move(index.id, below.id, 'prepend');
250
+ } else {
251
+ newIndex = tree.move(index.id, below.id, 'after');
252
+ }
253
+ }
254
+ }
255
+
256
+ if (newIndex) {
257
+ newIndex.node.collapsed = collapsed;
258
+ dragging.id = newIndex.id;
259
+ }
260
+
261
+ this.setState({
262
+ dragging: dragging,
263
+ tree: tree
264
+ });
265
+ }
266
+
267
+ dragStart(id, dom, e) {
268
+ // Only drag on left click
269
+ if (e.button !== 0) {
270
+ return;
271
+ }
272
+
273
+ this.dragging = {
274
+ id: id,
275
+ w: dom.offsetWidth,
276
+ h: dom.offsetHeight,
277
+ x: dom.offsetLeft,
278
+ y: dom.offsetTop,
279
+ scrollTop: document.body.scrollTop,
280
+ scrollLeft: document.body.scrollLeft
281
+ };
282
+
283
+ this._startX = dom.offsetLeft;
284
+ this._startY = dom.offsetTop;
285
+ this._offsetX = e.clientX;
286
+ this._offsetY = e.clientY;
287
+ this._start = true;
288
+
289
+ var self = this;
290
+ this._dragListener = (e) => self.drag(e);
291
+ this._dragEndListener = () => self.dragEnd();
292
+
293
+ window.addEventListener('mousemove', this._dragListener);
294
+ window.addEventListener('mouseup', this._dragEndListener);
295
+ }
296
+
297
+ dragEnd() {
298
+ if (!this._start) {
299
+ PageTreeActions.updateTree(this.state.tree);
300
+ PageTreeActions.movedPage(this.state.dragging.id);
301
+ }
302
+
303
+ this.setState({
304
+ dragging: this.initDragging()
305
+ });
306
+
307
+ window.removeEventListener('mousemove', this._dragListener);
308
+ window.removeEventListener('mouseup', this._dragEndListener);
309
+ }
310
+
311
+ toggleCollapse(nodeId) {
312
+ PageTreeActions.toggleCollapsed(nodeId);
313
+ }
314
+
315
+ updatePage(index, attributes) {
316
+ PageTreeActions.updatePage(
317
+ index.id,
318
+ attributes
319
+ );
320
+ }
321
+ }
322
+
323
+ PageTree.propTypes = {
324
+ tree: React.PropTypes.object.isRequired,
325
+ paddingLeft: React.PropTypes.number
326
+ };
327
+
328
+ PageTree.defaultProps = {
329
+ paddingLeft: 15
330
+ };