pages_core 3.15.3 → 3.15.5

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 (213) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/app/assets/builds/pages_core/admin-dist.js +1 -1
  4. data/app/assets/builds/pages_core/admin-dist.js.map +4 -4
  5. data/app/assets/builds/pages_core/admin.css +378 -253
  6. data/app/assets/builds/pages_core/mailer.css +41 -6
  7. data/app/assets/builds/pages_core_fonts/121b837e.woff2 +0 -0
  8. data/app/assets/builds/pages_core_fonts/216e5c23.woff2 +0 -0
  9. data/app/assets/builds/pages_core_fonts/3017b52f.woff2 +0 -0
  10. data/app/assets/builds/pages_core_fonts/489746b9.woff2 +0 -0
  11. data/app/assets/builds/pages_core_fonts/49775483.woff2 +0 -0
  12. data/app/assets/builds/pages_core_fonts/49c9e472.woff2 +0 -0
  13. data/app/assets/builds/pages_core_fonts/4a119645.woff2 +0 -0
  14. data/app/assets/builds/pages_core_fonts/5d56d7a8.woff2 +0 -0
  15. data/app/assets/builds/pages_core_fonts/61ea75a6.woff2 +0 -0
  16. data/app/assets/builds/pages_core_fonts/62cbb778.woff2 +0 -0
  17. data/app/assets/builds/pages_core_fonts/647d26c.woff2 +0 -0
  18. data/app/assets/builds/pages_core_fonts/67764053.woff2 +0 -0
  19. data/app/assets/builds/pages_core_fonts/6bb0fd00.woff2 +0 -0
  20. data/app/assets/builds/pages_core_fonts/6c0194a2.woff2 +0 -0
  21. data/app/assets/builds/pages_core_fonts/71423409.woff2 +0 -0
  22. data/app/assets/builds/pages_core_fonts/7584e61d.woff2 +0 -0
  23. data/app/assets/builds/pages_core_fonts/77bcfa1c.woff2 +0 -0
  24. data/app/assets/builds/pages_core_fonts/7aca0cc5.woff2 +0 -0
  25. data/app/assets/builds/pages_core_fonts/9a09533f.woff2 +0 -0
  26. data/app/assets/builds/pages_core_fonts/a51f5bc8.woff2 +0 -0
  27. data/app/assets/builds/pages_core_fonts/a80b2975.woff2 +0 -0
  28. data/app/assets/builds/pages_core_fonts/a891f617.woff2 +0 -0
  29. data/app/assets/builds/pages_core_fonts/ad6083f3.woff2 +0 -0
  30. data/app/assets/builds/pages_core_fonts/b29a61ff.woff2 +0 -0
  31. data/app/assets/builds/{fonts/6569749d.ttf → pages_core_fonts/b30b0656.ttf} +0 -0
  32. data/app/assets/builds/pages_core_fonts/b3a5f48c.woff2 +0 -0
  33. data/app/assets/builds/pages_core_fonts/bc73ee06.woff2 +0 -0
  34. data/app/assets/builds/pages_core_fonts/c38c6d45.woff2 +0 -0
  35. data/app/assets/builds/pages_core_fonts/c5ce0b1f.woff2 +0 -0
  36. data/app/assets/builds/pages_core_fonts/c8d53904.woff2 +0 -0
  37. data/app/assets/builds/pages_core_fonts/ce13c169.woff2 +0 -0
  38. data/app/assets/builds/pages_core_fonts/d43bd0d5.woff2 +0 -0
  39. data/app/assets/builds/pages_core_fonts/e1c7d368.woff2 +0 -0
  40. data/app/assets/builds/pages_core_fonts/e1e8175d.woff2 +0 -0
  41. data/app/assets/builds/pages_core_fonts/e318f796.woff2 +0 -0
  42. data/app/assets/builds/{fonts/ee32bc60.ttf → pages_core_fonts/e7acb7d9.ttf} +0 -0
  43. data/app/assets/builds/pages_core_fonts/ee5514c6.woff2 +0 -0
  44. data/app/assets/builds/pages_core_fonts/f4e495e2.woff2 +0 -0
  45. data/app/assets/builds/pages_core_fonts/f736ec65.woff2 +0 -0
  46. data/app/assets/builds/pages_core_fonts/f741c7ba.woff2 +0 -0
  47. data/app/assets/builds/pages_core_fonts/f7767345.woff2 +0 -0
  48. data/app/assets/builds/pages_core_fonts/fe9eb751.woff2 +0 -0
  49. data/app/assets/stylesheets/pages_core/admin/components/forms.css +2 -2
  50. data/app/assets/stylesheets/pages_core/admin/components/header.css +1 -1
  51. data/app/assets/stylesheets/pages_core/admin/controllers/pages.css +1 -1
  52. data/app/assets/stylesheets/pages_core/admin/global/fonts.css +38 -38
  53. data/app/controllers/{pages_core → admin}/admin_controller.rb +1 -3
  54. data/app/controllers/attachments_controller.rb +40 -0
  55. data/app/controllers/concerns/pages_core/document_title_controller.rb +16 -0
  56. data/app/controllers/concerns/pages_core/page_parameters.rb +1 -1
  57. data/app/controllers/concerns/pages_core/pages/preview_controller.rb +49 -0
  58. data/app/controllers/concerns/pages_core/pages/rss_controller.rb +43 -0
  59. data/app/controllers/errors_controller.rb +2 -0
  60. data/app/controllers/images_controller.rb +13 -0
  61. data/app/controllers/pages_core/frontend/pages_controller.rb +3 -4
  62. data/app/controllers/pages_core/frontend_controller.rb +6 -1
  63. data/app/controllers/pages_core/sitemaps_controller.rb +21 -52
  64. data/app/helpers/pages_core/admin/image_uploads_helper.rb +1 -1
  65. data/app/helpers/pages_core/application_helper.rb +0 -3
  66. data/app/helpers/pages_core/attachments_helper.rb +0 -10
  67. data/app/helpers/pages_core/feed_tags_helper.rb +31 -0
  68. data/app/helpers/pages_core/frontend_helper.rb +3 -0
  69. data/app/helpers/pages_core/head_tags_helper.rb +80 -70
  70. data/app/helpers/pages_core/page_path_helper.rb +1 -12
  71. data/app/javascript/components/Attachments/Attachment.tsx +3 -3
  72. data/app/javascript/components/Attachments/AttachmentEditor.tsx +5 -5
  73. data/app/javascript/components/Attachments/Deleted.tsx +28 -0
  74. data/app/javascript/components/Attachments/List.tsx +11 -24
  75. data/app/javascript/components/Attachments/Placeholder.tsx +0 -2
  76. data/app/javascript/components/Attachments.tsx +2 -3
  77. data/app/javascript/components/DateRangeSelect.tsx +13 -10
  78. data/app/javascript/components/DateTimeSelect.tsx +11 -11
  79. data/app/javascript/components/EditableImage.tsx +3 -3
  80. data/app/javascript/components/FileUploadButton.tsx +3 -3
  81. data/app/javascript/components/ImageCropper/FocalPoint.tsx +10 -14
  82. data/app/javascript/components/ImageCropper/Image.tsx +19 -25
  83. data/app/javascript/components/ImageCropper/Toolbar.tsx +27 -26
  84. data/app/javascript/components/ImageCropper/useContainerSize.ts +25 -0
  85. data/app/javascript/components/ImageCropper/useCrop.ts +28 -13
  86. data/app/javascript/components/ImageCropper/useImageCropperContext.ts +13 -0
  87. data/app/javascript/components/ImageCropper.tsx +24 -83
  88. data/app/javascript/components/ImageEditor/Form.tsx +25 -28
  89. data/app/javascript/components/ImageEditor/useImageEditor.ts +63 -0
  90. data/app/javascript/components/ImageEditor/useImageEditorContext.ts +14 -0
  91. data/app/javascript/components/ImageEditor.tsx +28 -42
  92. data/app/javascript/components/ImageGrid/Deleted.tsx +28 -0
  93. data/app/javascript/components/ImageGrid/DragElement.tsx +5 -5
  94. data/app/javascript/components/ImageGrid/FilePlaceholder.tsx +0 -2
  95. data/app/javascript/components/ImageGrid/Grid.tsx +15 -24
  96. data/app/javascript/components/ImageGrid/GridImage.tsx +4 -4
  97. data/app/javascript/components/ImageGrid/Placeholder.tsx +2 -4
  98. data/app/javascript/components/ImageGrid.tsx +2 -4
  99. data/app/javascript/components/ImageUploader.tsx +5 -5
  100. data/app/javascript/components/LabelledField.tsx +6 -6
  101. data/app/javascript/components/Modal.tsx +16 -13
  102. data/app/javascript/components/PageForm/Block.tsx +3 -3
  103. data/app/javascript/components/PageForm/Content.tsx +11 -15
  104. data/app/javascript/components/PageForm/Dates.tsx +3 -11
  105. data/app/javascript/components/PageForm/Files.tsx +2 -4
  106. data/app/javascript/components/PageForm/Form.tsx +3 -9
  107. data/app/javascript/components/PageForm/Images.tsx +2 -4
  108. data/app/javascript/components/PageForm/LocaleLinks.tsx +4 -11
  109. data/app/javascript/components/PageForm/Metadata.tsx +8 -13
  110. data/app/javascript/components/PageForm/Options.tsx +28 -11
  111. data/app/javascript/components/PageForm/PageDescription.tsx +7 -14
  112. data/app/javascript/components/PageForm/PathSegment.tsx +5 -10
  113. data/app/javascript/components/PageForm/TabPanel.tsx +3 -6
  114. data/app/javascript/components/PageForm/Tabs.tsx +2 -4
  115. data/app/javascript/components/PageForm/UnconfiguredContent.tsx +7 -12
  116. data/app/javascript/components/PageForm/pageParams.ts +3 -2
  117. data/app/javascript/components/PageForm/usePage.ts +1 -46
  118. data/app/javascript/components/PageForm/usePageFormContext.ts +8 -0
  119. data/app/javascript/components/PageForm/useTabs.ts +1 -1
  120. data/app/javascript/components/PageForm/utils.ts +49 -0
  121. data/app/javascript/components/PageForm.tsx +52 -48
  122. data/app/javascript/components/PageImages.tsx +1 -3
  123. data/app/javascript/components/PageTree/Button.tsx +25 -0
  124. data/app/javascript/components/PageTree/CollapseArrow.tsx +34 -0
  125. data/app/javascript/components/PageTree/CollapsedLabel.tsx +21 -0
  126. data/app/javascript/components/PageTree/EditPageName.tsx +68 -0
  127. data/app/javascript/components/PageTree/Node.tsx +143 -413
  128. data/app/javascript/components/PageTree/PageName.tsx +6 -4
  129. data/app/javascript/components/PageTree/StatusLabel.tsx +10 -0
  130. data/app/javascript/components/PageTree/tree.ts +268 -0
  131. data/app/javascript/components/PageTree/usePageTree.ts +268 -0
  132. data/app/javascript/components/PageTree/usePageTreeContext.ts +13 -0
  133. data/app/javascript/components/PageTree.tsx +194 -214
  134. data/app/javascript/components/{RichTextToolbarButton.tsx → RichTextArea/ToolbarButton.tsx} +3 -5
  135. data/app/javascript/components/RichTextArea/actions.ts +106 -0
  136. data/app/javascript/components/RichTextArea/useMaybeControlledValue.ts +14 -0
  137. data/app/javascript/components/RichTextArea.tsx +91 -209
  138. data/app/javascript/components/TagEditor/AddTagForm.tsx +2 -2
  139. data/app/javascript/components/TagEditor/Editor.tsx +3 -5
  140. data/app/javascript/components/TagEditor/Tag.tsx +3 -5
  141. data/app/javascript/components/TagEditor/useTags.ts +7 -4
  142. data/app/javascript/components/TagEditor.tsx +2 -4
  143. data/app/javascript/components/Toast.tsx +5 -5
  144. data/app/javascript/components/drag/draggedOrder.ts +6 -6
  145. data/app/javascript/components/drag/useDragCollection.ts +21 -25
  146. data/app/javascript/components/drag/useDragUploader.ts +20 -18
  147. data/app/javascript/components/drag/useDraggable.ts +3 -3
  148. data/app/javascript/features/RichText.tsx +0 -1
  149. data/app/javascript/features/contentTabs.ts +2 -2
  150. data/app/javascript/stores/useModalStore.ts +1 -1
  151. data/app/javascript/stores/useToastStore.ts +2 -2
  152. data/app/javascript/types/Attachments.ts +11 -11
  153. data/app/javascript/types/Crop.ts +16 -12
  154. data/app/javascript/types/Drag.ts +21 -23
  155. data/app/javascript/types/Images.ts +8 -8
  156. data/app/javascript/types/PageEditor.ts +11 -4
  157. data/app/javascript/types/Pages.ts +22 -27
  158. data/app/javascript/types/Tags.ts +5 -6
  159. data/app/javascript/types/Template.ts +4 -4
  160. data/app/javascript/types.ts +2 -2
  161. data/app/models/attachment.rb +5 -9
  162. data/app/models/autopublisher.rb +1 -1
  163. data/app/models/concerns/pages_core/page_model/redirectable.rb +1 -2
  164. data/app/models/concerns/pages_core/page_model/searchable.rb +1 -1
  165. data/app/models/concerns/pages_core/page_model/status.rb +2 -4
  166. data/app/models/concerns/pages_core/searchable_document.rb +2 -4
  167. data/app/models/image.rb +0 -15
  168. data/app/models/page_builder.rb +4 -6
  169. data/app/resources/admin/page_resource.rb +2 -2
  170. data/app/resources/export/page_resource.rb +1 -1
  171. data/app/services/pages_core/invite_service.rb +1 -2
  172. data/app/views/layouts/admin.html.erb +1 -0
  173. data/app/views/pages_core/sitemaps/index.xml.builder +10 -0
  174. data/config/routes.rb +4 -3
  175. data/db/migrate/20240917142300_add_skip_index_to_pages.rb +7 -0
  176. data/lib/pages_core/engine.rb +15 -17
  177. data/lib/pages_core/sitemap.rb +58 -0
  178. data/lib/pages_core/templates/configuration_proxy.rb +3 -3
  179. data/lib/pages_core.rb +7 -4
  180. data/lib/rails/generators/pages_core/frontend/frontend_generator.rb +2 -2
  181. data/lib/rails/generators/pages_core/frontend/templates/application.html.erb +13 -5
  182. data/lib/rails/generators/pages_core/frontend/templates/postcss.config.js +2 -6
  183. data/lib/rails/generators/pages_core/frontend/templates/stylesheets/components/base.css +3 -1
  184. data/lib/rails/generators/pages_core/frontend/templates/stylesheets/config.css +2 -3
  185. data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/animation.css +1 -1
  186. data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/colors.css +6 -5
  187. data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/fonts.css +1 -1
  188. data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/grid.css +9 -6
  189. data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/typography.css +42 -26
  190. data/lib/rails/generators/pages_core/install/templates/application_controller.rb +0 -6
  191. data/lib/rails/generators/pages_core/rspec/templates/rails_helper.rb +1 -1
  192. metadata +81 -49
  193. data/app/assets/builds/fonts/7b7db107.woff2 +0 -0
  194. data/app/assets/builds/fonts/921961e9.woff2 +0 -0
  195. data/app/controller_dummies/admin/admin_controller.rb +0 -6
  196. data/app/controller_dummies/application_controller.rb +0 -6
  197. data/app/controller_dummies/attachments_controller.rb +0 -4
  198. data/app/controller_dummies/frontend_controller.rb +0 -4
  199. data/app/controller_dummies/images_controller.rb +0 -4
  200. data/app/controller_dummies/page_files_controller.rb +0 -4
  201. data/app/controller_dummies/pages_controller.rb +0 -4
  202. data/app/controller_dummies/sitemaps_controller.rb +0 -4
  203. data/app/controllers/concerns/pages_core/preview_pages_controller.rb +0 -47
  204. data/app/controllers/concerns/pages_core/rss_controller.rb +0 -41
  205. data/app/controllers/pages_core/attachments_controller.rb +0 -42
  206. data/app/controllers/pages_core/frontend/page_files_controller.rb +0 -25
  207. data/app/controllers/pages_core/images_controller.rb +0 -15
  208. data/app/helpers/pages_core/meta_tags_helper.rb +0 -96
  209. data/app/helpers/pages_core/open_graph_tags_helper.rb +0 -49
  210. data/app/javascript/components/PageTree/Draggable.tsx +0 -338
  211. data/app/javascript/lib/Tree.ts +0 -305
  212. data/app/javascript/types/Trees.ts +0 -19
  213. data/app/views/sitemaps/show.xml.builder +0 -11
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from "react";
1
+ import { useEffect } from "react";
2
2
 
3
3
  import { putJson, postJson } from "../lib/request";
4
4
  import useToastStore from "../stores/useToastStore";
@@ -11,6 +11,7 @@ import useAttachments from "./Attachments/useAttachments";
11
11
  import useImageGrid from "./ImageGrid/useImageGrid";
12
12
  import useTags from "./TagEditor/useTags";
13
13
  import usePage from "./PageForm/usePage";
14
+ import { PageFormContext } from "./PageForm/usePageFormContext";
14
15
  import useTabs from "./PageForm/useTabs";
15
16
  import pageParams from "./PageForm/pageParams";
16
17
  import Content from "./PageForm/Content";
@@ -24,14 +25,14 @@ import TabPanel from "./PageForm/TabPanel";
24
25
  import Files from "./PageForm/Files";
25
26
  import Images from "./PageForm/Images";
26
27
 
27
- interface Props {
28
+ type Props = {
28
29
  locale: string;
29
30
  locales: { [index: string]: Locale };
30
31
  page: Pages.SerializedResource;
31
32
  templates: Template.Config[];
32
33
  authors: Pages.Author[];
33
34
  statuses: Pages.StatusLabels;
34
- }
35
+ };
35
36
 
36
37
  export default function PageForm(props: Props) {
37
38
  const [state, dispatch] = usePage({
@@ -72,7 +73,7 @@ export default function PageForm(props: Props) {
72
73
  if (history) {
73
74
  history.replaceState(null, "", pageUrl);
74
75
  }
75
- }, [page.id, locale, tab]);
76
+ }, [page.id, page.parent_page_id, locale, tab]);
76
77
 
77
78
  const handlePreview = (evt: React.MouseEvent) => {
78
79
  evt.preventDefault();
@@ -107,6 +108,13 @@ export default function PageForm(props: Props) {
107
108
  } else {
108
109
  filesState.update(response.page_files);
109
110
  imagesState.update(response.page_images);
111
+ tagsDispatch({
112
+ type: "update",
113
+ payload: {
114
+ tags: response.tags_and_suggestions,
115
+ enabled: response.enabled_tags
116
+ }
117
+ });
110
118
  noticeToast("Your changes were saved");
111
119
  }
112
120
  })
@@ -116,50 +124,46 @@ export default function PageForm(props: Props) {
116
124
  };
117
125
 
118
126
  return (
119
- <Form state={state}>
120
- <main>
121
- <PageDescription state={state} dispatch={dispatch}>
122
- <Tabs tabs={tabs} tab={tab} setTab={setTab} />
123
- </PageDescription>
124
- <div className="content">
125
- <TabPanel active={tab == "content"}>
126
- <Content
127
- state={state}
128
- dispatch={dispatch}
129
- tagsState={tagsState}
130
- tagsDispatch={tagsDispatch}
131
- />
132
- </TabPanel>
133
- <TabPanel active={tab == "unconfigured-content"}>
134
- <UnconfiguredContent state={state} dispatch={dispatch} />
135
- </TabPanel>
136
- <TabPanel active={tab == "images"}>
137
- <Images locale={locale} locales={locales} state={imagesState} />
138
- </TabPanel>
139
- <TabPanel active={tab == "files"}>
140
- <Files locale={locale} locales={locales} state={filesState} />
141
- </TabPanel>
142
- <TabPanel active={tab == "metadata"}>
143
- <Metadata state={state} dispatch={dispatch} />
144
- </TabPanel>
145
- <div className="buttons">
146
- <button type="button" onClick={handlePreview}>
147
- Preview
148
- </button>
149
- <button type="submit" onClick={handleSubmit}>
150
- Save
151
- </button>
127
+ <PageFormContext.Provider
128
+ value={{
129
+ state: state,
130
+ dispatch: dispatch
131
+ }}>
132
+ <Form>
133
+ <main>
134
+ <PageDescription>
135
+ <Tabs tabs={tabs} tab={tab} setTab={setTab} />
136
+ </PageDescription>
137
+ <div className="content">
138
+ <TabPanel active={tab == "content"}>
139
+ <Content tagsState={tagsState} tagsDispatch={tagsDispatch} />
140
+ </TabPanel>
141
+ <TabPanel active={tab == "unconfigured-content"}>
142
+ <UnconfiguredContent />
143
+ </TabPanel>
144
+ <TabPanel active={tab == "images"}>
145
+ <Images locale={locale} locales={locales} state={imagesState} />
146
+ </TabPanel>
147
+ <TabPanel active={tab == "files"}>
148
+ <Files locale={locale} locales={locales} state={filesState} />
149
+ </TabPanel>
150
+ <TabPanel active={tab == "metadata"}>
151
+ <Metadata />
152
+ </TabPanel>
153
+ <div className="buttons">
154
+ <button type="button" onClick={handlePreview}>
155
+ Preview
156
+ </button>
157
+ <button type="submit" onClick={handleSubmit}>
158
+ Save
159
+ </button>
160
+ </div>
152
161
  </div>
153
- </div>
154
- </main>
155
- <aside className="sidebar">
156
- <Options
157
- state={state}
158
- dispatch={dispatch}
159
- authors={props.authors}
160
- statuses={props.statuses}
161
- />
162
- </aside>
163
- </Form>
162
+ </main>
163
+ <aside className="sidebar">
164
+ <Options authors={props.authors} statuses={props.statuses} />
165
+ </aside>
166
+ </Form>
167
+ </PageFormContext.Provider>
164
168
  );
165
169
  }
@@ -1,11 +1,9 @@
1
- import React from "react";
2
-
3
1
  import * as Images from "../types/Images";
4
2
  import { Locale } from "../types";
5
3
 
6
4
  import ImageGrid from "./ImageGrid";
7
5
 
8
- interface Props {
6
+ type Props = {
9
7
  locale: string;
10
8
  locales: { [index: string]: Locale };
11
9
  records: Images.Record[];
@@ -0,0 +1,25 @@
1
+ type Props = {
2
+ label: string;
3
+ icon: string;
4
+ className: string;
5
+ onClick: (evt: React.MouseEvent) => void;
6
+ };
7
+
8
+ export default function Button({ label, icon, className, onClick }: Props) {
9
+ const iconClass = "fa-solid fa-" + icon + " icon";
10
+
11
+ const preventDrag = (evt: React.MouseEvent) => {
12
+ evt.stopPropagation();
13
+ };
14
+
15
+ return (
16
+ <button
17
+ type="button"
18
+ className={className}
19
+ onClick={onClick}
20
+ onMouseDown={preventDrag}>
21
+ <i className={iconClass} />
22
+ {label}
23
+ </button>
24
+ );
25
+ }
@@ -0,0 +1,34 @@
1
+ import * as Tree from "./tree";
2
+ import { visibleChildNodes } from "./usePageTree";
3
+ import usePageTreeContext from "./usePageTreeContext";
4
+
5
+ type Props = {
6
+ id: Tree.Id;
7
+ };
8
+
9
+ export default function CollapseArrow({ id }: Props) {
10
+ const { state, dispatch } = usePageTreeContext();
11
+ const node = state.nodes[id];
12
+ const classNames = ["collapse fa-solid fa-caret-right"];
13
+
14
+ classNames.push(node.collapsed ? "collapsed" : "open");
15
+
16
+ const handleClick = (evt: React.MouseEvent) => {
17
+ evt.stopPropagation();
18
+ dispatch({ type: "setCollapsed", id: id, payload: !node.collapsed });
19
+ };
20
+
21
+ const preventDrag = (evt: React.MouseEvent | React.TouchEvent) => {
22
+ evt.stopPropagation();
23
+ };
24
+
25
+ if (!("root" in node) && visibleChildNodes(state, id).length > 0) {
26
+ return (
27
+ <i
28
+ className={classNames.join(" ")}
29
+ onMouseDown={preventDrag}
30
+ onClick={handleClick}
31
+ />
32
+ );
33
+ }
34
+ }
@@ -0,0 +1,21 @@
1
+ import * as Tree from "./tree";
2
+ import { visibleChildNodes } from "./usePageTree";
3
+ import usePageTreeContext from "./usePageTreeContext";
4
+
5
+ type Props = {
6
+ id: Tree.Id;
7
+ };
8
+
9
+ export default function CollapsedLabel({ id }: Props) {
10
+ const { state } = usePageTreeContext();
11
+ const node = state.nodes[id];
12
+ const count = visibleChildNodes(state, id).length;
13
+
14
+ if (node.collapsed && count > 0) {
15
+ return (
16
+ <span className="collapsed-label">
17
+ ({count} {count == 1 ? "item" : "items"})
18
+ </span>
19
+ );
20
+ }
21
+ }
@@ -0,0 +1,68 @@
1
+ import { useState } from "react";
2
+
3
+ import * as Tree from "./tree";
4
+ import { updatePage } from "./usePageTree";
5
+ import usePageTreeContext from "./usePageTreeContext";
6
+ import Button from "./Button";
7
+
8
+ type Props = {
9
+ id: Tree.Id;
10
+ };
11
+
12
+ export default function EditPageName({ id }: Props) {
13
+ const { state, dispatch } = usePageTreeContext();
14
+ const { dir, locale } = state;
15
+ const node = state.nodes[id];
16
+ const page = node.record;
17
+ const [name, setName] = useState(page.blocks.name[locale]);
18
+
19
+ const handleCancel = () => {
20
+ if ("id" in page && page.id) {
21
+ dispatch({ type: "update", id: id, payload: { editing: false } });
22
+ } else {
23
+ dispatch({ type: "remove", id: id });
24
+ }
25
+ };
26
+
27
+ const handleChange = (evt: React.ChangeEvent<HTMLInputElement>) => {
28
+ setName(evt.target.value);
29
+ };
30
+
31
+ const handleSubmit = (evt: React.FormEvent) => {
32
+ evt.preventDefault();
33
+ updatePage(state, id, dispatch, {
34
+ blocks: {
35
+ ...page.blocks,
36
+ name: { ...page.blocks.name, [locale]: name }
37
+ },
38
+ editing: false
39
+ });
40
+ };
41
+
42
+ return (
43
+ <div className="page edit">
44
+ <i className="fa-regular fa-file icon"></i>
45
+ <form className="edit-name" onSubmit={handleSubmit}>
46
+ <input
47
+ className="tight"
48
+ type="text"
49
+ value={name}
50
+ dir={dir}
51
+ lang={locale}
52
+ autoFocus
53
+ onChange={handleChange}
54
+ />
55
+ <button className="save primary" type="submit">
56
+ <i className="fa-solid fa-cloud icon"></i>
57
+ Save
58
+ </button>
59
+ <Button
60
+ label="Cancel"
61
+ className="cancel"
62
+ icon="ban"
63
+ onClick={handleCancel}
64
+ />
65
+ </form>
66
+ </div>
67
+ );
68
+ }