pages_core 3.7.0 → 3.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/Rakefile +37 -0
  4. data/app/assets/builds/pages_core/admin-dist.js +55 -0
  5. data/app/assets/stylesheets/pages/admin/components/image_editor.scss +1 -0
  6. data/app/assets/stylesheets/pages/admin/components/image_grid.scss +33 -5
  7. data/app/assets/stylesheets/pages/admin/components/layout.scss +2 -1
  8. data/app/assets/stylesheets/pages/admin/components/login.scss +6 -0
  9. data/app/assets/stylesheets/pages/admin/components/tabs.scss +5 -0
  10. data/app/assets/stylesheets/pages/admin/components/tag_editor.scss +13 -7
  11. data/app/assets/stylesheets/pages/admin/controllers/pages.scss +13 -5
  12. data/app/assets/stylesheets/pages/admin.scss +0 -1
  13. data/app/controller_dummies/admin/admin_controller.rb +1 -1
  14. data/app/controller_dummies/application_controller.rb +1 -1
  15. data/app/controller_dummies/attachments_controller.rb +1 -1
  16. data/app/controller_dummies/frontend_controller.rb +1 -1
  17. data/app/controller_dummies/images_controller.rb +1 -1
  18. data/app/controller_dummies/page_files_controller.rb +1 -1
  19. data/app/controller_dummies/pages_controller.rb +1 -1
  20. data/app/controller_dummies/sitemaps_controller.rb +1 -1
  21. data/app/controllers/admin/attachments_controller.rb +1 -1
  22. data/app/controllers/admin/images_controller.rb +11 -8
  23. data/app/controllers/concerns/pages_core/authentication.rb +9 -4
  24. data/app/controllers/concerns/pages_core/preview_pages_controller.rb +5 -0
  25. data/app/controllers/pages_core/frontend/pages_controller.rb +5 -2
  26. data/app/controllers/sessions_controller.rb +1 -1
  27. data/app/formatters/pages_core/link_renderer.rb +2 -2
  28. data/app/helpers/application_helper.rb +1 -1
  29. data/app/helpers/frontend_helper.rb +1 -1
  30. data/app/helpers/pages_core/admin/content_tabs_helper.rb +5 -2
  31. data/app/helpers/pages_core/admin/image_uploads_helper.rb +2 -3
  32. data/app/helpers/pages_core/admin/tag_editor_helper.rb +9 -39
  33. data/app/helpers/pages_core/head_tags_helper.rb +11 -20
  34. data/app/helpers/pages_core/open_graph_tags_helper.rb +1 -1
  35. data/app/javascript/admin-dist.js +2 -0
  36. data/app/javascript/components/Attachments/Attachment.jsx +121 -0
  37. data/app/javascript/components/Attachments/AttachmentEditor.jsx +116 -0
  38. data/app/javascript/components/Attachments/Placeholder.jsx +10 -0
  39. data/app/javascript/components/Attachments.jsx +165 -0
  40. data/app/{assets/javascripts/pages/admin/components/date_range_select.jsx → javascript/components/DateRangeSelect.jsx} +16 -5
  41. data/app/javascript/components/EditableImage.jsx +61 -0
  42. data/app/javascript/components/FileUploadButton.jsx +47 -0
  43. data/app/{assets/javascripts/pages/admin/components/focal_point.jsx → javascript/components/ImageCropper/FocalPoint.jsx} +12 -1
  44. data/app/javascript/components/ImageCropper/Image.jsx +65 -0
  45. data/app/javascript/components/ImageCropper/Toolbar.jsx +73 -0
  46. data/app/javascript/components/ImageCropper/useCrop.js +199 -0
  47. data/app/javascript/components/ImageCropper.jsx +90 -0
  48. data/app/javascript/components/ImageEditor/Form.jsx +98 -0
  49. data/app/javascript/components/ImageEditor.jsx +62 -0
  50. data/app/javascript/components/ImageGrid/DragElement.jsx +30 -0
  51. data/app/javascript/components/ImageGrid/FilePlaceholder.jsx +9 -0
  52. data/app/javascript/components/ImageGrid/GridImage.jsx +103 -0
  53. data/app/javascript/components/ImageGrid/Placeholder.jsx +23 -0
  54. data/app/javascript/components/ImageGrid.jsx +257 -0
  55. data/app/javascript/components/ImageUploader.jsx +171 -0
  56. data/app/{assets/javascripts/pages/admin/components/modal.jsx → javascript/components/Modal.jsx} +13 -2
  57. data/app/{assets/javascripts/pages/admin/components/page_dates.jsx → javascript/components/PageDates.jsx} +11 -1
  58. data/app/{assets/javascripts/pages/admin/components/page_files.jsx → javascript/components/PageFiles.jsx} +11 -2
  59. data/app/{assets/javascripts/pages/admin/components/page_images.jsx → javascript/components/PageImages.jsx} +11 -2
  60. data/app/{assets/javascripts/pages/admin/components/page_tree_store.jsx → javascript/components/PageTree.jsx} +127 -137
  61. data/app/{assets/javascripts/pages/admin/components/page_tree.jsx → javascript/components/PageTreeDraggable.jsx} +35 -29
  62. data/app/{assets/javascripts/pages/admin/components/page_tree_node.jsx → javascript/components/PageTreeNode.jsx} +35 -20
  63. data/app/javascript/components/RichTextArea.jsx +213 -0
  64. data/app/javascript/components/RichTextToolbarButton.jsx +20 -0
  65. data/app/javascript/components/TagEditor/AddTagForm.jsx +42 -0
  66. data/app/javascript/components/TagEditor/Tag.jsx +32 -0
  67. data/app/javascript/components/TagEditor.jsx +61 -0
  68. data/app/javascript/components/Toast.jsx +72 -0
  69. data/app/javascript/components/drag/draggedOrder.js +51 -0
  70. data/app/javascript/components/drag/useDragCollection.js +84 -0
  71. data/app/javascript/components/drag/useDragUploader.js +112 -0
  72. data/app/javascript/components/drag/useDraggable.js +17 -0
  73. data/app/javascript/components/drag.js +6 -0
  74. data/app/javascript/components.js +15 -0
  75. data/app/javascript/controllers/EditPageController.js +20 -0
  76. data/app/javascript/controllers/LoginController.js +29 -0
  77. data/app/javascript/controllers/MainController.js +65 -0
  78. data/app/javascript/controllers/PageOptionsController.js +62 -0
  79. data/app/javascript/features/RichText.jsx +34 -0
  80. data/app/javascript/hooks.js +2 -0
  81. data/app/javascript/index.js +38 -0
  82. data/app/{assets/javascripts/pages/admin/lib/tree.jsx → javascript/lib/Tree.js} +55 -54
  83. data/app/javascript/lib/copyToClipboard.js +13 -0
  84. data/app/javascript/lib/readyHandler.js +22 -0
  85. data/app/javascript/lib/request.js +36 -0
  86. data/app/javascript/stores/ModalStore.jsx +12 -0
  87. data/app/javascript/stores/ToastStore.jsx +14 -0
  88. data/app/javascript/stores.js +2 -0
  89. data/app/models/concerns/pages_core/page_model/images.rb +3 -1
  90. data/app/models/concerns/pages_core/page_model/searchable.rb +19 -0
  91. data/app/models/concerns/pages_core/searchable_document.rb +71 -0
  92. data/app/models/concerns/pages_core/taggable.rb +27 -12
  93. data/app/models/page.rb +2 -0
  94. data/app/models/page_exporter.rb +2 -2
  95. data/app/models/page_image.rb +0 -2
  96. data/app/models/role.rb +1 -1
  97. data/app/models/search_document.rb +72 -0
  98. data/app/models/tag.rb +1 -0
  99. data/app/models/user.rb +1 -1
  100. data/app/{serializers/admin/attachment_serializer.rb → resources/admin/attachment_resource.rb} +6 -5
  101. data/app/{serializers/admin/image_serializer.rb → resources/admin/image_resource.rb} +9 -9
  102. data/app/resources/admin/page_file_resource.rb +10 -0
  103. data/app/{serializers/admin/page_image_serializer.rb → resources/admin/page_image_resource.rb} +4 -2
  104. data/app/resources/export/attachment_resource.rb +10 -0
  105. data/app/resources/export/page_image_resource.rb +45 -0
  106. data/app/resources/export/page_resource.rb +42 -0
  107. data/app/{serializers/page_image_serializer.rb → resources/page_image_resource.rb} +8 -16
  108. data/app/resources/page_resource.rb +33 -0
  109. data/app/services/pages_core/destroy_invite_service.rb +2 -2
  110. data/app/services/pages_core/invite_service.rb +2 -2
  111. data/app/views/admin/pages/_edit_content.html.erb +1 -1
  112. data/app/views/admin/pages/_edit_files.html.erb +1 -5
  113. data/app/views/admin/pages/_edit_images.html.erb +1 -5
  114. data/app/views/admin/pages/_edit_options.html.erb +74 -55
  115. data/app/views/admin/pages/_form.html.erb +19 -0
  116. data/app/views/admin/pages/edit.html.erb +35 -61
  117. data/app/views/admin/pages/index.html.erb +0 -1
  118. data/app/views/admin/pages/new.html.erb +32 -32
  119. data/app/views/admin/users/_access_control.html.erb +5 -1
  120. data/app/views/admin/users/login.html.erb +12 -4
  121. data/app/views/feeds/pages.rss.builder +1 -2
  122. data/app/views/layouts/admin/_header.html.erb +1 -1
  123. data/app/views/layouts/admin/_page_header.html.erb +33 -0
  124. data/app/views/layouts/admin.html.erb +23 -42
  125. data/app/views/pages_core/_google_analytics.html.erb +8 -0
  126. data/db/migrate/20180625154059_enable_search_extensions.rb +10 -0
  127. data/db/migrate/20210209151400_create_search_configurations.rb +35 -0
  128. data/db/migrate/20210210235200_create_search_documents.rb +74 -0
  129. data/lib/pages_core/engine.rb +1 -5
  130. data/lib/pages_core/templates/block_configuration.rb +1 -1
  131. data/lib/pages_core/templates/configuration_handler.rb +1 -1
  132. data/lib/pages_core/version.rb +3 -1
  133. data/lib/pages_core.rb +3 -5
  134. data/lib/rails/generators/pages_core/frontend/frontend_generator.rb +0 -7
  135. data/lib/rails/generators/pages_core/install/templates/page_templates_initializer.rb +2 -2
  136. metadata +116 -115
  137. data/app/assets/javascripts/pages/admin/components/attachment.jsx +0 -130
  138. data/app/assets/javascripts/pages/admin/components/attachment_editor.jsx +0 -131
  139. data/app/assets/javascripts/pages/admin/components/attachments.jsx +0 -211
  140. data/app/assets/javascripts/pages/admin/components/drag_uploader.jsx +0 -174
  141. data/app/assets/javascripts/pages/admin/components/editable_image.jsx +0 -57
  142. data/app/assets/javascripts/pages/admin/components/file_upload_button.jsx +0 -44
  143. data/app/assets/javascripts/pages/admin/components/grid_image.jsx +0 -124
  144. data/app/assets/javascripts/pages/admin/components/image_editor.jsx +0 -496
  145. data/app/assets/javascripts/pages/admin/components/image_grid.jsx +0 -306
  146. data/app/assets/javascripts/pages/admin/components/image_uploader.jsx +0 -176
  147. data/app/assets/javascripts/pages/admin/components/modal_store.jsx +0 -20
  148. data/app/assets/javascripts/pages/admin/components/rich_text_area.jsx +0 -64
  149. data/app/assets/javascripts/pages/admin/components/rich_text_toolbar.jsx +0 -91
  150. data/app/assets/javascripts/pages/admin/components/toast.jsx +0 -34
  151. data/app/assets/javascripts/pages/admin/components/toast_store.jsx +0 -52
  152. data/app/assets/javascripts/pages/admin/components.jsx +0 -2
  153. data/app/assets/javascripts/pages/admin/features/content_tabs.jsx +0 -72
  154. data/app/assets/javascripts/pages/admin/features/edit_page.jsx +0 -97
  155. data/app/assets/javascripts/pages/admin/features/rich_text.jsx +0 -14
  156. data/app/assets/javascripts/pages/admin/features/tag_editor.jsx +0 -160
  157. data/app/assets/javascripts/pages/admin.jsx +0 -17
  158. data/app/assets/javascripts/pages/login_form.jsx +0 -21
  159. data/app/serializers/admin/page_file_serializer.rb +0 -8
  160. data/app/serializers/page_export_serializer.rb +0 -32
  161. data/app/serializers/page_file_export_serializer.rb +0 -6
  162. data/app/serializers/page_image_export_serializer.rb +0 -42
  163. data/app/serializers/page_serializer.rb +0 -23
  164. data/app/views/layouts/admin/_analytics.html.erb +0 -16
  165. data/lib/rails/generators/pages_core/frontend/templates/application.js.erb +0 -15
  166. data/vendor/assets/javascripts/ReactCrop.min.js +0 -1
  167. data/vendor/assets/javascripts/reflux.min.js +0 -1
@@ -0,0 +1,6 @@
1
+ export { default as useDragCollection,
2
+ createDraggable } from "./drag/useDragCollection";
3
+ export { default as useDragUploader } from "./drag/useDragUploader";
4
+ export { default as useDraggable } from "./drag/useDraggable";
5
+ export { default as draggedOrder,
6
+ collectionOrder } from "./drag/draggedOrder";
@@ -0,0 +1,15 @@
1
+ export { default as Attachments } from "./components/Attachments";
2
+ export { default as DateRangeSelect } from "./components/DateRangeSelect";
3
+ export { default as EditableImage } from "./components/EditableImage";
4
+ export { default as FileUploadButton } from "./components/FileUploadButton";
5
+ export { default as ImageCropper } from "./components/ImageCropper";
6
+ export { default as ImageGrid } from "./components/ImageGrid";
7
+ export { default as ImageUploader } from "./components/ImageUploader";
8
+ export { default as Modal } from "./components/Modal";
9
+ export { default as PageDates } from "./components/PageDates";
10
+ export { default as PageFiles } from "./components/PageFiles";
11
+ export { default as PageImages } from "./components/PageImages";
12
+ export { default as PageTree } from "./components/PageTree";
13
+ export { default as RichTextArea } from "./components/RichTextArea";
14
+ export { default as TagEditor } from "./components/TagEditor";
15
+ export { default as Toast } from "./components/Toast";
@@ -0,0 +1,20 @@
1
+ import { Controller } from "stimulus";
2
+
3
+ export default class EditPageController extends Controller {
4
+ static get targets() {
5
+ return ["form"];
6
+ }
7
+
8
+ preview() {
9
+ const form = this.formTarget;
10
+ const prevAction = form.action;
11
+ const prevTarget = form.target;
12
+
13
+ form.target = "_blank";
14
+ form.action = form.dataset.previewUrl;
15
+ form.submit();
16
+
17
+ form.action = prevAction;
18
+ form.target = prevTarget;
19
+ }
20
+ }
@@ -0,0 +1,29 @@
1
+ import { Controller } from "stimulus";
2
+
3
+ export default class LoginController extends Controller {
4
+ static get targets() {
5
+ return ["tab"];
6
+ }
7
+
8
+ connect() {
9
+ if (this.tabTargets.length > 0) {
10
+ this.showTab(this.tabTargets[0].dataset.tab);
11
+ }
12
+ }
13
+
14
+
15
+ changeTab(evt) {
16
+ evt.preventDefault();
17
+ this.showTab(evt.target.dataset.tab);
18
+ }
19
+
20
+ showTab(tab) {
21
+ this.tabTargets.forEach((t) => {
22
+ if (t.dataset.tab == tab) {
23
+ t.classList.remove("hidden");
24
+ } else {
25
+ t.classList.add("hidden");
26
+ }
27
+ });
28
+ }
29
+ }
@@ -0,0 +1,65 @@
1
+ import { Controller } from "stimulus";
2
+
3
+ export default class MainController extends Controller {
4
+ static get targets() {
5
+ return ["tab", "link"];
6
+ }
7
+
8
+ connect() {
9
+ let tabs = this.tabNames();
10
+ if (tabs.length > 0) {
11
+ let initTab = null;
12
+ const tabExpression = /#(.*)$/;
13
+
14
+ if (document.location.toString().match(tabExpression)) {
15
+ let id = document.location.toString().match(tabExpression)[1];
16
+ if (tabs.indexOf(id) !== -1) {
17
+ initTab = id;
18
+ }
19
+ }
20
+
21
+ this.showTab(initTab || tabs[0]);
22
+ }
23
+
24
+ window.addEventListener("popstate", this.stateHandler.bind(this));
25
+ }
26
+
27
+ disconnect() {
28
+ window.removeEventListener("popstate", this.stateHandler.bind(this));
29
+ }
30
+
31
+ stateHandler(evt) {
32
+ if (evt.state && evt.state.tabId) {
33
+ this.showTab(evt.state.tabId);
34
+ }
35
+ }
36
+
37
+ changeTab(evt) {
38
+ evt.preventDefault();
39
+ const tab = evt.target.dataset.tab;
40
+ this.showTab(tab);
41
+ history.pushState({ tabId: tab }, "", `${window.location.pathname}#${tab}`);
42
+ }
43
+
44
+ showTab(tab) {
45
+ this.linkTargets.forEach((l) => {
46
+ if (l.dataset.tab == tab) {
47
+ l.classList.add("current");
48
+ } else {
49
+ l.classList.remove("current");
50
+ }
51
+ });
52
+
53
+ this.tabTargets.forEach((t) => {
54
+ if (t.dataset.tab == tab) {
55
+ t.classList.remove("hidden");
56
+ } else {
57
+ t.classList.add("hidden");
58
+ }
59
+ });
60
+ }
61
+
62
+ tabNames () {
63
+ return this.linkTargets.map((l) => l.dataset.tab);
64
+ }
65
+ }
@@ -0,0 +1,62 @@
1
+ import { Controller } from "stimulus";
2
+
3
+ export default class PageOptionsController extends Controller {
4
+ static get targets() {
5
+ return ["advancedOptions", "autoPublishNotice", "published", "publishedDate"];
6
+ }
7
+
8
+ connect() {
9
+ this.checkAutoPublish();
10
+ this.checkPublishedDate();
11
+ }
12
+
13
+ checkAutoPublish() {
14
+ if (this.publishedDate() > new Date()) {
15
+ this.show(this.autoPublishNoticeTarget);
16
+ } else {
17
+ this.hide(this.autoPublishNoticeTarget);
18
+ }
19
+ }
20
+
21
+ checkPublishedDate() {
22
+ if (this.publishedTarget.value == 2) {
23
+ this.show(this.publishedDateTarget);
24
+ } else {
25
+ this.hide(this.publishedDateTarget);
26
+ }
27
+ }
28
+
29
+ publishedDate() {
30
+ const lookup = (name) => {
31
+ return this.publishedDateTarget.getElementsByClassName(name)[0].value;
32
+ };
33
+ return new Date(
34
+ lookup("year"),
35
+ (lookup("month") - 1),
36
+ lookup("day"),
37
+ lookup("hour"),
38
+ lookup("minute")
39
+ );
40
+ }
41
+
42
+ show(elem) {
43
+ elem.classList.add("show");
44
+ }
45
+
46
+ hide(elem) {
47
+ elem.classList.remove("show");
48
+ }
49
+
50
+ toggle(elem) {
51
+ if (elem.classList.contains("show")) {
52
+ this.hide(elem);
53
+ } else {
54
+ this.show(elem);
55
+ }
56
+ }
57
+
58
+ toggleAdvancedOptions(evt) {
59
+ evt.preventDefault();
60
+ this.toggle(this.advancedOptionsTarget);
61
+ }
62
+ }
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom";
3
+ import RichTextArea from "../components/RichTextArea";
4
+ import readyHandler from "../lib/readyHandler";
5
+
6
+ class RichText {
7
+ apply () {
8
+ const elems = document.querySelectorAll("textarea.rich");
9
+ elems.forEach((elem) => {
10
+ this.enhance(elem);
11
+ });
12
+ }
13
+
14
+ enhance (elem) {
15
+ const container = document.createElement("div");
16
+ elem.parentNode.appendChild(container);
17
+ ReactDOM.render(
18
+ <RichTextArea value={elem.value}
19
+ name={elem.name}
20
+ rows={elem.rows}
21
+ id={elem.id} />,
22
+ container
23
+ );
24
+ elem.parentNode.removeChild(elem);
25
+ }
26
+
27
+ start () {
28
+ readyHandler.ready(() => {
29
+ this.apply();
30
+ });
31
+ }
32
+ }
33
+
34
+ export default new RichText();
@@ -0,0 +1,2 @@
1
+ export { useCrop, cropParams } from "./components/ImageCropper";
2
+ export * from "./components/drag";
@@ -0,0 +1,38 @@
1
+ import Rails from "@rails/ujs";
2
+ import { Application } from "stimulus";
3
+ require("react_ujs");
4
+
5
+ import * as Components from "./components";
6
+
7
+ import EditPageController from "./controllers/EditPageController";
8
+ import MainController from "./controllers/MainController";
9
+ import LoginController from "./controllers/LoginController";
10
+ import PageOptionsController from "./controllers/PageOptionsController";
11
+
12
+ import RichText from "./features/RichText";
13
+
14
+ export function registerComponent(name, component) {
15
+ window[name] = component;
16
+ }
17
+
18
+ export default function startPages () {
19
+ Rails.start();
20
+ for (var name in Components) {
21
+ registerComponent(name, Components[name]);
22
+ }
23
+ RichText.start();
24
+
25
+ const application = Application.start();
26
+ application.register("edit-page", EditPageController);
27
+ application.register("main", MainController);
28
+ application.register("login", LoginController);
29
+ application.register("page-options", PageOptionsController);
30
+ }
31
+
32
+ export * from "./components";
33
+ export * from "./hooks";
34
+ export * from "./stores";
35
+
36
+ export * from "./lib/request.js";
37
+ export { default as copyToClipboard,
38
+ copySupported } from "./lib/copyToClipboard";
@@ -1,55 +1,56 @@
1
1
  /*
2
- Based on
3
-
4
- js-tree by Wang Zuo
5
- https://github.com/wangzuo/js-tree
6
-
7
- react-ui-tree
8
- https://github.com/pqx/react-ui-tree
9
-
10
- The MIT License (MIT)
11
-
12
- Copyright (c) 2015 Wang Zuo
13
-
14
- Permission is hereby granted, free of charge, to any person obtaining a copy
15
- of this software and associated documentation files (the "Software"), to deal
16
- in the Software without restriction, including without limitation the rights
17
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
- copies of the Software, and to permit persons to whom the Software is
19
- furnished to do so, subject to the following conditions:
20
-
21
- The above copyright notice and this permission notice shall be included in
22
- all copies or substantial portions of the Software.
23
-
24
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
- SOFTWARE.
31
-
32
- Copyright (c) 2015 pqx Limited
33
-
34
- Permission is hereby granted, free of charge, to any person obtaining a copy
35
- of this software and associated documentation files (the "Software"), to deal
36
- in the Software without restriction, including without limitation the rights
37
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
- copies of the Software, and to permit persons to whom the Software is
39
- furnished to do so, subject to the following conditions:
40
-
41
- The above copyright notice and this permission notice shall be included in
42
- all copies or substantial portions of the Software.
43
-
44
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50
- SOFTWARE.
51
- */
52
- class Tree {
2
+ Based on
3
+
4
+ js-tree by Wang Zuo
5
+ https://github.com/wangzuo/js-tree
6
+
7
+ react-ui-tree
8
+ https://github.com/pqx/react-ui-tree
9
+
10
+ The MIT License (MIT)
11
+
12
+ Copyright (c) 2015 Wang Zuo
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in
22
+ all copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+
32
+ Copyright (c) 2015 pqx Limited
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ of this software and associated documentation files (the "Software"), to deal
36
+ in the Software without restriction, including without limitation the rights
37
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
+ copies of the Software, and to permit persons to whom the Software is
39
+ furnished to do so, subject to the following conditions:
40
+
41
+ The above copyright notice and this permission notice shall be included in
42
+ all copies or substantial portions of the Software.
43
+
44
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50
+ SOFTWARE.
51
+ */
52
+
53
+ export default class Tree {
53
54
  constructor(obj) {
54
55
  this.cnt = 1;
55
56
  this.obj = obj || { children: [] };
@@ -72,7 +73,7 @@ class Tree {
72
73
 
73
74
  function walk(objs, parent) {
74
75
  var children = [];
75
- objs.forEach(function(obj, i) {
76
+ objs.forEach(function(obj) {
76
77
  var index = {};
77
78
  index.id = self.cnt;
78
79
  index.node = obj;
@@ -276,7 +277,7 @@ class Tree {
276
277
 
277
278
  getParent(id) {
278
279
  var indexes = this.indexes;
279
- if (indexes.hasOwnProperty(id)) {
280
+ if (Object.prototype.hasOwnProperty.call(indexes, id)) {
280
281
  return this.getIndex(indexes[id].parent);
281
282
  }
282
283
  }
@@ -284,7 +285,7 @@ class Tree {
284
285
  getNodeByTop(top) {
285
286
  var indexes = this.indexes;
286
287
  for(var id in indexes) {
287
- if (indexes.hasOwnProperty(id)) {
288
+ if (Object.prototype.hasOwnProperty.call(indexes, id)) {
288
289
  if(indexes[id].top === top) {
289
290
  return indexes[id];
290
291
  }
@@ -0,0 +1,13 @@
1
+ export function copySupported () {
2
+ return document.queryCommandSupported &&
3
+ document.queryCommandSupported("copy");
4
+ }
5
+
6
+ export default function copyToClipboard (str) {
7
+ const el = document.createElement("textarea");
8
+ el.value = str;
9
+ document.body.appendChild(el);
10
+ el.select();
11
+ document.execCommand("copy");
12
+ document.body.removeChild(el);
13
+ }
@@ -0,0 +1,22 @@
1
+ let readyHandlers = [];
2
+
3
+ const handleState = () => {
4
+ if (["interactive", "complete"].indexOf(document.readyState) > -1) {
5
+ while(readyHandlers.length > 0) {
6
+ (readyHandlers.shift())();
7
+ }
8
+ }
9
+ };
10
+
11
+ class ReadyHandler {
12
+ constructor () {
13
+ document.onreadystatechange = handleState;
14
+ }
15
+
16
+ ready (handler) {
17
+ readyHandlers.push(handler);
18
+ handleState();
19
+ }
20
+ }
21
+
22
+ export default new ReadyHandler();
@@ -0,0 +1,36 @@
1
+ export function csrfToken() {
2
+ return document.querySelector("[name=csrf-token]").content;
3
+ }
4
+
5
+ function jsonFetchOptions() {
6
+ return({ method: "POST",
7
+ headers: { "Content-Type": "application/json; charset=utf-8",
8
+ "X-CSRF-Token": csrfToken() } });
9
+ }
10
+
11
+ export async function postJson(url, data) {
12
+ const options = { ...jsonFetchOptions(), method: "POST" };
13
+ if (data) {
14
+ options.body = JSON.stringify(data);
15
+ }
16
+ const response = await fetch(url, options);
17
+ return response.json();
18
+ }
19
+
20
+ export async function putJson(url, data) {
21
+ const options = { ...jsonFetchOptions(), method: "PUT" };
22
+ if (data) {
23
+ options.body = JSON.stringify(data);
24
+ }
25
+ const response = await fetch(url, options);
26
+ return response.json();
27
+ }
28
+
29
+ export async function post(url, data) {
30
+ const response = await fetch(url, {
31
+ method: "POST",
32
+ body: data,
33
+ headers: { "X-CSRF-Token": csrfToken() }
34
+ });
35
+ return response.json();
36
+ }
@@ -0,0 +1,12 @@
1
+ import { createStore } from "redux";
2
+
3
+ export default createStore((state = {}, action) => {
4
+ switch(action.type) {
5
+ case "OPEN":
6
+ return {...state, component: action.payload };
7
+ case "CLOSE":
8
+ return {...state, component: null };
9
+ default:
10
+ return state;
11
+ }
12
+ });
@@ -0,0 +1,14 @@
1
+ import { createStore } from "redux";
2
+
3
+ export default createStore((state = [], action) => {
4
+ switch(action.type) {
5
+ case "ERROR":
6
+ return [...state, { message: action.message, type: "error" }];
7
+ case "NOTICE":
8
+ return [...state, { message: action.message, type: "notice" }];
9
+ case "NEXT":
10
+ return state.slice(1);
11
+ default:
12
+ return state;
13
+ }
14
+ });
@@ -0,0 +1,2 @@
1
+ export { default as ModalStore } from "./stores/ModalStore";
2
+ export { default as ToastStore } from "./stores/ToastStore";
@@ -8,7 +8,9 @@ module PagesCore
8
8
  included do
9
9
  belongs_to_image :image, optional: true
10
10
  belongs_to_image :meta_image, class_name: "Image", optional: true
11
- has_many :page_images, -> { order("position") }, inverse_of: :page
11
+ has_many :page_images, -> { order("position") },
12
+ inverse_of: :page,
13
+ dependent: :destroy
12
14
  has_many(
13
15
  :images,
14
16
  -> { where(page_images: { primary: false }).order("position") },
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PagesCore
4
+ module PageModel
5
+ module Searchable
6
+ extend ActiveSupport::Concern
7
+
8
+ def search_document_attributes
9
+ super.merge(
10
+ published: published?,
11
+ name: name,
12
+ description: try(&:meta_description?) ? meta_description : excerpt,
13
+ # content: "",
14
+ tags: tag_names.join(" ")
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PagesCore
4
+ module SearchableDocument
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :search_documents, as: :searchable, dependent: :destroy
9
+ after_save :update_search_documents!
10
+ end
11
+
12
+ class Indexer
13
+ attr_reader :record
14
+
15
+ def initialize(record)
16
+ @record = record
17
+ end
18
+
19
+ class << self
20
+ def index_all!(scope)
21
+ scope.all.find_each { |r| new(r).index! }
22
+ end
23
+ end
24
+
25
+ def index!
26
+ SearchDocument.transaction do
27
+ record.search_documents.where.not(locale: locales).destroy_all
28
+ locales.each do |locale|
29
+ update_index(
30
+ locale,
31
+ localized_record(locale).search_document_attributes
32
+ )
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def locales
40
+ if record.respond_to?(:locales)
41
+ record.locales
42
+ elsif PagesCore.config.locales
43
+ PagesCore.config.locales.keys
44
+ else
45
+ [I18n.default_locale]
46
+ end
47
+ end
48
+
49
+ def localized_record(locale)
50
+ return record unless record.respond_to?(:localize)
51
+
52
+ record.localize(locale)
53
+ end
54
+
55
+ def update_index(locale, attrs)
56
+ record.search_documents.create_or_find_by!(locale: locale).update(attrs)
57
+ end
58
+ end
59
+
60
+ def search_document_attributes
61
+ return {} unless respond_to?(:localized_attributes)
62
+
63
+ content = localized_attributes.keys.map { |a| localizer.get(a) }.join(" ")
64
+ { content: content }
65
+ end
66
+
67
+ def update_search_documents!
68
+ PagesCore::SearchableDocument::Indexer.new(self).index!
69
+ end
70
+ end
71
+ end