pages_core 3.6.2 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/Rakefile +3 -1
  4. data/app/assets/javascripts/pages/admin/components/grid_image.jsx +1 -1
  5. data/app/assets/javascripts/pages/admin/components/image_editor.jsx +5 -5
  6. data/app/assets/javascripts/pages/admin/components/image_grid.jsx +10 -5
  7. data/app/assets/javascripts/pages/admin/components/image_uploader.jsx +10 -5
  8. data/app/assets/javascripts/pages/admin/components/page_tree.jsx +9 -9
  9. data/app/assets/javascripts/pages/admin/components/page_tree_node.jsx +11 -11
  10. data/app/assets/javascripts/pages/admin/components/rich_text_area.jsx +5 -4
  11. data/app/assets/javascripts/pages/admin/components/rich_text_toolbar.jsx +54 -21
  12. data/app/assets/javascripts/pages/admin/components/toast.jsx +0 -3
  13. data/app/assets/javascripts/pages/admin/components/toast_store.jsx +1 -1
  14. data/app/assets/javascripts/pages/admin/features/edit_page.jsx +3 -3
  15. data/app/assets/javascripts/pages/admin/features/rich_text.jsx +1 -1
  16. data/app/assets/javascripts/pages/admin/features/tag_editor.jsx +28 -28
  17. data/app/assets/javascripts/pages/admin/lib/tree.jsx +9 -9
  18. data/app/assets/javascripts/pages/login_form.jsx +8 -8
  19. data/app/assets/stylesheets/pages/admin/components/forms.scss +20 -0
  20. data/app/assets/stylesheets/pages/errors.css +2 -0
  21. data/app/controller_dummies/admin/admin_controller.rb +2 -0
  22. data/app/controller_dummies/application_controller.rb +2 -0
  23. data/app/controller_dummies/attachments_controller.rb +2 -0
  24. data/app/controller_dummies/frontend_controller.rb +2 -0
  25. data/app/controller_dummies/images_controller.rb +2 -0
  26. data/app/controller_dummies/page_files_controller.rb +2 -0
  27. data/app/controller_dummies/pages_controller.rb +2 -0
  28. data/app/controller_dummies/sitemaps_controller.rb +2 -0
  29. data/app/controllers/admin/attachments_controller.rb +4 -2
  30. data/app/controllers/admin/categories_controller.rb +2 -0
  31. data/app/controllers/admin/images_controller.rb +10 -5
  32. data/app/controllers/admin/invites_controller.rb +4 -1
  33. data/app/controllers/admin/pages_controller.rb +7 -19
  34. data/app/controllers/admin/password_resets_controller.rb +9 -5
  35. data/app/controllers/admin/users_controller.rb +10 -4
  36. data/app/controllers/concerns/pages_core/admin/news_page_controller.rb +13 -11
  37. data/app/controllers/concerns/pages_core/admin/persistent_params.rb +75 -0
  38. data/app/controllers/concerns/pages_core/authentication.rb +4 -1
  39. data/app/controllers/concerns/pages_core/error_renderer.rb +3 -0
  40. data/app/controllers/concerns/pages_core/error_reporting.rb +36 -0
  41. data/app/controllers/concerns/pages_core/policies_helper.rb +4 -1
  42. data/app/controllers/concerns/pages_core/preview_pages_controller.rb +3 -0
  43. data/app/controllers/concerns/pages_core/process_titler.rb +2 -0
  44. data/app/controllers/concerns/pages_core/rss_controller.rb +2 -0
  45. data/app/controllers/concerns/pages_core/static_cache_controller.rb +48 -0
  46. data/app/controllers/errors_controller.rb +5 -53
  47. data/app/controllers/pages_core/admin_controller.rb +7 -67
  48. data/app/controllers/pages_core/attachments_controller.rb +10 -6
  49. data/app/controllers/pages_core/base_controller.rb +11 -17
  50. data/app/controllers/pages_core/frontend/page_files_controller.rb +6 -2
  51. data/app/controllers/pages_core/frontend/pages_controller.rb +9 -15
  52. data/app/controllers/pages_core/frontend_controller.rb +3 -0
  53. data/app/controllers/pages_core/images_controller.rb +3 -1
  54. data/app/controllers/pages_core/sitemaps_controller.rb +11 -5
  55. data/app/controllers/sessions_controller.rb +2 -0
  56. data/app/formatters/pages_core/html_formatter.rb +13 -63
  57. data/app/formatters/pages_core/image_embedder.rb +79 -0
  58. data/app/formatters/pages_core/link_renderer.rb +2 -0
  59. data/app/helpers/admin/admin_helper.rb +2 -0
  60. data/app/helpers/admin/menu_helper.rb +6 -4
  61. data/app/helpers/admin/pages_helper.rb +4 -57
  62. data/app/helpers/application_helper.rb +2 -0
  63. data/app/helpers/frontend_helper.rb +2 -0
  64. data/app/helpers/pages_core/admin/admin_helper.rb +22 -106
  65. data/app/helpers/pages_core/admin/content_tabs_helper.rb +28 -0
  66. data/app/helpers/pages_core/admin/date_range_helper.rb +55 -0
  67. data/app/helpers/pages_core/admin/form_builder.rb +8 -0
  68. data/app/helpers/pages_core/admin/image_uploads_helper.rb +48 -0
  69. data/app/helpers/pages_core/admin/labelled_field_helper.rb +12 -9
  70. data/app/helpers/pages_core/admin/page_blocks_helper.rb +66 -0
  71. data/app/helpers/pages_core/admin/page_json_helper.rb +23 -0
  72. data/app/helpers/pages_core/admin/tag_editor_helper.rb +11 -9
  73. data/app/helpers/pages_core/application_helper.rb +3 -0
  74. data/app/helpers/pages_core/attachments_helper.rb +31 -27
  75. data/app/helpers/pages_core/form_builder.rb +17 -13
  76. data/app/helpers/pages_core/frontend_helper.rb +3 -3
  77. data/app/helpers/pages_core/head_tags_helper.rb +7 -2
  78. data/app/helpers/pages_core/images_helper.rb +3 -0
  79. data/app/helpers/pages_core/meta_tags_helper.rb +3 -1
  80. data/app/helpers/pages_core/open_graph_tags_helper.rb +7 -5
  81. data/app/helpers/pages_core/page_path_helper.rb +24 -3
  82. data/app/jobs/pages_core/autopublish_job.rb +3 -1
  83. data/app/jobs/pages_core/sweep_cache_job.rb +4 -2
  84. data/app/mailers/admin_mailer.rb +4 -14
  85. data/app/models/attachment.rb +10 -8
  86. data/app/models/autopublisher.rb +3 -0
  87. data/app/models/category.rb +3 -1
  88. data/app/models/concerns/pages_core/has_roles.rb +2 -0
  89. data/app/models/concerns/pages_core/humanizable_param.rb +9 -6
  90. data/app/models/concerns/pages_core/page_model/attachments.rb +2 -0
  91. data/app/models/concerns/pages_core/page_model/autopublishable.rb +2 -0
  92. data/app/models/concerns/pages_core/page_model/dated_page.rb +11 -11
  93. data/app/models/concerns/pages_core/page_model/images.rb +5 -1
  94. data/app/models/concerns/pages_core/page_model/localizable.rb +2 -0
  95. data/app/models/concerns/pages_core/page_model/pathable.rb +26 -25
  96. data/app/models/concerns/pages_core/page_model/redirectable.rb +3 -1
  97. data/app/models/concerns/pages_core/page_model/sortable.rb +6 -5
  98. data/app/models/concerns/pages_core/page_model/status.rb +2 -0
  99. data/app/models/concerns/pages_core/page_model/templateable.rb +7 -2
  100. data/app/models/concerns/pages_core/page_model/tree.rb +27 -20
  101. data/app/models/concerns/pages_core/sweepable.rb +4 -2
  102. data/app/models/concerns/pages_core/taggable.rb +8 -2
  103. data/app/models/image.rb +14 -1
  104. data/app/models/invite.rb +3 -1
  105. data/app/models/invite_role.rb +5 -3
  106. data/app/models/page.rb +4 -3
  107. data/app/models/page_builder.rb +2 -0
  108. data/app/models/page_category.rb +3 -1
  109. data/app/models/page_exporter.rb +22 -9
  110. data/app/models/page_file.rb +3 -1
  111. data/app/models/page_image.rb +3 -1
  112. data/app/models/page_path.rb +13 -5
  113. data/app/models/password_reset_token.rb +3 -1
  114. data/app/models/role.rb +8 -5
  115. data/app/models/tag.rb +8 -6
  116. data/app/models/tagging.rb +4 -2
  117. data/app/models/user.rb +7 -4
  118. data/app/policies/invite_policy.rb +2 -0
  119. data/app/policies/page_file_policy.rb +2 -0
  120. data/app/policies/page_image_policy.rb +2 -0
  121. data/app/policies/page_policy.rb +2 -0
  122. data/app/policies/policy.rb +2 -0
  123. data/app/policies/user_policy.rb +2 -0
  124. data/app/serializers/admin/attachment_serializer.rb +4 -2
  125. data/app/serializers/admin/image_serializer.rb +4 -2
  126. data/app/serializers/admin/page_file_serializer.rb +2 -0
  127. data/app/serializers/admin/page_image_serializer.rb +2 -0
  128. data/app/serializers/page_export_serializer.rb +2 -0
  129. data/app/serializers/page_file_export_serializer.rb +2 -0
  130. data/app/serializers/page_image_export_serializer.rb +2 -0
  131. data/app/serializers/page_image_serializer.rb +2 -0
  132. data/app/serializers/page_serializer.rb +2 -0
  133. data/app/services/pages_core/create_user_service.rb +5 -2
  134. data/app/services/pages_core/destroy_invite_service.rb +25 -0
  135. data/app/services/pages_core/invite_service.rb +2 -0
  136. data/app/views/admin/images/show.json.jbuilder +2 -0
  137. data/app/views/admin/pages/news.html.erb +1 -1
  138. data/app/views/errors/500.html.erb +2 -20
  139. data/app/views/errors/_generic_help.html.erb +1 -1
  140. data/app/views/feeds/pages.rss.builder +2 -0
  141. data/app/views/sitemaps/show.xml.builder +2 -0
  142. data/config/routes.rb +5 -5
  143. data/db/migrate/20111219033112_create_pages_tables.rb +192 -271
  144. data/lib/pages_core.rb +10 -0
  145. data/lib/pages_core/admin_menu_item.rb +3 -0
  146. data/lib/pages_core/archive_finder.rb +12 -16
  147. data/lib/pages_core/attachment_embedder.rb +4 -6
  148. data/lib/pages_core/cache_sweeper.rb +10 -108
  149. data/lib/pages_core/configuration.rb +2 -0
  150. data/lib/pages_core/configuration/base.rb +5 -0
  151. data/lib/pages_core/configuration/pages.rb +4 -2
  152. data/lib/pages_core/digest_verifier.rb +5 -5
  153. data/lib/pages_core/engine.rb +52 -0
  154. data/lib/pages_core/extensions.rb +2 -0
  155. data/lib/pages_core/extensions/string_extensions.rb +3 -1
  156. data/lib/pages_core/page_path_constraint.rb +2 -0
  157. data/lib/pages_core/pages_plugin.rb +3 -1
  158. data/lib/pages_core/plugin.rb +4 -52
  159. data/lib/pages_core/pub_sub.rb +2 -0
  160. data/lib/pages_core/static_cache.rb +26 -0
  161. data/lib/pages_core/static_cache/null_handler.rb +17 -0
  162. data/lib/pages_core/static_cache/page_cache_handler.rb +56 -0
  163. data/lib/pages_core/static_cache/varnish_handler.rb +55 -0
  164. data/lib/pages_core/templates.rb +5 -3
  165. data/lib/pages_core/templates/block_configuration.rb +3 -0
  166. data/lib/pages_core/templates/configuration.rb +5 -1
  167. data/lib/pages_core/templates/configuration_handler.rb +4 -2
  168. data/lib/pages_core/templates/configuration_proxy.rb +2 -0
  169. data/lib/pages_core/templates/controller_actions.rb +2 -0
  170. data/lib/pages_core/templates/template_configuration.rb +18 -13
  171. data/lib/pages_core/version.rb +3 -1
  172. data/lib/rails/generators/pages_core/frontend/frontend_generator.rb +2 -0
  173. data/lib/rails/generators/pages_core/install/install_generator.rb +3 -7
  174. data/lib/rails/generators/pages_core/install/templates/active_job_initializer.rb +2 -0
  175. data/lib/rails/generators/pages_core/install/templates/application_controller.rb +2 -0
  176. data/lib/rails/generators/pages_core/install/templates/application_helper.rb +2 -0
  177. data/lib/rails/generators/pages_core/install/templates/delayed_job +1 -0
  178. data/lib/rails/generators/pages_core/install/templates/delayed_job_initializer.rb +17 -0
  179. data/lib/rails/generators/pages_core/install/templates/frontend_controller.rb +2 -0
  180. data/lib/rails/generators/pages_core/install/templates/frontend_helper.rb +2 -0
  181. data/lib/rails/generators/pages_core/install/templates/gitignore.erb +12 -1
  182. data/lib/rails/generators/pages_core/install/templates/page_templates_initializer.rb +2 -0
  183. data/lib/rails/generators/pages_core/install/templates/pages_controller.rb +2 -0
  184. data/lib/rails/generators/pages_core/install/templates/pages_initializer.rb +2 -6
  185. data/lib/rails/generators/pages_core/rspec/rspec_generator.rb +18 -14
  186. data/lib/rails/generators/pages_core/rspec/templates/factories.rb +3 -8
  187. data/lib/rails/generators/pages_core/rspec/templates/mailer_macros.rb +2 -0
  188. data/lib/rails/generators/pages_core/rspec/templates/page_templates_spec.rb +26 -0
  189. data/lib/rails/generators/pages_core/rspec/templates/rails_helper.rb +91 -0
  190. data/lib/rails/generators/pages_core/rspec/templates/spec_helper.rb +89 -36
  191. data/lib/tasks/pages.rake +3 -2
  192. data/lib/tasks/pages/cache.rake +8 -5
  193. data/lib/tasks/pages/export.rake +3 -1
  194. data/lib/tasks/pages/page_paths.rake +2 -0
  195. data/template.rb +2 -0
  196. metadata +127 -77
  197. data/app/controllers/concerns/pages_core/domain_based_cache.rb +0 -26
  198. data/app/views/admin_mailer/error_report.html.erb +0 -70
  199. data/app/views/errors/500_critical.html.erb +0 -7
  200. data/app/views/errors/report.html.erb +0 -4
  201. data/config/removed_migrations.yml +0 -60
  202. data/db/migrate/20120627033112_rename_textbits.rb +0 -17
  203. data/db/migrate/20121010055412_drop_removed_tables.rb +0 -81
  204. data/db/migrate/20130130053932_add_queue_to_delayed_jobs.rb +0 -9
  205. data/db/migrate/20130303053932_remove_filter_from_localizations.rb +0 -9
  206. data/db/migrate/20130303160632_remove_imagesets.rb +0 -22
  207. data/db/migrate/20130303161732_remove_sms_subscribers.rb +0 -14
  208. data/db/migrate/20130823133208_update_page_redirect_to.rb +0 -10
  209. data/db/migrate/20140203183900_create_roles.rb +0 -66
  210. data/db/migrate/20140414150500_change_locale_names.rb +0 -11
  211. data/db/migrate/20140604142100_remove_openid_url.rb +0 -9
  212. data/db/migrate/20140920231700_convert_images_to_dis.rb +0 -81
  213. data/db/migrate/20140922124600_convert_page_files_to_dis.rb +0 -50
  214. data/db/migrate/20141004003100_create_password_reset_tokens.rb +0 -10
  215. data/db/migrate/20141006181300_remove_user_cruft.rb +0 -11
  216. data/db/migrate/20141007173000_create_invites.rb +0 -16
  217. data/db/migrate/20150204130800_update_delayed_job_table.rb +0 -9
  218. data/db/migrate/20150401131300_localize_images.rb +0 -38
  219. data/db/migrate/20150520174300_add_meta_image_to_page.rb +0 -5
  220. data/db/migrate/20150904164200_add_pinned_to_tags.rb +0 -5
  221. data/db/migrate/20151002174800_create_page_paths.rb +0 -10
  222. data/db/migrate/20151021103400_drop_binaries_table.rb +0 -7
  223. data/db/migrate/20151204151000_remove_page_content_order.rb +0 -5
  224. data/db/migrate/20160330220900_rename_pages_categories.rb +0 -6
  225. data/db/migrate/20160405202700_change_localization_limit.rb +0 -9
  226. data/db/migrate/20170716040500_remove_page_comments.rb +0 -23
  227. data/db/migrate/20170716213400_remove_sessions.rb +0 -15
  228. data/db/migrate/20180207134000_add_dates_to_pages.rb +0 -11
  229. data/db/migrate/20190211154800_create_attachments.rb +0 -73
  230. data/db/migrate/20190318115000_fix_page_file_ids.rb +0 -34
  231. data/lib/rails/generators/pages_core/install/templates/cache_sweeper_initializer.rb +0 -6
  232. data/lib/tasks/pages/update.rake +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 537e618c3f5f182e0e23ccd5178037c2a71a89e61ca0950a862a1801b0f23ce9
4
- data.tar.gz: be1896eb7eafd63271d6d25821b7ca386980bdd0b69347db27bfb947e5a41c9b
3
+ metadata.gz: cba48a2b0698e8cd5316c0a6ff4ac970acea8abafb22cafb9963bda731c1ff8c
4
+ data.tar.gz: 9496d0d7a91a8109461bdf0481e612dc5fa164ca9f429a1a020a5f0113a96a42
5
5
  SHA512:
6
- metadata.gz: e41a054282acbdd004aad81c839bffebf9c55c05b3a47bd1c98d08dd8af3bb8ce227f77a11ae3a1bb8c680f72f8b3e34c5ac2f1710aef3b34bae1a59c5e03afb
7
- data.tar.gz: d06e26f9d9f20990f1a982f29fba091d24a9c43b8962a98c4209bbecfb9540a5f3c1fda8c462e1f412f832334d811ec29771a1ffa9831c95cf6cb43850bc2190
6
+ metadata.gz: 2e6907a2509eac3121bc1afb5a77a4aca368c624bbb26499ba4cca59301e706471f72a6f06fbff0e024a402805e5ddf09f932b723a30dca0e617b363a6389b03
7
+ data.tar.gz: aea50ccfcbbc65d5ec92f0e8dcb7d55e4088c2d71cce24d6d1b1a627545532c5d3b70496c5954612f83b46bcce794e1f55bb9ef7493dfbd3bd5c4bd16fa19c7b
data/README.md CHANGED
@@ -3,7 +3,6 @@
3
3
  [![Code Climate](https://codeclimate.com/github/anyone-oslo/pages/badges/gpa.svg)](https://codeclimate.com/github/anyone-oslo/pages)
4
4
  [![Test Coverage](https://codeclimate.com/github/anyone-oslo/pages/badges/coverage.svg)](https://codeclimate.com/github/anyone-oslo/pages)
5
5
  [![Inline docs](http://inch-ci.org/github/anyone-oslo/pages.svg)](http://inch-ci.org/github/anyone-oslo/pages)
6
- [![Security](https://hakiri.io/github/anyone-oslo/pages/master.svg)](https://hakiri.io/github/anyone-oslo/pages/master)
7
6
 
8
7
  # Pages
9
8
 
data/Rakefile CHANGED
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
4
- APP_RAKEFILE = "spec/internal/Rakefile".freeze
6
+ APP_RAKEFILE = "spec/internal/Rakefile"
5
7
  load "rails/tasks/engine.rake"
6
8
 
7
9
  RSpec::Core::RakeTask.new
@@ -56,7 +56,7 @@ class GridImage extends React.Component {
56
56
  locales={this.props.locales}
57
57
  csrf_token={this.props.csrf_token}
58
58
  onUpdate={this.props.onUpdate} />
59
- )
59
+ );
60
60
  }
61
61
 
62
62
  renderPlaceholder() {
@@ -40,7 +40,7 @@ class ImageEditor extends React.Component {
40
40
  this.img = new Image;
41
41
  this.img.onload = function() {
42
42
  component.setState({ croppedImage: component.getCroppedImage() });
43
- }
43
+ };
44
44
  this.img.src = this.props.image.uncropped_url;
45
45
  window.addEventListener("resize", this.handleResize);
46
46
  this.handleResize();
@@ -89,7 +89,7 @@ class ImageEditor extends React.Component {
89
89
  crop_width,
90
90
  crop_height,
91
91
  crop_gravity_x,
92
- crop_gravity_y } = this.state
92
+ crop_gravity_y } = this.state;
93
93
 
94
94
  // Disable focal point if it's out of bounds.
95
95
  if (crop_gravity_x < crop_start_x ||
@@ -177,7 +177,7 @@ class ImageEditor extends React.Component {
177
177
  crop_start_x: image.real_width * (crop.x / 100),
178
178
  crop_start_y: image.real_height * (crop.y / 100),
179
179
  crop_width: image.real_width * (crop.width / 100),
180
- crop_height: image.real_height * (crop.height / 100)})
180
+ crop_height: image.real_height * (crop.height / 100)});
181
181
  }
182
182
 
183
183
  getFocal() {
@@ -263,11 +263,11 @@ class ImageEditor extends React.Component {
263
263
  renderToolbar() {
264
264
  let component = this;
265
265
  let cropping = this.state.cropping;
266
- let image = this.props.image
266
+ let image = this.props.image;
267
267
  let updateAspect = function (evt, aspect) {
268
268
  evt.preventDefault();
269
269
  component.setAspect(aspect);
270
- }
270
+ };
271
271
 
272
272
 
273
273
  return (
@@ -268,11 +268,16 @@ class ImageGrid extends DragUploader {
268
268
 
269
269
  data.append("image[file]", file);
270
270
  this.postFile("/admin/images.json", data, function (json) {
271
- let preloader = new Image();
272
- obj.file = null;
273
- obj.image = json;
274
- preloader.onload = () => component.setState({});
275
- preloader.src = obj.image.thumbnail_url;
271
+ if (json.status === "error") {
272
+ ToastActions.error("Error uploading image: " + json.error.join(" "));
273
+ component.deleteImage(obj);
274
+ } else {
275
+ let preloader = new Image();
276
+ obj.file = null;
277
+ obj.image = json;
278
+ preloader.onload = () => component.setState({});
279
+ preloader.src = obj.image.thumbnail_url;
280
+ }
276
281
  });
277
282
 
278
283
  return obj;
@@ -154,16 +154,21 @@ class ImageUploader extends React.Component {
154
154
  this.setState({ image: null, src: null, dragover: false, uploading: true });
155
155
  data.append("image[file]", file);
156
156
  locales.forEach((l) => {
157
- data.append(`image[alternative][${l}]`, this.props.alternative);
157
+ data.append(`image[alternative][${l}]`, (this.props.alternative || ""));
158
158
  });
159
159
  xhr.open("POST", "/admin/images.json");
160
160
  xhr.setRequestHeader("X-CSRF-Token", this.props.csrf_token);
161
161
  xhr.addEventListener("load", function (evt) {
162
162
  if (xhr.readyState == 4 && xhr.status == "200") {
163
- let image = JSON.parse(xhr.responseText);
164
- component.setState({ uploading: false,
165
- image: image,
166
- src: image.thumbnail_url });
163
+ let response = JSON.parse(xhr.responseText);
164
+ if (response.status === "error") {
165
+ ToastActions.error("Error uploading image: " + response.error.join(" "));
166
+ component.setState({ uploading: false });
167
+ } else {
168
+ component.setState({ uploading: false,
169
+ image: response,
170
+ src: response.thumbnail_url });
171
+ }
167
172
  }
168
173
  });
169
174
  xhr.send(data);
@@ -190,7 +190,7 @@ class PageTree extends Reflux.Component {
190
190
  if (diffX < 0) {
191
191
  // left
192
192
  if (index.parent && !index.next) {
193
- newIndex = tree.move(index.id, index.parent, 'after');
193
+ newIndex = tree.move(index.id, index.parent, "after");
194
194
  }
195
195
  } else if (diffX > paddingLeft) {
196
196
  // right
@@ -198,7 +198,7 @@ class PageTree extends Reflux.Component {
198
198
  var prev = tree.getIndex(index.prev);
199
199
 
200
200
  if (!prev.node.leaf && !prev.node.collapsed) {
201
- newIndex = tree.move(index.id, index.prev, 'append');
201
+ newIndex = tree.move(index.id, index.prev, "append");
202
202
  }
203
203
  }
204
204
  }
@@ -212,7 +212,7 @@ class PageTree extends Reflux.Component {
212
212
  if (diffY < (0 - dragging.h * 0.5)) {
213
213
  // up
214
214
  var above = tree.getNodeByTop(index.top-1);
215
- newIndex = tree.move(index.id, above.id, 'before');
215
+ newIndex = tree.move(index.id, above.id, "before");
216
216
  } else if (diffY > dragging.h * 1.5) {
217
217
  // down
218
218
  let below = index.next ?
@@ -221,9 +221,9 @@ class PageTree extends Reflux.Component {
221
221
 
222
222
  if (below && below.parent !== index.id) {
223
223
  if (below.children && below.children.length && !below.node.collapsed) {
224
- newIndex = tree.move(index.id, below.id, 'prepend');
224
+ newIndex = tree.move(index.id, below.id, "prepend");
225
225
  } else {
226
- newIndex = tree.move(index.id, below.id, 'after');
226
+ newIndex = tree.move(index.id, below.id, "after");
227
227
  }
228
228
  }
229
229
  }
@@ -265,8 +265,8 @@ class PageTree extends Reflux.Component {
265
265
  this._dragListener = (e) => self.drag(e);
266
266
  this._dragEndListener = () => self.dragEnd();
267
267
 
268
- window.addEventListener('mousemove', this._dragListener);
269
- window.addEventListener('mouseup', this._dragEndListener);
268
+ window.addEventListener("mousemove", this._dragListener);
269
+ window.addEventListener("mouseup", this._dragEndListener);
270
270
  }
271
271
 
272
272
  dragEnd() {
@@ -279,8 +279,8 @@ class PageTree extends Reflux.Component {
279
279
  dragging: this.initDragging()
280
280
  });
281
281
 
282
- window.removeEventListener('mousemove', this._dragListener);
283
- window.removeEventListener('mouseup', this._dragEndListener);
282
+ window.removeEventListener("mousemove", this._dragListener);
283
+ window.removeEventListener("mouseup", this._dragEndListener);
284
284
  }
285
285
 
286
286
  toggleCollapse(nodeId) {
@@ -93,7 +93,7 @@ class PageTreeNode extends React.Component {
93
93
  if (self.props.addChild) {
94
94
  self.props.addChild(self.props.index);
95
95
  }
96
- }
96
+ };
97
97
 
98
98
  if (!node.collapsed &&
99
99
  this.permitted("create") &&
@@ -128,9 +128,9 @@ class PageTreeNode extends React.Component {
128
128
  if (index.children && index.children.length && !index.node.collapsed) {
129
129
  var childrenStyles = {};
130
130
  if (index.node.collapsed) {
131
- childrenStyles.display = 'none';
131
+ childrenStyles.display = "none";
132
132
  }
133
- childrenStyles['paddingLeft'] = this.props.paddingLeft + 'px';
133
+ childrenStyles["paddingLeft"] = this.props.paddingLeft + "px";
134
134
 
135
135
  return (
136
136
  <div className="children" style={childrenStyles}>
@@ -172,7 +172,7 @@ class PageTreeNode extends React.Component {
172
172
  if (self.props.onCollapse) {
173
173
  self.props.onCollapse(nodeId);
174
174
  }
175
- }
175
+ };
176
176
 
177
177
  if (this.visibleChildren().length > 0) {
178
178
  let collapsed = index.node.collapsed;
@@ -186,7 +186,7 @@ class PageTreeNode extends React.Component {
186
186
 
187
187
  return (
188
188
  <i className={classnames}
189
- onMouseDown={function(e) {e.stopPropagation()}}
189
+ onMouseDown={function(e) {e.stopPropagation();}}
190
190
  onClick={handleCollapse} />
191
191
  );
192
192
  }
@@ -220,7 +220,7 @@ class PageTreeNode extends React.Component {
220
220
  }
221
221
 
222
222
  editUrl(page) {
223
- return(`/admin/${page.locale}/pages/${page.param}/edit`)
223
+ return(`/admin/${page.locale}/pages/${page.param}/edit`);
224
224
  }
225
225
 
226
226
  node() {
@@ -253,7 +253,7 @@ class PageTreeNode extends React.Component {
253
253
  if (self.permitted("edit") && !editing && props.onDragStart) {
254
254
  props.onDragStart(props.index.id, self.refs.inner, e);
255
255
  }
256
- }
256
+ };
257
257
 
258
258
  if (this.node().status != 4) {
259
259
  return (
@@ -276,7 +276,7 @@ class PageTreeNode extends React.Component {
276
276
 
277
277
  let handleNameChange = function(event) {
278
278
  self.setState({newName: event.target.value});
279
- }
279
+ };
280
280
 
281
281
  let performEdit = function(event) {
282
282
  event.preventDefault();
@@ -284,12 +284,12 @@ class PageTreeNode extends React.Component {
284
284
  name: self.state.newName,
285
285
  editing: false
286
286
  });
287
- }
287
+ };
288
288
 
289
289
  let cancelEdit = function(e) {
290
290
  self.setState({newName: self.node().name});
291
291
  self.updatePage({editing: false});
292
- }
292
+ };
293
293
 
294
294
  return (
295
295
  <div className="page edit">
@@ -338,7 +338,7 @@ class PageTreeNode extends React.Component {
338
338
  if (node.id && node.starts_at) {
339
339
  dateLabel = <span className="date">
340
340
  {node.starts_at}
341
- </span>
341
+ </span>;
342
342
  }
343
343
 
344
344
  if (node.news_page) {
@@ -2,7 +2,7 @@ class RichTextArea extends React.Component {
2
2
  constructor(props) {
3
3
  super(props);
4
4
  this.state = {
5
- value: props.value,
5
+ value: props.value || "",
6
6
  rows: props.rows || 5
7
7
  };
8
8
  this.inputRef = React.createRef();
@@ -33,7 +33,7 @@ class RichTextArea extends React.Component {
33
33
  selectionStart + prefix.length + replacement.length
34
34
  );
35
35
  this.setValue(textarea.value);
36
- };
36
+ }
37
37
 
38
38
  handleChange(evt) {
39
39
  this.setValue(evt.target.value);
@@ -41,10 +41,11 @@ class RichTextArea extends React.Component {
41
41
 
42
42
  render() {
43
43
  let { value, rows } = this.state;
44
- let { id, name } = this.props;
44
+ let { id, name, simple } = this.props;
45
45
  return (
46
46
  <div className="rich-text-area">
47
- <RichTextToolbar getSelection={this.getSelection}
47
+ <RichTextToolbar simple={simple}
48
+ getSelection={this.getSelection}
48
49
  replaceSelection={this.replaceSelection} />
49
50
  <textarea className="rich"
50
51
  ref={this.inputRef}
@@ -1,20 +1,44 @@
1
1
  class RichTextToolbar extends React.Component {
2
2
  constructor(props) {
3
3
  super(props);
4
+ this.link = this.link.bind(this);
5
+ }
6
+
7
+ relativeUrl(str) {
8
+ let url = null;
9
+
10
+ if (!str.match(/^https:\/\//) || !document || !document.location) {
11
+ return str;
12
+ }
13
+
14
+ try {
15
+ url = new URL(str);
16
+ } catch (error) {
17
+ console.log("Error parsing URL: ", error);
18
+ }
19
+
20
+ if (url &&
21
+ url.hostname == document.location.hostname &&
22
+ (document.location.port || "80") == (url.port || "80")) {
23
+ return url.pathname;
24
+ }
25
+ return str;
4
26
  }
5
27
 
6
28
  link(selection) {
7
29
  let name = selection.length > 0 ? selection : "Link text";
8
30
  var url = prompt("Enter link URL", "");
9
- url = url.length > 0 ? url : "http://example.com/";
10
- url = url.replace(/^(?!(f|ht)tps?:\/\/)/, 'http://');
11
- return ["\"", name, `\":${url}`];
31
+ if (url) {
32
+ return ["\"", name, `":${this.relativeUrl(url)}`];
33
+ } else {
34
+ return ["", name, ""];
35
+ }
12
36
  }
13
37
 
14
38
  emailLink(selection) {
15
39
  var address = prompt("Enter email address", "");
16
40
  let name = selection.length > 0 ? selection : address;
17
- return ["\"", name, `\":mailto:${address}`];
41
+ return ["\"", name, `":mailto:${address}`];
18
42
  }
19
43
 
20
44
  strToList(str, prefix) {
@@ -35,24 +59,33 @@ class RichTextToolbar extends React.Component {
35
59
  <i className={"fa fa-" + className} />
36
60
  </a>
37
61
  );
38
- };
62
+ }
39
63
 
40
64
  render() {
41
- return (
42
- <div className="rich-text toolbar">
43
- {this.button("Bold", "bold", (str) => ["<b>", str, "</b>"])}
44
- {this.button("Italics", "italic", (str) => ["<i>", str, "</i>"])}
45
- {this.button("Heading 2", "header h2", (str) => ["h2. ", str, ""])}
46
- {this.button("Heading 3", "header h3", (str) => ["h3. ", str, ""])}
47
- {this.button("Heading 4", "header h4", (str) => ["h4. ", str, ""])}
48
- {this.button("Blockquote", "quote-left", (str) => ["bq. ", str, ""])}
49
- {this.button("List", "list-ul",
50
- (str) => ["", this.strToList(str, "*"), ""])}
51
- {this.button("Ordered list", "list-ol",
52
- (str) => ["", this.strToList(str, "#"), ""])}
53
- {this.button("Link", "link", this.link)}
54
- {this.button("Email link", "envelope", this.emailLink)}
55
- </div>
56
- );
65
+ if (this.props.simple) {
66
+ return (
67
+ <div className="rich-text toolbar">
68
+ {this.button("Bold", "bold", (str) => ["<b>", str, "</b>"])}
69
+ {this.button("Italics", "italic", (str) => ["<i>", str, "</i>"])}
70
+ </div>
71
+ );
72
+ } else {
73
+ return (
74
+ <div className="rich-text toolbar">
75
+ {this.button("Bold", "bold", (str) => ["<b>", str, "</b>"])}
76
+ {this.button("Italics", "italic", (str) => ["<i>", str, "</i>"])}
77
+ {this.button("Heading 2", "header h2", (str) => ["h2. ", str, ""])}
78
+ {this.button("Heading 3", "header h3", (str) => ["h3. ", str, ""])}
79
+ {this.button("Heading 4", "header h4", (str) => ["h4. ", str, ""])}
80
+ {this.button("Blockquote", "quote-left", (str) => ["bq. ", str, ""])}
81
+ {this.button("List", "list-ul",
82
+ (str) => ["", this.strToList(str, "*"), ""])}
83
+ {this.button("Ordered list", "list-ol",
84
+ (str) => ["", this.strToList(str, "#"), ""])}
85
+ {this.button("Link", "link", this.link)}
86
+ {this.button("Email link", "envelope", this.emailLink)}
87
+ </div>
88
+ );
89
+ }
57
90
  }
58
91
  }
@@ -10,9 +10,6 @@ class Toast extends Reflux.Component {
10
10
  }
11
11
  }
12
12
 
13
- componentWillUnmount() {
14
- }
15
-
16
13
  render() {
17
14
  let toast = this.state.current;
18
15
  let classNames = ["toast"];
@@ -20,7 +20,7 @@ class ToastStore extends Reflux.Store {
20
20
  this.setState({ queue: [...this.state.queue, entry] });
21
21
  } else {
22
22
  this.showToast(entry, this.state.queue);
23
- };
23
+ }
24
24
  }
25
25
 
26
26
  showToast(entry, queue) {
@@ -49,7 +49,7 @@ class EditPage {
49
49
  $("#previewButton").click(function() {
50
50
  var button = this;
51
51
  var form = $(button).closest("form").get(0);
52
- var previewUrl = $(this).data('url');
52
+ var previewUrl = $(this).data("url");
53
53
 
54
54
  // Rewrite the form and submit
55
55
  form.oldAction = form.action;
@@ -91,7 +91,7 @@ class EditPage {
91
91
  }
92
92
 
93
93
  $(function () {
94
- $('.edit-page').each(function() {
95
- new EditPage(this)}
94
+ $(".edit-page").each(function() {
95
+ new EditPage(this);}
96
96
  );
97
97
  });