pages_core 3.14.0 → 3.15.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 (227) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/app/assets/builds/pages_core/admin-dist.js +19 -8
  4. data/app/assets/builds/pages_core/admin-dist.js.map +4 -4
  5. data/app/assets/builds/pages_core/admin.css +672 -379
  6. data/app/assets/fonts/Inter-Black.woff2 +0 -0
  7. data/app/assets/fonts/Inter-BlackItalic.woff2 +0 -0
  8. data/app/assets/fonts/Inter-Bold.woff2 +0 -0
  9. data/app/assets/fonts/Inter-BoldItalic.woff2 +0 -0
  10. data/app/assets/fonts/Inter-ExtraBold.woff2 +0 -0
  11. data/app/assets/fonts/Inter-ExtraBoldItalic.woff2 +0 -0
  12. data/app/assets/fonts/Inter-ExtraLight.woff2 +0 -0
  13. data/app/assets/fonts/Inter-ExtraLightItalic.woff2 +0 -0
  14. data/app/assets/fonts/Inter-Italic.woff2 +0 -0
  15. data/app/assets/fonts/Inter-Light.woff2 +0 -0
  16. data/app/assets/fonts/Inter-LightItalic.woff2 +0 -0
  17. data/app/assets/fonts/Inter-Medium.woff2 +0 -0
  18. data/app/assets/fonts/Inter-MediumItalic.woff2 +0 -0
  19. data/app/assets/fonts/Inter-Regular.woff2 +0 -0
  20. data/app/assets/fonts/Inter-SemiBold.woff2 +0 -0
  21. data/app/assets/fonts/Inter-SemiBoldItalic.woff2 +0 -0
  22. data/app/assets/fonts/Inter-Thin.woff2 +0 -0
  23. data/app/assets/fonts/Inter-ThinItalic.woff2 +0 -0
  24. data/app/assets/fonts/InterDisplay-Black.woff2 +0 -0
  25. data/app/assets/fonts/InterDisplay-BlackItalic.woff2 +0 -0
  26. data/app/assets/fonts/InterDisplay-Bold.woff2 +0 -0
  27. data/app/assets/fonts/InterDisplay-BoldItalic.woff2 +0 -0
  28. data/app/assets/fonts/InterDisplay-ExtraBold.woff2 +0 -0
  29. data/app/assets/fonts/InterDisplay-ExtraBoldItalic.woff2 +0 -0
  30. data/app/assets/fonts/InterDisplay-ExtraLight.woff2 +0 -0
  31. data/app/assets/fonts/InterDisplay-ExtraLightItalic.woff2 +0 -0
  32. data/app/assets/fonts/InterDisplay-Italic.woff2 +0 -0
  33. data/app/assets/fonts/InterDisplay-Light.woff2 +0 -0
  34. data/app/assets/fonts/InterDisplay-LightItalic.woff2 +0 -0
  35. data/app/assets/fonts/InterDisplay-Medium.woff2 +0 -0
  36. data/app/assets/fonts/InterDisplay-MediumItalic.woff2 +0 -0
  37. data/app/assets/fonts/InterDisplay-Regular.woff2 +0 -0
  38. data/app/assets/fonts/InterDisplay-SemiBold.woff2 +0 -0
  39. data/app/assets/fonts/InterDisplay-SemiBoldItalic.woff2 +0 -0
  40. data/app/assets/fonts/InterDisplay-Thin.woff2 +0 -0
  41. data/app/assets/fonts/InterDisplay-ThinItalic.woff2 +0 -0
  42. data/app/assets/fonts/InterVariable-Italic.woff2 +0 -0
  43. data/app/assets/fonts/InterVariable.woff2 +0 -0
  44. data/app/assets/stylesheets/pages_core/admin/components/archive.css +1 -1
  45. data/app/assets/stylesheets/pages_core/admin/components/attachments.css +22 -34
  46. data/app/assets/stylesheets/pages_core/admin/components/base.css +1 -68
  47. data/app/assets/stylesheets/pages_core/admin/components/forms.css +107 -48
  48. data/app/assets/stylesheets/pages_core/admin/components/header.css +56 -58
  49. data/app/assets/stylesheets/pages_core/admin/components/image_editor.css +35 -24
  50. data/app/assets/stylesheets/pages_core/admin/components/image_grid.css +28 -27
  51. data/app/assets/stylesheets/pages_core/admin/components/image_uploader.css +5 -5
  52. data/app/assets/stylesheets/pages_core/admin/components/layout.css +7 -1
  53. data/app/assets/stylesheets/pages_core/admin/components/list_table.css +24 -15
  54. data/app/assets/stylesheets/pages_core/admin/components/page_tree.css +63 -104
  55. data/app/assets/stylesheets/pages_core/admin/components/pagination.css +12 -13
  56. data/app/assets/stylesheets/pages_core/admin/components/search.css +1 -16
  57. data/app/assets/stylesheets/pages_core/admin/components/sidebar.css +5 -11
  58. data/app/assets/stylesheets/pages_core/admin/components/tag_editor.css +22 -36
  59. data/app/assets/stylesheets/pages_core/admin/components/toast.css +1 -2
  60. data/app/assets/stylesheets/pages_core/admin/components/toolbar.css +10 -10
  61. data/app/assets/stylesheets/pages_core/admin/components/totp.css +1 -1
  62. data/app/assets/stylesheets/pages_core/admin/controllers/pages.css +37 -51
  63. data/app/assets/stylesheets/pages_core/admin/global/fonts.css +271 -0
  64. data/app/assets/stylesheets/pages_core/admin/global/typography.css +109 -0
  65. data/app/assets/stylesheets/pages_core/admin/vars.css +1 -3
  66. data/app/assets/stylesheets/pages_core/admin.postcss.css +1 -0
  67. data/app/controllers/admin/account_recoveries_controller.rb +2 -2
  68. data/app/controllers/admin/pages_controller.rb +22 -42
  69. data/app/controllers/concerns/pages_core/error_reporting.rb +1 -1
  70. data/app/controllers/concerns/pages_core/page_parameters.rb +29 -0
  71. data/app/controllers/concerns/pages_core/policies_helper.rb +1 -1
  72. data/app/controllers/concerns/pages_core/preview_pages_controller.rb +20 -20
  73. data/app/controllers/pages_core/admin_controller.rb +0 -2
  74. data/app/controllers/pages_core/frontend/pages_controller.rb +2 -6
  75. data/app/formatters/pages_core/html_formatter.rb +2 -4
  76. data/app/helpers/admin/menu_helper.rb +5 -4
  77. data/app/helpers/admin/pages_helper.rb +1 -21
  78. data/app/helpers/pages_core/admin/admin_helper.rb +2 -3
  79. data/app/helpers/pages_core/admin/content_tabs_helper.rb +1 -2
  80. data/app/helpers/pages_core/admin/labelled_field_helper.rb +1 -1
  81. data/app/helpers/pages_core/frontend_helper.rb +1 -1
  82. data/app/helpers/pages_core/images_helper.rb +10 -8
  83. data/app/helpers/pages_core/labelled_form_builder.rb +2 -7
  84. data/app/helpers/pages_core/page_path_helper.rb +1 -1
  85. data/app/javascript/components/Attachments/Attachment.tsx +20 -18
  86. data/app/javascript/components/Attachments/AttachmentEditor.tsx +11 -9
  87. data/app/javascript/components/{Attachments.jsx → Attachments/List.tsx} +58 -63
  88. data/app/javascript/components/Attachments/useAttachments.ts +15 -0
  89. data/app/javascript/components/Attachments.tsx +14 -0
  90. data/app/javascript/components/DateRangeSelect.tsx +105 -0
  91. data/app/javascript/components/DateTimeSelect.tsx +136 -0
  92. data/app/javascript/components/EditableImage.tsx +11 -9
  93. data/app/javascript/components/FileUploadButton.tsx +7 -7
  94. data/app/javascript/components/ImageCropper/FocalPoint.tsx +9 -12
  95. data/app/javascript/components/ImageCropper/Image.tsx +10 -8
  96. data/app/javascript/components/ImageCropper/Toolbar.tsx +11 -12
  97. data/app/javascript/components/ImageCropper/useCrop.ts +24 -53
  98. data/app/javascript/components/ImageCropper.tsx +10 -15
  99. data/app/javascript/components/ImageEditor/Form.tsx +12 -8
  100. data/app/javascript/components/ImageEditor.tsx +12 -7
  101. data/app/javascript/components/ImageGrid/DragElement.tsx +9 -12
  102. data/app/javascript/components/{ImageGrid.jsx → ImageGrid/Grid.tsx} +62 -71
  103. data/app/javascript/components/ImageGrid/GridImage.tsx +22 -23
  104. data/app/javascript/components/ImageGrid/Placeholder.tsx +2 -2
  105. data/app/javascript/components/ImageGrid/useImageGrid.ts +26 -0
  106. data/app/javascript/components/ImageGrid.tsx +15 -0
  107. data/app/javascript/components/ImageUploader.tsx +35 -22
  108. data/app/javascript/components/LabelledField.tsx +34 -0
  109. data/app/javascript/components/Modal.tsx +2 -2
  110. data/app/javascript/components/PageForm/Block.tsx +81 -0
  111. data/app/javascript/components/PageForm/Content.tsx +54 -0
  112. data/app/javascript/components/PageForm/Dates.tsx +66 -0
  113. data/app/javascript/components/PageForm/Files.tsx +28 -0
  114. data/app/javascript/components/PageForm/Form.tsx +41 -0
  115. data/app/javascript/components/PageForm/Images.tsx +28 -0
  116. data/app/javascript/components/PageForm/LocaleLinks.tsx +36 -0
  117. data/app/javascript/components/PageForm/Metadata.tsx +67 -0
  118. data/app/javascript/components/PageForm/Options.tsx +180 -0
  119. data/app/javascript/components/PageForm/PageDescription.tsx +48 -0
  120. data/app/javascript/components/PageForm/PathSegment.tsx +65 -0
  121. data/app/javascript/components/PageForm/TabPanel.tsx +21 -0
  122. data/app/javascript/components/PageForm/Tabs.tsx +33 -0
  123. data/app/javascript/components/PageForm/UnconfiguredContent.tsx +42 -0
  124. data/app/javascript/components/PageForm/pageParams.ts +95 -0
  125. data/app/javascript/components/PageForm/preview.ts +23 -0
  126. data/app/javascript/components/PageForm/usePage.ts +169 -0
  127. data/app/javascript/components/PageForm/useTabs.ts +46 -0
  128. data/app/javascript/components/PageForm.tsx +163 -0
  129. data/app/javascript/components/PageImages.tsx +7 -9
  130. data/app/javascript/components/PageTree/Draggable.tsx +40 -39
  131. data/app/javascript/components/PageTree/Node.tsx +62 -56
  132. data/app/javascript/components/PageTree/PageName.tsx +28 -0
  133. data/app/javascript/components/PageTree.tsx +65 -53
  134. data/app/javascript/components/{RichTextArea.jsx → RichTextArea.tsx} +98 -79
  135. data/app/javascript/components/RichTextToolbarButton.tsx +4 -6
  136. data/app/javascript/components/TagEditor/AddTagForm.tsx +19 -12
  137. data/app/javascript/components/TagEditor/Editor.tsx +32 -0
  138. data/app/javascript/components/TagEditor/Tag.tsx +6 -4
  139. data/app/javascript/components/TagEditor/useTags.ts +58 -0
  140. data/app/javascript/components/TagEditor.tsx +8 -58
  141. data/app/javascript/components/Toast.tsx +3 -3
  142. data/app/javascript/components/drag/draggedOrder.ts +22 -14
  143. data/app/javascript/components/drag/useDragCollection.ts +35 -30
  144. data/app/javascript/components/drag/useDragUploader.ts +32 -21
  145. data/app/javascript/components/drag/useDraggable.ts +7 -6
  146. data/app/javascript/components/drag.ts +0 -1
  147. data/app/javascript/components.ts +1 -3
  148. data/app/javascript/features/RichText.tsx +2 -3
  149. data/app/javascript/features/contentTabs.ts +79 -0
  150. data/app/javascript/index.ts +5 -12
  151. data/app/javascript/lib/Tree.ts +31 -45
  152. data/app/javascript/lib/request.ts +11 -11
  153. data/app/javascript/stores/useToastStore.ts +1 -1
  154. data/app/javascript/types/Attachments.ts +29 -0
  155. data/app/javascript/types/Crop.ts +36 -0
  156. data/app/javascript/types/Drag.ts +34 -0
  157. data/app/javascript/types/Images.ts +47 -0
  158. data/app/javascript/types/PageEditor.ts +26 -0
  159. data/app/javascript/types/Pages.ts +75 -0
  160. data/app/javascript/types/Tags.ts +9 -0
  161. data/app/javascript/types/Template.ts +24 -0
  162. data/app/javascript/types/Trees.ts +19 -0
  163. data/app/javascript/types.ts +2 -25
  164. data/app/models/attachment.rb +1 -1
  165. data/app/models/concerns/pages_core/authenticable_user.rb +63 -0
  166. data/app/models/concerns/pages_core/emailable.rb +16 -0
  167. data/app/models/concerns/pages_core/page_model/templateable.rb +2 -16
  168. data/app/models/invite.rb +2 -6
  169. data/app/models/otp_secret.rb +4 -4
  170. data/app/models/page.rb +0 -3
  171. data/app/models/user.rb +2 -46
  172. data/app/policies/page_policy.rb +6 -2
  173. data/app/resources/admin/page_resource.rb +95 -0
  174. data/app/resources/admin/page_tree_resource.rb +27 -0
  175. data/app/resources/admin/template_configuration_resource.rb +50 -0
  176. data/app/views/admin/news/_sidebar.html.erb +2 -4
  177. data/app/views/admin/news/index.html.erb +0 -1
  178. data/app/views/admin/pages/_form.html.erb +10 -30
  179. data/app/views/admin/pages/_search_bar.html.erb +1 -1
  180. data/app/views/admin/pages/edit.html.erb +1 -57
  181. data/app/views/admin/pages/index.html.erb +1 -1
  182. data/app/views/admin/pages/new.html.erb +1 -44
  183. data/app/views/admin/sessions/new.html.erb +9 -11
  184. data/app/views/admin/users/_access_control.html.erb +5 -1
  185. data/app/views/admin/users/_list.html.erb +12 -7
  186. data/app/views/layouts/admin/_header.html.erb +2 -4
  187. data/app/views/layouts/admin/_page_header.html.erb +1 -2
  188. data/app/views/layouts/admin.html.erb +1 -1
  189. data/config/locales/en.yml +0 -4
  190. data/config/routes.rb +3 -7
  191. data/db/migrate/20240126160700_add_2fa_fields.rb +5 -1
  192. data/db/migrate/20240131140700_change_email_to_citext.rb +18 -0
  193. data/db/migrate/20240201160700_remove_persistent_data.rb +7 -0
  194. data/db/migrate/20240508145300_remove_categories.rb +21 -0
  195. data/lib/pages_core/configuration/base.rb +2 -2
  196. data/lib/pages_core/templates/configuration.rb +1 -1
  197. data/lib/pages_core/templates/configuration_proxy.rb +2 -2
  198. data/lib/pages_core/templates/template_configuration.rb +11 -1
  199. data/lib/pages_core/templates.rb +6 -4
  200. data/lib/pages_core/version.rb +1 -1
  201. data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/gridOverlay.ts +6 -7
  202. data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/responsiveEmbeds.ts +17 -12
  203. data/lib/rails/generators/pages_core/rspec/rspec_generator.rb +0 -2
  204. data/lib/rails/generators/pages_core/rspec/templates/rails_helper.rb +3 -4
  205. metadata +95 -29
  206. data/app/assets/stylesheets/pages_core/admin/components/login.css +0 -27
  207. data/app/controllers/admin/categories_controller.rb +0 -56
  208. data/app/controllers/concerns/pages_core/admin/persistent_params.rb +0 -75
  209. data/app/helpers/pages_core/admin/page_blocks_helper.rb +0 -66
  210. data/app/helpers/pages_core/admin/page_json_helper.rb +0 -23
  211. data/app/javascript/components/DateRangeSelect.jsx +0 -225
  212. data/app/javascript/components/PageDates.jsx +0 -73
  213. data/app/javascript/components/PageFiles.jsx +0 -25
  214. data/app/javascript/components/PageTree/types.ts +0 -15
  215. data/app/javascript/components/drag/types.ts +0 -28
  216. data/app/javascript/controllers/EditPageController.ts +0 -22
  217. data/app/javascript/controllers/MainController.ts +0 -74
  218. data/app/javascript/controllers/PageOptionsController.js +0 -67
  219. data/app/models/category.rb +0 -22
  220. data/app/models/concerns/pages_core/has_otp.rb +0 -27
  221. data/app/models/page_category.rb +0 -6
  222. data/app/views/admin/pages/_edit_content.html.erb +0 -19
  223. data/app/views/admin/pages/_edit_files.html.erb +0 -4
  224. data/app/views/admin/pages/_edit_images.html.erb +0 -4
  225. data/app/views/admin/pages/_edit_metadata.html.erb +0 -35
  226. data/app/views/admin/pages/_edit_options.html.erb +0 -91
  227. data/lib/rails/generators/pages_core/rspec/templates/mailer_macros.rb +0 -11
@@ -2,9 +2,8 @@
2
2
 
3
3
  module Admin
4
4
  class PagesController < Admin::AdminController
5
- include PagesCore::Admin::PageJsonHelper
5
+ include PagesCore::PageParameters
6
6
 
7
- before_action :find_categories
8
7
  before_action :find_page, only: %i[show edit update destroy move]
9
8
 
10
9
  require_authorization
@@ -39,26 +38,26 @@ module Admin
39
38
  def edit; end
40
39
 
41
40
  def create
42
- @page = build_page(content_locale, page_params,
43
- param_categories).tap(&:save)
44
- if @page.valid?
45
- respond_with_page(@page) do
41
+ @page = build_page(content_locale, page_params).tap(&:save)
42
+
43
+ respond_with_page(@page) do
44
+ if @page.valid?
46
45
  redirect_to(edit_admin_page_url(content_locale, @page))
46
+ else
47
+ render action: :new
47
48
  end
48
- else
49
- render action: :new
50
49
  end
51
50
  end
52
51
 
53
52
  def update
54
- if @page.update(page_params)
55
- @page.categories = param_categories
56
- respond_with_page(@page) do
53
+ @page.update(page_params)
54
+ respond_with_page(@page) do
55
+ if @page.valid?
57
56
  flash[:notice] = t("pages_core.changes_saved")
58
57
  redirect_to edit_admin_page_url(content_locale, @page)
58
+ else
59
+ render action: :edit
59
60
  end
60
- else
61
- render action: :edit
62
61
  end
63
62
  end
64
63
 
@@ -75,53 +74,34 @@ module Admin
75
74
 
76
75
  private
77
76
 
78
- def build_page(locale, attributes = nil, categories = nil)
77
+ def build_page(locale, attributes = nil)
79
78
  Page.new.localize(locale).tap do |page|
80
79
  page.author = default_author || current_user
81
80
  page.attributes = attributes if attributes
82
- page.categories = categories if categories
83
81
  end
84
82
  end
85
83
 
86
84
  def default_author
87
- User.find_by_email(PagesCore.config.default_author)
88
- end
89
-
90
- def page_attributes
91
- %i[template user_id status feed_enabled published_at redirect_to
92
- image_link news_page unique_name pinned parent_page_id serialized_tags
93
- meta_image_id starts_at ends_at all_day image_id path_segment
94
- meta_title meta_description open_graph_title open_graph_description]
85
+ User.find_by(email: PagesCore.config.default_author)
95
86
  end
96
87
 
97
88
  def page_params
98
- params.require(:page).permit(
99
- PagesCore::Templates::TemplateConfiguration.all_blocks +
100
- page_attributes,
101
- page_images_attributes: %i[id position image_id primary _destroy],
102
- page_files_attributes: %i[id position attachment_id _destroy]
103
- )
104
- end
105
-
106
- def param_categories
107
- return [] unless params[:category]
108
-
109
- params.permit(category: {})[:category].to_hash
110
- .map { |id, _| Category.find(id) }
89
+ params.require(:page).permit(page_content_attributes)
111
90
  end
112
91
 
113
92
  def find_page
114
93
  @page = Page.find(params[:id]).localize(content_locale)
115
94
  end
116
95
 
117
- def find_categories
118
- @categories = Category.order("name")
119
- end
120
-
121
96
  def respond_with_page(page, &block)
122
97
  respond_to do |format|
123
- format.html { block.call }
124
- format.json { render json: page_json(page) }
98
+ format.html(&block)
99
+ format.json do
100
+ render json: ::Admin::PageResource.new(
101
+ page,
102
+ params: { user: current_user }
103
+ )
104
+ end
125
105
  end
126
106
  end
127
107
  end
@@ -11,7 +11,7 @@ module PagesCore
11
11
  protected
12
12
 
13
13
  def configure_sentry_scope
14
- return if Rails.env.test? || !Object.const_defined?("Sentry")
14
+ return if Rails.env.test? || !Object.const_defined?(:Sentry)
15
15
 
16
16
  Sentry.set_context("params", params.to_unsafe_h)
17
17
  Sentry.set_tags(locale: params[:locale] || I18n.default_locale.to_s)
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PagesCore
4
+ module PageParameters
5
+ extend ActiveSupport::Concern
6
+
7
+ def page_attachment_attributes
8
+ { page_images_attributes: %i[id position image_id primary _destroy],
9
+ page_files_attributes: %i[id position attachment_id _destroy] }
10
+ end
11
+
12
+ def page_content_attributes
13
+ locales = PagesCore.config.locales&.keys || [I18n.default_locale]
14
+ [page_static_attributes,
15
+ PagesCore::Templates::TemplateConfiguration.all_blocks,
16
+ :path_segment,
17
+ (PagesCore::Templates::TemplateConfiguration
18
+ .localized_blocks + %i[path_segment])
19
+ .index_with { locales },
20
+ page_attachment_attributes]
21
+ end
22
+
23
+ def page_static_attributes
24
+ %i[template user_id status feed_enabled published_at redirect_to
25
+ news_page unique_name pinned parent_page_id serialized_tags
26
+ meta_image_id starts_at ends_at all_day]
27
+ end
28
+ end
29
+ end
@@ -35,7 +35,7 @@ module PagesCore
35
35
  end
36
36
 
37
37
  def verify_policy(record)
38
- return true if policy(record).public_send("#{action_name}?")
38
+ return true if policy(record).public_send(:"#{action_name}?")
39
39
 
40
40
  raise PagesCore::NotAuthorized
41
41
  end
@@ -3,11 +3,27 @@
3
3
  module PagesCore
4
4
  module PreviewPagesController
5
5
  extend ActiveSupport::Concern
6
+ include PagesCore::PageParameters
7
+
8
+ included do
9
+ before_action :disable_xss_protection, only: %i[preview]
10
+ end
6
11
 
7
12
  def preview?
8
13
  @preview || false
9
14
  end
10
15
 
16
+ def preview
17
+ render_error 403 unless logged_in?
18
+
19
+ @preview = true
20
+ @page = Page.find_by(id: params[:page_id]) || Page.new
21
+ @page.readonly!
22
+ @page.assign_attributes(preview_page_params)
23
+
24
+ render_page
25
+ end
26
+
11
27
  private
12
28
 
13
29
  def disable_xss_protection
@@ -17,31 +33,15 @@ module PagesCore
17
33
  response.headers["X-XSS-Protection"] = "0"
18
34
  end
19
35
 
20
- def permitted_page_attributes
21
- %i[template user_id status feed_enabled published_at
22
- redirect_to image_link news_page
23
- unique_name pinned parent_page_id]
24
- end
25
-
26
- def page_params
27
- params.require(:page).permit(
28
- Page.localized_attributes + permitted_page_attributes
29
- )
30
- end
31
-
32
- def preview_page(page)
33
- redirect_to(page_url(content_locale, page)) && return unless logged_in?
34
-
35
- disable_xss_protection
36
-
37
- @preview = true
38
- page.attributes = page_params.merge(
36
+ def preview_page_params
37
+ ActionController::Parameters.new(
38
+ JSON.parse(params.require(:preview_page))
39
+ ).permit(:id, page_content_attributes).merge(
39
40
  status: 2,
40
41
  published_at: Time.zone.now,
41
42
  locale: content_locale,
42
43
  redirect_to: nil
43
44
  )
44
- render_page
45
45
  end
46
46
  end
47
47
  end
@@ -4,8 +4,6 @@
4
4
  # authorization and other common code for the Admin set of controllers.
5
5
  module PagesCore
6
6
  class AdminController < ::ApplicationController
7
- include PagesCore::Admin::PersistentParams
8
-
9
7
  protect_from_forgery with: :exception
10
8
 
11
9
  before_action :set_i18n_locale
@@ -12,8 +12,8 @@ module PagesCore
12
12
 
13
13
  before_action :load_root_pages
14
14
  before_action :find_page_by_path, only: [:show]
15
- before_action :find_page, only: %i[show preview]
16
- before_action :require_page, only: %i[show preview]
15
+ before_action :find_page, only: %i[show]
16
+ before_action :require_page, only: %i[show]
17
17
  before_action :canonicalize_url, only: [:show]
18
18
  static_cache :index, :show
19
19
 
@@ -27,10 +27,6 @@ module PagesCore
27
27
  end
28
28
  end
29
29
 
30
- def preview
31
- preview_page(@page)
32
- end
33
-
34
30
  def show
35
31
  respond_to do |format|
36
32
  format.html { render_published_page(@page) }
@@ -38,8 +38,7 @@ module PagesCore
38
38
  def find_attachments(str)
39
39
  str.match(attachment_expression)[1]
40
40
  .split(",")
41
- .map { |id| find_attachment(id) }
42
- .compact
41
+ .filter_map { |id| find_attachment(id) }
43
42
  end
44
43
 
45
44
  def find_file(id)
@@ -51,8 +50,7 @@ module PagesCore
51
50
  def find_files(str)
52
51
  str.match(file_expression)[1]
53
52
  .split(",")
54
- .map { |id| find_file(id) }
55
- .compact
53
+ .filter_map { |id| find_file(id) }
56
54
  end
57
55
 
58
56
  def fix_markup(str)
@@ -5,12 +5,13 @@ module Admin
5
5
  include PagesCore::LocalesHelper
6
6
 
7
7
  def header_tabs(group)
8
+ return unless menu_items_for(group).any?
9
+
8
10
  tag.ul(class: group.to_s) do
9
11
  safe_join(menu_items_for(group).map do |item|
10
12
  tag.li do
11
13
  path = instance_eval(&item.path)
12
- link_to(item.label,
13
- path,
14
+ link_to(item.label, path,
14
15
  class: (current_menu_item?(item) ? "current" : ""))
15
16
  end
16
17
  end)
@@ -24,9 +25,9 @@ module Admin
24
25
  .select { |_, routing| routing[:controller] == params[:controller] }
25
26
  end
26
27
 
27
- def find_menu_candidate(&block)
28
+ def find_menu_candidate(&)
28
29
  menu_item_candidates
29
- .select { |item, routing| block.call(item, routing) }
30
+ .select(&)
30
31
  .try(&:first)
31
32
  .try(&:first)
32
33
  end
@@ -2,8 +2,6 @@
2
2
 
3
3
  module Admin
4
4
  module PagesHelper
5
- include PagesCore::Admin::PageBlocksHelper
6
-
7
5
  def autopublish_notice(page)
8
6
  return unless page.autopublish?
9
7
 
@@ -13,22 +11,8 @@ module Admin
13
11
  end
14
12
  end
15
13
 
16
- def available_templates_for_select
17
- PagesCore::Templates.names.collect do |template|
18
- if template == "index"
19
- ["[Default]", "index"]
20
- else
21
- [template.humanize, template]
22
- end
23
- end
24
- end
25
-
26
- def file_embed_code(file)
27
- "[file:#{file.id}]"
28
- end
29
-
30
14
  def news_section_name(page, news_pages)
31
- if news_pages.select { |p| p.name == page.name }.length > 1
15
+ if news_pages.count { |p| p.name == page.name } > 1
32
16
  page_name(page, include_parents: true)
33
17
  else
34
18
  page_name(page)
@@ -83,10 +67,6 @@ module Admin
83
67
 
84
68
  private
85
69
 
86
- def nested_array?(array)
87
- array.present? && array.first.is_a?(Array)
88
- end
89
-
90
70
  def page_name_with_fallback(page)
91
71
  if page.name?
92
72
  page.name.to_s
@@ -7,7 +7,6 @@ module PagesCore
7
7
  include PagesCore::Admin::DateRangeHelper
8
8
  include PagesCore::Admin::ImageUploadsHelper
9
9
  include PagesCore::Admin::LocalesHelper
10
- include PagesCore::Admin::PageJsonHelper
11
10
  include PagesCore::Admin::LabelledFieldHelper
12
11
  include PagesCore::Admin::TagEditorHelper
13
12
 
@@ -18,12 +17,12 @@ module PagesCore
18
17
  value: content))
19
18
  end
20
19
 
21
- def locale_links(&block)
20
+ def locale_links
22
21
  return unless PagesCore.config.localizations?
23
22
 
24
23
  safe_join(
25
24
  PagesCore.config.locales.map do |locale, name|
26
- link_to(name, block.call(locale),
25
+ link_to(name, yield(locale),
27
26
  class: ("current" if locale == params[:locale].to_sym))
28
27
  end
29
28
  )
@@ -31,8 +31,7 @@ module PagesCore
31
31
  class: "content-tab",
32
32
  id: "content-tab-#{key}",
33
33
  role: "tabpanel",
34
- data: { tab: key,
35
- "main-target" => "tab" })
34
+ data: { tab: key })
36
35
  end
37
36
  end
38
37
  end
@@ -53,7 +53,7 @@ module PagesCore
53
53
 
54
54
  def labelled_field_label(label, options = {})
55
55
  tag.label do
56
- safe_join([label, labelled_field_errors(options[:errors])])
56
+ safe_join([label, labelled_field_errors(options[:errors])], " ")
57
57
  end
58
58
  end
59
59
 
@@ -10,6 +10,6 @@ module PagesCore
10
10
  @root_page ||= root_pages.first
11
11
  end
12
12
 
13
- attr_reader :search_query, :search_category_id
13
+ attr_reader :search_query
14
14
  end
15
15
  end
@@ -28,7 +28,8 @@ module PagesCore
28
28
  # * <tt>:ratio</tt>: Ratio to constrain image by.
29
29
  # * <tt>:size</tt>: Max size for image.
30
30
  def image_figure(image, opts = {})
31
- class_name = ["image", image_class_name(image), opts[:class_name]].compact
31
+ class_name = ["image", image_class_name(image, ratio: opts[:ratio]),
32
+ opts[:class_name]].compact
32
33
  image_tag = image_figure_image_tag(image,
33
34
  size: opts[:size],
34
35
  ratio: opts[:ratio])
@@ -47,7 +48,8 @@ module PagesCore
47
48
  # * <tt>:ratio</tt>: Ratio to constrain image by.
48
49
  # * <tt>:sizes</tt>: Sizes attribute for image tag, default: "100vw".
49
50
  def picture(image, opts = {})
50
- class_name = ["image", image_class_name(image), opts[:class_name]].compact
51
+ class_name = ["image", image_class_name(image, ratio: opts[:ratio]),
52
+ opts[:class_name]].compact
51
53
  pict = picture_tag(image, ratio: opts[:ratio], sizes: opts[:sizes])
52
54
  content = opts[:link] ? image_link_to(pict, opts[:link]) : pict
53
55
  tag.figure(content + image_caption(image, caption: opts[:caption]),
@@ -95,9 +97,11 @@ module PagesCore
95
97
  Vector2d.new(v.y * ratio, v.y).fit(v)
96
98
  end
97
99
 
98
- def image_class_name(image)
99
- return "square" if image.size.x == image.size.y
100
- return "landscape" if image.size.x > image.size.y
100
+ def image_class_name(image, ratio: nil)
101
+ size = ratio ? fit_ratio(image.size, ratio) : image.size
102
+
103
+ return "square" if size.x == size.y
104
+ return "landscape" if size.x > size.y
101
105
 
102
106
  "portrait"
103
107
  end
@@ -120,9 +124,7 @@ module PagesCore
120
124
  end
121
125
 
122
126
  def image_widths(image)
123
- [233, 350, 700, 1050, 1400, 2100, 2800].select do |w|
124
- image.size.x >= w
125
- end
127
+ [233, 350, 700, 1050, 1400, 2100, 2800].select { |w| image.size.x >= w }
126
128
  end
127
129
 
128
130
  def srcset(image, ratio: nil, format: nil)
@@ -30,15 +30,10 @@ module PagesCore
30
30
  end
31
31
 
32
32
  def labelled_country_select(
33
- attr, label = nil, priority = {}, opts = {}, html_opts = {}
33
+ attr, label = nil, opts = {}, html_opts = {}
34
34
  )
35
- if priority.is_a?(Hash)
36
- return labelled_field(attr, label, priority) do |options|
37
- country_select(attr, options, opts, html_opts)
38
- end
39
- end
40
35
  labelled_field(attr, label, opts) do |options|
41
- country_select(attr, priority, options, html_opts)
36
+ country_select(attr, options, html_opts)
42
37
  end
43
38
  end
44
39
 
@@ -31,7 +31,7 @@ module PagesCore
31
31
 
32
32
  def page_redirect_url(locale, page)
33
33
  redirect = page.redirect_path(locale:)
34
- return redirect if redirect =~ %r{^https?://}
34
+ return redirect if %r{^https?://}.match?(redirect)
35
35
 
36
36
  base_page_url + redirect
37
37
  end
@@ -1,32 +1,31 @@
1
- import React from "react";
1
+ import React, { MouseEvent } from "react";
2
2
  import copyToClipboard from "../../lib/copyToClipboard";
3
3
  import AttachmentEditor from "./AttachmentEditor";
4
4
  import useModalStore from "../../stores/useModalStore";
5
5
  import useToastStore from "../../stores/useToastStore";
6
- import { AttachmentResource, Locale } from "../../types";
6
+ import * as Attachments from "../../types/Attachments";
7
+ import * as Drag from "../../types/Drag";
8
+ import { Locale } from "../../types";
7
9
 
8
- import { useDraggable, Draggable } from "../drag";
10
+ import { useDraggable } from "../drag";
9
11
 
10
- interface Record {
11
- id: number | null;
12
- attachment: AttachmentResource;
13
- uploading: boolean;
14
- }
15
-
16
- interface AttachmentProps {
12
+ interface Props {
17
13
  attributeName: string;
18
14
  placeholder: boolean;
19
- draggable: { record: Record };
15
+ draggable: Drag.Draggable<Attachments.Record>;
20
16
  locale: string;
21
17
  locales: { [index: string]: Locale };
22
18
  deleteRecord: () => void;
23
19
  showEmbed: boolean;
24
20
  position: number;
25
- onUpdate: (localizations: Record<string, Record<string, string>>) => void;
26
- startDrag: (evt: Event, draggable: Draggable) => void;
21
+ onUpdate: (attachment: Partial<Attachments.Resource>) => void;
22
+ startDrag: (
23
+ evt: MouseEvent,
24
+ draggable: Drag.Draggable<Attachments.Record>
25
+ ) => void;
27
26
  }
28
27
 
29
- export default function Attachment(props: AttachmentProps) {
28
+ export default function Attachment(props: Props) {
30
29
  const { attributeName, draggable, locales, locale } = props;
31
30
  const { record } = draggable;
32
31
  const { attachment, uploading } = record;
@@ -34,15 +33,18 @@ export default function Attachment(props: AttachmentProps) {
34
33
  const openModal = useModalStore((state) => state.open);
35
34
  const notice = useToastStore((state) => state.notice);
36
35
 
37
- const listeners = useDraggable(draggable, props.startDrag);
36
+ const listeners = useDraggable<Attachments.Record>(
37
+ draggable,
38
+ props.startDrag
39
+ );
38
40
 
39
- const copyEmbed = (evt: Event) => {
41
+ const copyEmbed = (evt: MouseEvent) => {
40
42
  evt.preventDefault();
41
43
  copyToClipboard(`[attachment:${attachment.id}]`);
42
44
  notice("Embed code copied to clipboard");
43
45
  };
44
46
 
45
- const deleteRecord = (evt: Event) => {
47
+ const deleteRecord = (evt: MouseEvent) => {
46
48
  evt.preventDefault();
47
49
  if (props.deleteRecord) {
48
50
  props.deleteRecord();
@@ -63,7 +65,7 @@ export default function Attachment(props: AttachmentProps) {
63
65
  return null;
64
66
  };
65
67
 
66
- const editAttachment = (evt: Event) => {
68
+ const editAttachment = (evt: MouseEvent) => {
67
69
  evt.preventDefault();
68
70
  openModal(
69
71
  <AttachmentEditor
@@ -1,18 +1,19 @@
1
- import React, { ChangeEvent, useState } from "react";
1
+ import React, { ChangeEvent, MouseEvent, useState } from "react";
2
2
  import copyToClipboard, { copySupported } from "../../lib/copyToClipboard";
3
3
  import useModalStore from "../../stores/useModalStore";
4
4
  import useToastStore from "../../stores/useToastStore";
5
- import { AttachmentResource, Locale } from "../../types";
6
5
  import { putJson } from "../../lib/request";
6
+ import * as Attachments from "../../types/Attachments";
7
+ import { Locale } from "../../types";
7
8
 
8
- interface AttachmentEditorProps {
9
- attachment: AttachmentResource;
9
+ interface Props {
10
+ attachment: Attachments.Resource;
10
11
  locale: string;
11
12
  locales: { [index: string]: Locale };
12
- onUpdate: (localizations: Record<string, Record<string, string>>) => void;
13
+ onUpdate: (attachment: Partial<Attachments.Resource>) => void;
13
14
  }
14
15
 
15
- export default function AttachmentEditor(props: AttachmentEditorProps) {
16
+ export default function AttachmentEditor(props: Props) {
16
17
  const { attachment, locales } = props;
17
18
 
18
19
  const [locale, setLocale] = useState(props.locale);
@@ -25,20 +26,21 @@ export default function AttachmentEditor(props: AttachmentEditorProps) {
25
26
  const closeModal = useModalStore((state) => state.close);
26
27
 
27
28
  const updateLocalization =
28
- (name: "name" | "description") => (evt: ChangeEvent<HTMLInputElement>) => {
29
+ (name: "name" | "description") =>
30
+ (evt: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>) => {
29
31
  setLocalizations({
30
32
  ...localizations,
31
33
  [name]: { ...localizations[name], [locale]: evt.target.value }
32
34
  });
33
35
  };
34
36
 
35
- const copyEmbedCode = (evt: Event) => {
37
+ const copyEmbedCode = (evt: MouseEvent) => {
36
38
  evt.preventDefault();
37
39
  copyToClipboard(`[attachment:${attachment.id}]`);
38
40
  notice("Embed code copied to clipboard");
39
41
  };
40
42
 
41
- const save = (evt: Event) => {
43
+ const save = (evt: MouseEvent) => {
42
44
  evt.preventDefault();
43
45
  evt.stopPropagation();
44
46