pages_core 3.14.0 → 3.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/app/assets/builds/fonts/6569749d.ttf +0 -0
  4. data/app/assets/builds/fonts/7b7db107.woff2 +0 -0
  5. data/app/assets/builds/fonts/921961e9.woff2 +0 -0
  6. data/app/assets/builds/fonts/ee32bc60.ttf +0 -0
  7. data/app/assets/builds/pages_core/admin-dist.js +19 -8
  8. data/app/assets/builds/pages_core/admin-dist.js.map +4 -4
  9. data/app/assets/builds/pages_core/admin.css +699 -394
  10. data/app/assets/builds/pages_core/mailer.css +99 -0
  11. data/app/assets/fonts/Inter-Black.woff2 +0 -0
  12. data/app/assets/fonts/Inter-BlackItalic.woff2 +0 -0
  13. data/app/assets/fonts/Inter-Bold.woff2 +0 -0
  14. data/app/assets/fonts/Inter-BoldItalic.woff2 +0 -0
  15. data/app/assets/fonts/Inter-ExtraBold.woff2 +0 -0
  16. data/app/assets/fonts/Inter-ExtraBoldItalic.woff2 +0 -0
  17. data/app/assets/fonts/Inter-ExtraLight.woff2 +0 -0
  18. data/app/assets/fonts/Inter-ExtraLightItalic.woff2 +0 -0
  19. data/app/assets/fonts/Inter-Italic.woff2 +0 -0
  20. data/app/assets/fonts/Inter-Light.woff2 +0 -0
  21. data/app/assets/fonts/Inter-LightItalic.woff2 +0 -0
  22. data/app/assets/fonts/Inter-Medium.woff2 +0 -0
  23. data/app/assets/fonts/Inter-MediumItalic.woff2 +0 -0
  24. data/app/assets/fonts/Inter-Regular.woff2 +0 -0
  25. data/app/assets/fonts/Inter-SemiBold.woff2 +0 -0
  26. data/app/assets/fonts/Inter-SemiBoldItalic.woff2 +0 -0
  27. data/app/assets/fonts/Inter-Thin.woff2 +0 -0
  28. data/app/assets/fonts/Inter-ThinItalic.woff2 +0 -0
  29. data/app/assets/fonts/InterDisplay-Black.woff2 +0 -0
  30. data/app/assets/fonts/InterDisplay-BlackItalic.woff2 +0 -0
  31. data/app/assets/fonts/InterDisplay-Bold.woff2 +0 -0
  32. data/app/assets/fonts/InterDisplay-BoldItalic.woff2 +0 -0
  33. data/app/assets/fonts/InterDisplay-ExtraBold.woff2 +0 -0
  34. data/app/assets/fonts/InterDisplay-ExtraBoldItalic.woff2 +0 -0
  35. data/app/assets/fonts/InterDisplay-ExtraLight.woff2 +0 -0
  36. data/app/assets/fonts/InterDisplay-ExtraLightItalic.woff2 +0 -0
  37. data/app/assets/fonts/InterDisplay-Italic.woff2 +0 -0
  38. data/app/assets/fonts/InterDisplay-Light.woff2 +0 -0
  39. data/app/assets/fonts/InterDisplay-LightItalic.woff2 +0 -0
  40. data/app/assets/fonts/InterDisplay-Medium.woff2 +0 -0
  41. data/app/assets/fonts/InterDisplay-MediumItalic.woff2 +0 -0
  42. data/app/assets/fonts/InterDisplay-Regular.woff2 +0 -0
  43. data/app/assets/fonts/InterDisplay-SemiBold.woff2 +0 -0
  44. data/app/assets/fonts/InterDisplay-SemiBoldItalic.woff2 +0 -0
  45. data/app/assets/fonts/InterDisplay-Thin.woff2 +0 -0
  46. data/app/assets/fonts/InterDisplay-ThinItalic.woff2 +0 -0
  47. data/app/assets/fonts/InterVariable-Italic.woff2 +0 -0
  48. data/app/assets/fonts/InterVariable.woff2 +0 -0
  49. data/app/assets/stylesheets/pages_core/admin/components/archive.css +1 -1
  50. data/app/assets/stylesheets/pages_core/admin/components/attachments.css +22 -34
  51. data/app/assets/stylesheets/pages_core/admin/components/base.css +1 -68
  52. data/app/assets/stylesheets/pages_core/admin/components/forms.css +109 -48
  53. data/app/assets/stylesheets/pages_core/admin/components/header.css +56 -58
  54. data/app/assets/stylesheets/pages_core/admin/components/image_editor.css +35 -24
  55. data/app/assets/stylesheets/pages_core/admin/components/image_grid.css +28 -27
  56. data/app/assets/stylesheets/pages_core/admin/components/image_uploader.css +5 -5
  57. data/app/assets/stylesheets/pages_core/admin/components/layout.css +7 -1
  58. data/app/assets/stylesheets/pages_core/admin/components/list_table.css +24 -15
  59. data/app/assets/stylesheets/pages_core/admin/components/page_tree.css +63 -104
  60. data/app/assets/stylesheets/pages_core/admin/components/pagination.css +12 -13
  61. data/app/assets/stylesheets/pages_core/admin/components/search.css +1 -16
  62. data/app/assets/stylesheets/pages_core/admin/components/sidebar.css +5 -11
  63. data/app/assets/stylesheets/pages_core/admin/components/tag_editor.css +22 -36
  64. data/app/assets/stylesheets/pages_core/admin/components/toast.css +1 -2
  65. data/app/assets/stylesheets/pages_core/admin/components/toolbar.css +10 -10
  66. data/app/assets/stylesheets/pages_core/admin/components/totp.css +1 -1
  67. data/app/assets/stylesheets/pages_core/admin/controllers/pages.css +37 -51
  68. data/app/assets/stylesheets/pages_core/admin/global/fonts.css +271 -0
  69. data/app/assets/stylesheets/pages_core/admin/global/typography.css +109 -0
  70. data/app/assets/stylesheets/pages_core/admin/vars.css +1 -3
  71. data/app/assets/stylesheets/pages_core/{admin.postcss.css → admin.css} +1 -0
  72. data/app/assets/stylesheets/pages_core/mailer.css +90 -0
  73. data/app/controllers/admin/account_recoveries_controller.rb +2 -2
  74. data/app/controllers/admin/pages_controller.rb +22 -42
  75. data/app/controllers/concerns/pages_core/error_reporting.rb +1 -1
  76. data/app/controllers/concerns/pages_core/page_parameters.rb +29 -0
  77. data/app/controllers/concerns/pages_core/policies_helper.rb +1 -1
  78. data/app/controllers/concerns/pages_core/preview_pages_controller.rb +20 -20
  79. data/app/controllers/pages_core/admin_controller.rb +0 -2
  80. data/app/controllers/pages_core/frontend/pages_controller.rb +2 -6
  81. data/app/formatters/pages_core/html_formatter.rb +2 -4
  82. data/app/helpers/admin/menu_helper.rb +5 -4
  83. data/app/helpers/admin/pages_helper.rb +1 -21
  84. data/app/helpers/pages_core/admin/admin_helper.rb +2 -3
  85. data/app/helpers/pages_core/admin/content_tabs_helper.rb +1 -2
  86. data/app/helpers/pages_core/admin/labelled_field_helper.rb +1 -1
  87. data/app/helpers/pages_core/attachments_helper.rb +1 -1
  88. data/app/helpers/pages_core/frontend_helper.rb +1 -1
  89. data/app/helpers/pages_core/images_helper.rb +10 -8
  90. data/app/helpers/pages_core/labelled_form_builder.rb +2 -7
  91. data/app/helpers/pages_core/page_path_helper.rb +1 -1
  92. data/app/javascript/components/Attachments/Attachment.tsx +20 -18
  93. data/app/javascript/components/Attachments/AttachmentEditor.tsx +11 -9
  94. data/app/javascript/components/{Attachments.jsx → Attachments/List.tsx} +58 -63
  95. data/app/javascript/components/Attachments/useAttachments.ts +15 -0
  96. data/app/javascript/components/Attachments.tsx +14 -0
  97. data/app/javascript/components/DateRangeSelect.tsx +105 -0
  98. data/app/javascript/components/DateTimeSelect.tsx +136 -0
  99. data/app/javascript/components/EditableImage.tsx +11 -9
  100. data/app/javascript/components/FileUploadButton.tsx +7 -7
  101. data/app/javascript/components/ImageCropper/FocalPoint.tsx +9 -12
  102. data/app/javascript/components/ImageCropper/Image.tsx +10 -8
  103. data/app/javascript/components/ImageCropper/Toolbar.tsx +11 -12
  104. data/app/javascript/components/ImageCropper/useCrop.ts +24 -53
  105. data/app/javascript/components/ImageCropper.tsx +10 -15
  106. data/app/javascript/components/ImageEditor/Form.tsx +12 -8
  107. data/app/javascript/components/ImageEditor.tsx +12 -7
  108. data/app/javascript/components/ImageGrid/DragElement.tsx +9 -12
  109. data/app/javascript/components/{ImageGrid.jsx → ImageGrid/Grid.tsx} +62 -71
  110. data/app/javascript/components/ImageGrid/GridImage.tsx +22 -23
  111. data/app/javascript/components/ImageGrid/Placeholder.tsx +2 -2
  112. data/app/javascript/components/ImageGrid/useImageGrid.ts +26 -0
  113. data/app/javascript/components/ImageGrid.tsx +15 -0
  114. data/app/javascript/components/ImageUploader.tsx +35 -22
  115. data/app/javascript/components/LabelledField.tsx +34 -0
  116. data/app/javascript/components/Modal.tsx +2 -2
  117. data/app/javascript/components/PageForm/Block.tsx +81 -0
  118. data/app/javascript/components/PageForm/Content.tsx +54 -0
  119. data/app/javascript/components/PageForm/Dates.tsx +66 -0
  120. data/app/javascript/components/PageForm/Files.tsx +28 -0
  121. data/app/javascript/components/PageForm/Form.tsx +41 -0
  122. data/app/javascript/components/PageForm/Images.tsx +28 -0
  123. data/app/javascript/components/PageForm/LocaleLinks.tsx +36 -0
  124. data/app/javascript/components/PageForm/Metadata.tsx +67 -0
  125. data/app/javascript/components/PageForm/Options.tsx +180 -0
  126. data/app/javascript/components/PageForm/PageDescription.tsx +48 -0
  127. data/app/javascript/components/PageForm/PathSegment.tsx +65 -0
  128. data/app/javascript/components/PageForm/TabPanel.tsx +21 -0
  129. data/app/javascript/components/PageForm/Tabs.tsx +33 -0
  130. data/app/javascript/components/PageForm/UnconfiguredContent.tsx +42 -0
  131. data/app/javascript/components/PageForm/pageParams.ts +95 -0
  132. data/app/javascript/components/PageForm/preview.ts +23 -0
  133. data/app/javascript/components/PageForm/usePage.ts +169 -0
  134. data/app/javascript/components/PageForm/useTabs.ts +46 -0
  135. data/app/javascript/components/PageForm.tsx +169 -0
  136. data/app/javascript/components/PageImages.tsx +7 -9
  137. data/app/javascript/components/PageTree/Draggable.tsx +40 -39
  138. data/app/javascript/components/PageTree/Node.tsx +62 -56
  139. data/app/javascript/components/PageTree/PageName.tsx +28 -0
  140. data/app/javascript/components/PageTree.tsx +65 -53
  141. data/app/javascript/components/{RichTextArea.jsx → RichTextArea.tsx} +98 -79
  142. data/app/javascript/components/RichTextToolbarButton.tsx +4 -6
  143. data/app/javascript/components/TagEditor/AddTagForm.tsx +19 -12
  144. data/app/javascript/components/TagEditor/Editor.tsx +32 -0
  145. data/app/javascript/components/TagEditor/Tag.tsx +6 -4
  146. data/app/javascript/components/TagEditor/useTags.ts +58 -0
  147. data/app/javascript/components/TagEditor.tsx +8 -58
  148. data/app/javascript/components/Toast.tsx +3 -3
  149. data/app/javascript/components/drag/draggedOrder.ts +22 -14
  150. data/app/javascript/components/drag/useDragCollection.ts +35 -30
  151. data/app/javascript/components/drag/useDragUploader.ts +32 -21
  152. data/app/javascript/components/drag/useDraggable.ts +7 -6
  153. data/app/javascript/components/drag.ts +0 -1
  154. data/app/javascript/components.ts +1 -3
  155. data/app/javascript/features/RichText.tsx +2 -3
  156. data/app/javascript/features/contentTabs.ts +79 -0
  157. data/app/javascript/index.ts +5 -12
  158. data/app/javascript/lib/Tree.ts +31 -45
  159. data/app/javascript/lib/request.ts +11 -11
  160. data/app/javascript/stores/useToastStore.ts +1 -1
  161. data/app/javascript/types/Attachments.ts +29 -0
  162. data/app/javascript/types/Crop.ts +36 -0
  163. data/app/javascript/types/Drag.ts +34 -0
  164. data/app/javascript/types/Images.ts +47 -0
  165. data/app/javascript/types/PageEditor.ts +26 -0
  166. data/app/javascript/types/Pages.ts +75 -0
  167. data/app/javascript/types/Tags.ts +9 -0
  168. data/app/javascript/types/Template.ts +24 -0
  169. data/app/javascript/types/Trees.ts +19 -0
  170. data/app/javascript/types.ts +2 -25
  171. data/app/mailers/admin_mailer.rb +5 -9
  172. data/app/models/attachment.rb +1 -1
  173. data/app/models/autopublisher.rb +1 -1
  174. data/app/models/concerns/pages_core/authenticable_user.rb +63 -0
  175. data/app/models/concerns/pages_core/emailable.rb +16 -0
  176. data/app/models/concerns/pages_core/page_model/dated_page.rb +3 -3
  177. data/app/models/concerns/pages_core/page_model/templateable.rb +2 -16
  178. data/app/models/concerns/pages_core/taggable.rb +2 -19
  179. data/app/models/invite.rb +2 -6
  180. data/app/models/otp_secret.rb +4 -4
  181. data/app/models/page.rb +0 -3
  182. data/app/models/user.rb +2 -46
  183. data/app/policies/page_policy.rb +6 -2
  184. data/app/resources/admin/page_resource.rb +95 -0
  185. data/app/resources/admin/page_tree_resource.rb +27 -0
  186. data/app/resources/admin/template_configuration_resource.rb +50 -0
  187. data/app/views/admin/news/_sidebar.html.erb +2 -4
  188. data/app/views/admin/news/index.html.erb +0 -1
  189. data/app/views/admin/pages/_form.html.erb +10 -30
  190. data/app/views/admin/pages/_search_bar.html.erb +1 -1
  191. data/app/views/admin/pages/edit.html.erb +1 -57
  192. data/app/views/admin/pages/index.html.erb +1 -1
  193. data/app/views/admin/pages/new.html.erb +1 -44
  194. data/app/views/admin/sessions/new.html.erb +9 -11
  195. data/app/views/admin/users/_access_control.html.erb +5 -1
  196. data/app/views/admin/users/_list.html.erb +12 -7
  197. data/app/views/admin_mailer/account_recovery.html.erb +20 -0
  198. data/app/views/admin_mailer/invite.html.erb +11 -0
  199. data/app/views/layouts/admin/_header.html.erb +2 -4
  200. data/app/views/layouts/admin/_page_header.html.erb +1 -2
  201. data/app/views/layouts/admin.html.erb +1 -1
  202. data/app/views/layouts/pages_core/mailer.html.erb +11 -0
  203. data/config/locales/en.yml +0 -4
  204. data/config/routes.rb +3 -7
  205. data/db/migrate/20240126160700_add_2fa_fields.rb +5 -1
  206. data/db/migrate/20240131140700_change_email_to_citext.rb +18 -0
  207. data/db/migrate/20240201160700_remove_persistent_data.rb +7 -0
  208. data/db/migrate/20240508145300_remove_categories.rb +21 -0
  209. data/lib/pages_core/configuration/base.rb +2 -2
  210. data/lib/pages_core/engine.rb +1 -0
  211. data/lib/pages_core/templates/configuration.rb +1 -1
  212. data/lib/pages_core/templates/configuration_proxy.rb +2 -2
  213. data/lib/pages_core/templates/template_configuration.rb +11 -1
  214. data/lib/pages_core/templates.rb +6 -4
  215. data/lib/pages_core/version.rb +1 -1
  216. data/lib/pages_core.rb +1 -0
  217. data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/gridOverlay.ts +6 -7
  218. data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/responsiveEmbeds.ts +17 -12
  219. data/lib/rails/generators/pages_core/rspec/rspec_generator.rb +0 -2
  220. data/lib/rails/generators/pages_core/rspec/templates/rails_helper.rb +3 -4
  221. metadata +119 -36
  222. data/app/assets/builds/fonts/2a3059ad.ttf +0 -0
  223. data/app/assets/builds/fonts/47262711.woff2 +0 -0
  224. data/app/assets/builds/fonts/500ddeb0.woff2 +0 -0
  225. data/app/assets/builds/fonts/81221036.ttf +0 -0
  226. data/app/assets/stylesheets/pages_core/admin/components/login.css +0 -27
  227. data/app/controllers/admin/categories_controller.rb +0 -56
  228. data/app/controllers/concerns/pages_core/admin/persistent_params.rb +0 -75
  229. data/app/helpers/pages_core/admin/page_blocks_helper.rb +0 -66
  230. data/app/helpers/pages_core/admin/page_json_helper.rb +0 -23
  231. data/app/javascript/components/DateRangeSelect.jsx +0 -225
  232. data/app/javascript/components/PageDates.jsx +0 -73
  233. data/app/javascript/components/PageFiles.jsx +0 -25
  234. data/app/javascript/components/PageTree/types.ts +0 -15
  235. data/app/javascript/components/drag/types.ts +0 -28
  236. data/app/javascript/controllers/EditPageController.ts +0 -22
  237. data/app/javascript/controllers/MainController.ts +0 -74
  238. data/app/javascript/controllers/PageOptionsController.js +0 -67
  239. data/app/models/category.rb +0 -22
  240. data/app/models/concerns/pages_core/has_otp.rb +0 -27
  241. data/app/models/page_category.rb +0 -6
  242. data/app/views/admin/pages/_edit_content.html.erb +0 -19
  243. data/app/views/admin/pages/_edit_files.html.erb +0 -4
  244. data/app/views/admin/pages/_edit_images.html.erb +0 -4
  245. data/app/views/admin/pages/_edit_metadata.html.erb +0 -35
  246. data/app/views/admin/pages/_edit_options.html.erb +0 -91
  247. data/app/views/admin_mailer/account_recovery.text.erb +0 -10
  248. data/app/views/admin_mailer/invite.text.erb +0 -7
  249. data/lib/rails/generators/pages_core/rspec/templates/mailer_macros.rb +0 -11
@@ -1,225 +0,0 @@
1
- import React from "react";
2
- import PropTypes from "prop-types";
3
-
4
- export default class DateRangeSelect extends React.Component {
5
- constructor(props) {
6
- super(props);
7
- this.state = {
8
- startsAt: this.parseDate(props.startsAt) || this.defaultDate(),
9
- endsAt: this.parseDate(props.endsAt) || this.defaultDate(60),
10
- startTime: "",
11
- endTime: ""
12
- };
13
- this.state.startTime = this.timeToString(this.state.startsAt);
14
- this.state.endTime = this.timeToString(this.state.endsAt);
15
-
16
- this.changeStartsAt = this.changeStartsAt.bind(this);
17
- this.changeEndsAt = this.changeEndsAt.bind(this);
18
- }
19
-
20
- changeStartsAt(options = {}) {
21
- let newDate = this.modifyDate(this.state.startsAt, options);
22
- this.setDates(
23
- newDate,
24
- new Date(this.state.endsAt.getTime() + (newDate - this.state.startsAt))
25
- );
26
- }
27
-
28
- changeEndsAt(options = {}) {
29
- let newDate = this.modifyDate(this.state.endsAt, options);
30
- this.setDates(this.state.startsAt, newDate);
31
- }
32
-
33
- defaultDate(offset = 0) {
34
- let coeff = 1000 * 60 * 60;
35
- return new Date(
36
- Math.round(new Date().getTime() / coeff) * coeff +
37
- coeff +
38
- 1000 * 60 * offset
39
- );
40
- }
41
-
42
- modifyDate(original, options = {}) {
43
- var newDate = new Date(original);
44
- if (Object.prototype.hasOwnProperty.call(options, "year")) {
45
- newDate.setFullYear(options.year);
46
- }
47
- if (Object.prototype.hasOwnProperty.call(options, "month")) {
48
- newDate.setMonth(options.month);
49
- }
50
- if (Object.prototype.hasOwnProperty.call(options, "date")) {
51
- newDate.setDate(options.date);
52
- }
53
- if (
54
- Object.prototype.hasOwnProperty.call(options, "time") &&
55
- options.time.match(/^[\d]{1,2}(:[\d]{1,2})?$/)
56
- ) {
57
- newDate.setHours(options.time.split(":")[0]);
58
- newDate.setMinutes(options.time.split(":")[1] || 0);
59
- }
60
- return newDate;
61
- }
62
-
63
- parseDate(str) {
64
- if (!str) {
65
- return;
66
- }
67
- return new Date(str);
68
- }
69
-
70
- setDates(start, end) {
71
- if (end < start) {
72
- end = start;
73
- }
74
- this.setState({
75
- startsAt: start,
76
- endsAt: end,
77
- startTime: this.timeToString(start),
78
- endTime: this.timeToString(end)
79
- });
80
- }
81
-
82
- startsAtToString() {
83
- if (this.props.disabled) {
84
- return "";
85
- }
86
- return this.state.startsAt.toJSON();
87
- }
88
-
89
- endsAtToString() {
90
- if (this.props.disabled) {
91
- return "";
92
- }
93
- return this.state.endsAt.toJSON();
94
- }
95
-
96
- renderDateSelect(key, date, handleChange) {
97
- return (
98
- <div className="date-select">
99
- <select
100
- value={date.getMonth()}
101
- onChange={(e) => handleChange({ month: e.target.value })}
102
- disabled={this.props.disabled}>
103
- {this.monthOptions().map((m, i) => (
104
- <option key={key + "-month-" + i} value={i}>
105
- {m}
106
- </option>
107
- ))}
108
- </select>
109
- <select
110
- value={date.getDate()}
111
- onChange={(e) => handleChange({ date: e.target.value })}
112
- disabled={this.props.disabled}>
113
- {this.dayOptions().map((d) => (
114
- <option key={key + "-date-" + d} value={d}>
115
- {d}
116
- </option>
117
- ))}
118
- </select>
119
- <select
120
- value={date.getFullYear()}
121
- onChange={(e) => handleChange({ year: e.target.value })}
122
- disabled={this.props.disabled}>
123
- {this.yearOptions().map((y) => (
124
- <option key={key + "-year-" + y} value={y}>
125
- {y}
126
- </option>
127
- ))}
128
- </select>
129
- </div>
130
- );
131
- }
132
-
133
- render() {
134
- return (
135
- <div className="date-range-select">
136
- <input
137
- type="hidden"
138
- name={this.props.objectName + "[starts_at]"}
139
- value={this.startsAtToString()}
140
- />
141
- <input
142
- type="hidden"
143
- name={this.props.objectName + "[ends_at]"}
144
- value={this.endsAtToString()}
145
- />
146
- <div className="date">
147
- {this.renderDateSelect(
148
- "starts-at",
149
- this.state.startsAt,
150
- this.changeStartsAt
151
- )}
152
- {!this.props.disableTime && (
153
- <input
154
- type="text"
155
- size="5"
156
- value={this.state.startTime}
157
- disabled={this.props.disabled}
158
- onChange={(e) => this.setState({ startTime: e.target.value })}
159
- onBlur={(e) => this.changeStartsAt({ time: e.target.value })}
160
- />
161
- )}
162
- </div>
163
- <span className="to">to</span>
164
- <div className="date">
165
- {this.renderDateSelect(
166
- "ends-at",
167
- this.state.endsAt,
168
- this.changeEndsAt
169
- )}
170
- {!this.props.disableTime && (
171
- <input
172
- type="text"
173
- size="5"
174
- value={this.state.endTime}
175
- disabled={this.props.disabled}
176
- onChange={(e) => this.setState({ endTime: e.target.value })}
177
- onBlur={(e) => this.changeEndsAt({ time: e.target.value })}
178
- />
179
- )}
180
- </div>
181
- </div>
182
- );
183
- }
184
-
185
- timeToString(time) {
186
- return time.toTimeString().slice(0, 5);
187
- }
188
-
189
- // Returns an array with years from 2000 to 10 years from now.
190
- yearOptions() {
191
- let start = 2000;
192
- return Array.apply(null, Array(new Date().getFullYear() - start + 11)).map(
193
- (_, i) => i + start
194
- );
195
- }
196
-
197
- monthOptions() {
198
- return [
199
- "January",
200
- "February",
201
- "March",
202
- "April",
203
- "May",
204
- "June",
205
- "July",
206
- "August",
207
- "September",
208
- "October",
209
- "November",
210
- "December"
211
- ];
212
- }
213
-
214
- dayOptions() {
215
- return Array.apply(null, Array(31)).map((_, i) => i + 1);
216
- }
217
- }
218
-
219
- DateRangeSelect.propTypes = {
220
- startsAt: PropTypes.string,
221
- endsAt: PropTypes.string,
222
- disabled: PropTypes.bool,
223
- disableTime: PropTypes.bool,
224
- objectName: PropTypes.string
225
- };
@@ -1,73 +0,0 @@
1
- import React from "react";
2
- import PropTypes from "prop-types";
3
- import DateRangeSelect from "./DateRangeSelect";
4
-
5
- export default class PageDates extends React.Component {
6
- constructor(props) {
7
- super(props);
8
- this.state = {
9
- has_dates: props.starts_at ? true : false,
10
- all_day: !!props.all_day
11
- };
12
-
13
- this.toggleAllDay = this.toggleAllDay.bind(this);
14
- this.toggleHasDates = this.toggleHasDates.bind(this);
15
- }
16
-
17
- toggleHasDates() {
18
- this.setState({ has_dates: !this.state.has_dates });
19
- }
20
-
21
- toggleAllDay() {
22
- this.setState({ all_day: !this.state.all_day });
23
- }
24
-
25
- timeToString(time) {
26
- return time.toTimeString().slice(0, 5);
27
- }
28
-
29
- render() {
30
- return (
31
- <div className="page-dates field">
32
- <input
33
- type="hidden"
34
- name="page[all_day]"
35
- value={this.state.has_dates && this.state.all_day ? "1" : "0"}
36
- />
37
- <label>Dates</label>
38
- <div className="toggles">
39
- <label className="has-dates-toggle">
40
- <input
41
- type="checkbox"
42
- checked={this.state.has_dates}
43
- onChange={this.toggleHasDates}
44
- />
45
- Enabled
46
- </label>
47
- <label className={!this.state.has_dates && "disabled"}>
48
- <input
49
- type="checkbox"
50
- disabled={!this.state.has_dates}
51
- checked={this.state.all_day}
52
- onChange={this.toggleAllDay}
53
- />
54
- All day event
55
- </label>
56
- </div>
57
- <DateRangeSelect
58
- objectName="page"
59
- startsAt={this.props.starts_at}
60
- endsAt={this.props.ends_at}
61
- disabled={!this.state.has_dates}
62
- disableTime={this.state.all_day}
63
- />
64
- </div>
65
- );
66
- }
67
- }
68
-
69
- PageDates.propTypes = {
70
- starts_at: PropTypes.string,
71
- ends_at: PropTypes.string,
72
- all_day: PropTypes.bool
73
- };
@@ -1,25 +0,0 @@
1
- import React from "react";
2
- import PropTypes from "prop-types";
3
- import Attachments from "./Attachments";
4
-
5
- export default class PageFiles extends React.Component {
6
- render() {
7
- return (
8
- <div className="page-files">
9
- <Attachments
10
- attribute="page[page_files_attributes]"
11
- showEmbed={true}
12
- locale={this.props.locale}
13
- locales={this.props.locales}
14
- records={this.props.records}
15
- />
16
- </div>
17
- );
18
- }
19
- }
20
-
21
- PageFiles.propTypes = {
22
- locale: PropTypes.string,
23
- locales: PropTypes.object,
24
- records: PropTypes.array
25
- };
@@ -1,15 +0,0 @@
1
- import { TreeNode } from "../../lib/Tree";
2
-
3
- export type Attributes = Record<string, unknown>;
4
-
5
- export interface PageNode extends TreeNode {
6
- id: number | null;
7
- children: PageNode[];
8
- editing: boolean;
9
- locale: string;
10
- name: string;
11
- param: string;
12
- permissions: string[];
13
- published_at: string;
14
- status: string;
15
- }
@@ -1,28 +0,0 @@
1
- export type DraggableRecord = Record<string, unknown>;
2
-
3
- export interface Draggable {
4
- record: DraggableRecord;
5
- ref: React.MutableRefObject<HTMLDivElement>;
6
- rect: DOMRect | null;
7
- handle: string;
8
- }
9
-
10
- export interface DragCollectionAction {
11
- type: string;
12
- payload?: Draggable[] | Draggable | null;
13
- }
14
-
15
- export interface DragCollection {
16
- ref: React.MutableRefObject<HTMLDivElement>;
17
- draggables: Draggable[];
18
- dispatch: (DragCollectionAction) => void;
19
- }
20
-
21
- export interface Position {
22
- x: number | null;
23
- y: number | null;
24
- }
25
-
26
- export interface DragState extends Position {
27
- dragging: Draggable | false;
28
- }
@@ -1,22 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus";
2
-
3
- export default class EditPageController extends Controller<HTMLFormElement> {
4
- declare readonly formTarget: HTMLFormElement;
5
-
6
- static get targets() {
7
- return ["form"];
8
- }
9
-
10
- preview() {
11
- const form = this.formTarget;
12
- const prevAction = form.action;
13
- const prevTarget = form.target;
14
-
15
- form.target = "_blank";
16
- form.action = form.dataset.previewUrl;
17
- form.submit();
18
-
19
- form.action = prevAction;
20
- form.target = prevTarget;
21
- }
22
- }
@@ -1,74 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus";
2
-
3
- export default class MainController extends Controller {
4
- declare readonly linkTargets: HTMLLinkElement[];
5
- declare readonly tabTargets: HTMLDivElement[];
6
-
7
- static get targets() {
8
- return ["tab", "link"];
9
- }
10
-
11
- connect() {
12
- const tabs = this.tabNames();
13
- if (tabs.length > 0) {
14
- let initTab: string = null;
15
- const tabExpression = /#(.*)$/;
16
-
17
- if (document.location.toString().match(tabExpression)) {
18
- const id = document.location.toString().match(tabExpression)[1];
19
- if (tabs.indexOf(id) !== -1) {
20
- initTab = id;
21
- }
22
- }
23
-
24
- this.showTab(initTab || tabs[0]);
25
- }
26
-
27
- window.addEventListener("popstate", this.stateHandler);
28
- }
29
-
30
- disconnect() {
31
- window.removeEventListener("popstate", this.stateHandler);
32
- }
33
-
34
- stateHandler = (evt: Event) => {
35
- if ("state" in evt && "tabId" in evt.state) {
36
- this.showTab(evt.state.tabId);
37
- }
38
- };
39
-
40
- changeTab(evt: Event) {
41
- evt.preventDefault();
42
- if ("dataset" in evt.target && "tab" in evt.target.dataset) {
43
- const tab = evt.target.dataset.tab as string;
44
- this.showTab(tab);
45
- history.pushState(
46
- { tabId: tab },
47
- "",
48
- `${window.location.pathname}#${tab}`
49
- );
50
- }
51
- }
52
-
53
- showTab(tab: string | null) {
54
- this.linkTargets.forEach((l) => {
55
- if (l.dataset.tab == tab) {
56
- l.classList.add("current");
57
- } else {
58
- l.classList.remove("current");
59
- }
60
- });
61
-
62
- this.tabTargets.forEach((t) => {
63
- if (t.dataset.tab == tab) {
64
- t.classList.remove("hidden");
65
- } else {
66
- t.classList.add("hidden");
67
- }
68
- });
69
- }
70
-
71
- tabNames(): string[] {
72
- return this.linkTargets.map((l) => l.dataset.tab);
73
- }
74
- }
@@ -1,67 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus";
2
-
3
- export default class PageOptionsController extends Controller {
4
- static get targets() {
5
- return [
6
- "advancedOptions",
7
- "autoPublishNotice",
8
- "published",
9
- "publishedDate"
10
- ];
11
- }
12
-
13
- connect() {
14
- this.checkAutoPublish();
15
- this.checkPublishedDate();
16
- }
17
-
18
- checkAutoPublish() {
19
- if (this.publishedDate() > new Date()) {
20
- this.show(this.autoPublishNoticeTarget);
21
- } else {
22
- this.hide(this.autoPublishNoticeTarget);
23
- }
24
- }
25
-
26
- checkPublishedDate() {
27
- if (this.publishedTarget.value == 2) {
28
- this.show(this.publishedDateTarget);
29
- } else {
30
- this.hide(this.publishedDateTarget);
31
- }
32
- }
33
-
34
- publishedDate() {
35
- const lookup = (name) => {
36
- return this.publishedDateTarget.getElementsByClassName(name)[0].value;
37
- };
38
- return new Date(
39
- lookup("year"),
40
- lookup("month") - 1,
41
- lookup("day"),
42
- lookup("hour"),
43
- lookup("minute")
44
- );
45
- }
46
-
47
- show(elem) {
48
- elem.classList.add("show");
49
- }
50
-
51
- hide(elem) {
52
- elem.classList.remove("show");
53
- }
54
-
55
- toggle(elem) {
56
- if (elem.classList.contains("show")) {
57
- this.hide(elem);
58
- } else {
59
- this.show(elem);
60
- }
61
- }
62
-
63
- toggleAdvancedOptions(evt) {
64
- evt.preventDefault();
65
- this.toggle(this.advancedOptionsTarget);
66
- }
67
- }
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Category < ApplicationRecord
4
- has_many :page_categories, dependent: :destroy
5
- has_many :pages, through: :page_categories
6
- validates :name, presence: true
7
- acts_as_list
8
-
9
- before_save :set_slug
10
-
11
- scope :by_name, -> { order("name ASC") }
12
-
13
- private
14
-
15
- def set_slug
16
- self.slug = name.downcase
17
- .gsub(/[^\w\s]/, "")
18
- .split(/[^\w\d-]+/)
19
- .compact
20
- .join("-")
21
- end
22
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PagesCore
4
- module HasOtp
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- validates :otp_secret, presence: true, if: :otp_enabled?
9
- end
10
-
11
- def recovery_codes=(codes)
12
- self.hashed_recovery_codes = codes.map do |c|
13
- BCrypt::Password.create(c, cost: 8)
14
- end
15
- end
16
-
17
- def use_recovery_code!(code)
18
- valid_hashes = hashed_recovery_codes.select do |c|
19
- BCrypt::Password.new(c) == code
20
- end
21
- return false unless valid_hashes.any?
22
-
23
- update(hashed_recovery_codes: hashed_recovery_codes - valid_hashes)
24
- true
25
- end
26
- end
27
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class PageCategory < ApplicationRecord
4
- belongs_to :page
5
- belongs_to :category
6
- end
@@ -1,19 +0,0 @@
1
- <% @page.enabled_blocks do |block_name, block_options| %>
2
- <%= page_block_field(f, block_name, block_options) %>
3
- <% end %>
4
-
5
- <% if @page.template_config.value(:dates) %>
6
- <%= react_component("PageDates",
7
- { starts_at: @page.starts_at,
8
- ends_at: @page.ends_at,
9
- all_day: @page.all_day }) %>
10
- <% end %>
11
-
12
- <% if @page.template_config.value(:tags) %>
13
- <div class="field">
14
- <label>
15
- Tags
16
- </label>
17
- <%= tag_editor_for(f, @page) %>
18
- </div>
19
- <% end %>
@@ -1,4 +0,0 @@
1
- <%= react_component("PageFiles",
2
- locale: content_locale,
3
- locales: locales_with_dir,
4
- records: @page.files.map { |pf| Admin::PageFileResource.new(pf).to_hash }) %>
@@ -1,4 +0,0 @@
1
- <%= react_component("PageImages",
2
- locale: content_locale,
3
- locales: locales_with_dir,
4
- records: @page.page_images.map { |pi| Admin::PageImageResource.new(pi).to_hash }) %>
@@ -1,35 +0,0 @@
1
- <div class="field">
2
- <% if f.object.pathable? %>
3
- <%= labelled_field(f.text_field(:path_segment, dir: "ltr", lang: nil),
4
- "Path segment",
5
- description: "Only alpanumeric characters and dashes " \
6
- "are allowed.") %>
7
- <% else %>
8
- <div class="field">
9
- <label>Path segment</label>
10
- <p class="description">
11
- Unable to add a path segment,
12
- please add one to
13
- <%= link_to("this page's parent",
14
- edit_admin_page_path(f.object.parent,
15
- locale: f.object.locale,
16
- anchor: "metadata")) %>
17
- first.
18
- </p>
19
- </div>
20
- <% end %>
21
- </div>
22
-
23
- <div class="field">
24
- <%= f.label_for :meta_image, "Image" %>
25
- <p class="description">
26
- Image displayed when sharing on social media.
27
- Will fall back to the primary image if absent.
28
- Recommended size is at least 1200x630.
29
- </p>
30
- <%= f.image_uploader :meta_image %>
31
- </div>
32
-
33
- <% @page.template_config.metadata_blocks do |block_name, block_options| %>
34
- <%= page_block_field(f, block_name, block_options) %>
35
- <% end %>