pages_core 3.15.4 → 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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/app/assets/builds/pages_core/admin-dist.js +1 -1
- data/app/assets/builds/pages_core/admin-dist.js.map +4 -4
- data/app/assets/builds/pages_core/admin.css +378 -253
- data/app/assets/builds/pages_core/mailer.css +41 -6
- data/app/assets/builds/pages_core_fonts/121b837e.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/216e5c23.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/3017b52f.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/489746b9.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/49775483.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/49c9e472.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/4a119645.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/5d56d7a8.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/61ea75a6.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/62cbb778.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/647d26c.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/67764053.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/6bb0fd00.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/6c0194a2.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/71423409.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/7584e61d.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/77bcfa1c.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/7aca0cc5.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/9a09533f.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/a51f5bc8.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/a80b2975.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/a891f617.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/ad6083f3.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/b29a61ff.woff2 +0 -0
- data/app/assets/builds/{fonts/6569749d.ttf → pages_core_fonts/b30b0656.ttf} +0 -0
- data/app/assets/builds/pages_core_fonts/b3a5f48c.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/bc73ee06.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/c38c6d45.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/c5ce0b1f.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/c8d53904.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/ce13c169.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/d43bd0d5.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/e1c7d368.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/e1e8175d.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/e318f796.woff2 +0 -0
- data/app/assets/builds/{fonts/ee32bc60.ttf → pages_core_fonts/e7acb7d9.ttf} +0 -0
- data/app/assets/builds/pages_core_fonts/ee5514c6.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/f4e495e2.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/f736ec65.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/f741c7ba.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/f7767345.woff2 +0 -0
- data/app/assets/builds/pages_core_fonts/fe9eb751.woff2 +0 -0
- data/app/assets/stylesheets/pages_core/admin/components/forms.css +2 -2
- data/app/assets/stylesheets/pages_core/admin/components/header.css +1 -1
- data/app/assets/stylesheets/pages_core/admin/controllers/pages.css +1 -1
- data/app/assets/stylesheets/pages_core/admin/global/fonts.css +38 -38
- data/app/controllers/{pages_core → admin}/admin_controller.rb +1 -3
- data/app/controllers/attachments_controller.rb +40 -0
- data/app/controllers/concerns/pages_core/document_title_controller.rb +16 -0
- data/app/controllers/concerns/pages_core/page_parameters.rb +1 -1
- data/app/controllers/concerns/pages_core/pages/preview_controller.rb +49 -0
- data/app/controllers/concerns/pages_core/pages/rss_controller.rb +43 -0
- data/app/controllers/errors_controller.rb +2 -0
- data/app/controllers/images_controller.rb +13 -0
- data/app/controllers/pages_core/frontend/pages_controller.rb +3 -4
- data/app/controllers/pages_core/frontend_controller.rb +6 -1
- data/app/controllers/pages_core/sitemaps_controller.rb +21 -52
- data/app/helpers/pages_core/admin/image_uploads_helper.rb +1 -1
- data/app/helpers/pages_core/application_helper.rb +0 -3
- data/app/helpers/pages_core/attachments_helper.rb +0 -10
- data/app/helpers/pages_core/feed_tags_helper.rb +31 -0
- data/app/helpers/pages_core/frontend_helper.rb +3 -0
- data/app/helpers/pages_core/head_tags_helper.rb +80 -70
- data/app/helpers/pages_core/page_path_helper.rb +1 -12
- data/app/javascript/components/Attachments/Attachment.tsx +3 -3
- data/app/javascript/components/Attachments/AttachmentEditor.tsx +5 -5
- data/app/javascript/components/Attachments/Deleted.tsx +28 -0
- data/app/javascript/components/Attachments/List.tsx +11 -24
- data/app/javascript/components/Attachments/Placeholder.tsx +0 -2
- data/app/javascript/components/Attachments.tsx +2 -3
- data/app/javascript/components/DateRangeSelect.tsx +13 -10
- data/app/javascript/components/DateTimeSelect.tsx +11 -11
- data/app/javascript/components/EditableImage.tsx +3 -3
- data/app/javascript/components/FileUploadButton.tsx +3 -3
- data/app/javascript/components/ImageCropper/FocalPoint.tsx +10 -14
- data/app/javascript/components/ImageCropper/Image.tsx +19 -25
- data/app/javascript/components/ImageCropper/Toolbar.tsx +27 -26
- data/app/javascript/components/ImageCropper/useContainerSize.ts +25 -0
- data/app/javascript/components/ImageCropper/useCrop.ts +28 -13
- data/app/javascript/components/ImageCropper/useImageCropperContext.ts +13 -0
- data/app/javascript/components/ImageCropper.tsx +23 -82
- data/app/javascript/components/ImageEditor/Form.tsx +25 -28
- data/app/javascript/components/ImageEditor/useImageEditor.ts +63 -0
- data/app/javascript/components/ImageEditor/useImageEditorContext.ts +14 -0
- data/app/javascript/components/ImageEditor.tsx +28 -42
- data/app/javascript/components/ImageGrid/Deleted.tsx +28 -0
- data/app/javascript/components/ImageGrid/DragElement.tsx +5 -5
- data/app/javascript/components/ImageGrid/FilePlaceholder.tsx +0 -2
- data/app/javascript/components/ImageGrid/Grid.tsx +15 -24
- data/app/javascript/components/ImageGrid/GridImage.tsx +4 -4
- data/app/javascript/components/ImageGrid/Placeholder.tsx +2 -4
- data/app/javascript/components/ImageGrid.tsx +2 -4
- data/app/javascript/components/ImageUploader.tsx +5 -5
- data/app/javascript/components/LabelledField.tsx +6 -6
- data/app/javascript/components/Modal.tsx +16 -13
- data/app/javascript/components/PageForm/Block.tsx +3 -3
- data/app/javascript/components/PageForm/Content.tsx +11 -15
- data/app/javascript/components/PageForm/Dates.tsx +3 -11
- data/app/javascript/components/PageForm/Files.tsx +2 -4
- data/app/javascript/components/PageForm/Form.tsx +3 -9
- data/app/javascript/components/PageForm/Images.tsx +2 -4
- data/app/javascript/components/PageForm/LocaleLinks.tsx +4 -11
- data/app/javascript/components/PageForm/Metadata.tsx +8 -13
- data/app/javascript/components/PageForm/Options.tsx +28 -11
- data/app/javascript/components/PageForm/PageDescription.tsx +7 -14
- data/app/javascript/components/PageForm/PathSegment.tsx +5 -10
- data/app/javascript/components/PageForm/TabPanel.tsx +3 -6
- data/app/javascript/components/PageForm/Tabs.tsx +2 -4
- data/app/javascript/components/PageForm/UnconfiguredContent.tsx +7 -12
- data/app/javascript/components/PageForm/pageParams.ts +3 -2
- data/app/javascript/components/PageForm/usePage.ts +1 -46
- data/app/javascript/components/PageForm/usePageFormContext.ts +8 -0
- data/app/javascript/components/PageForm/useTabs.ts +1 -1
- data/app/javascript/components/PageForm/utils.ts +49 -0
- data/app/javascript/components/PageForm.tsx +45 -48
- data/app/javascript/components/PageImages.tsx +1 -3
- data/app/javascript/components/PageTree/Button.tsx +25 -0
- data/app/javascript/components/PageTree/CollapseArrow.tsx +34 -0
- data/app/javascript/components/PageTree/CollapsedLabel.tsx +21 -0
- data/app/javascript/components/PageTree/EditPageName.tsx +68 -0
- data/app/javascript/components/PageTree/Node.tsx +143 -413
- data/app/javascript/components/PageTree/PageName.tsx +6 -4
- data/app/javascript/components/PageTree/StatusLabel.tsx +10 -0
- data/app/javascript/components/PageTree/tree.ts +268 -0
- data/app/javascript/components/PageTree/usePageTree.ts +268 -0
- data/app/javascript/components/PageTree/usePageTreeContext.ts +13 -0
- data/app/javascript/components/PageTree.tsx +194 -214
- data/app/javascript/components/{RichTextToolbarButton.tsx → RichTextArea/ToolbarButton.tsx} +3 -5
- data/app/javascript/components/RichTextArea/actions.ts +106 -0
- data/app/javascript/components/RichTextArea/useMaybeControlledValue.ts +14 -0
- data/app/javascript/components/RichTextArea.tsx +91 -209
- data/app/javascript/components/TagEditor/AddTagForm.tsx +2 -2
- data/app/javascript/components/TagEditor/Editor.tsx +3 -5
- data/app/javascript/components/TagEditor/Tag.tsx +3 -5
- data/app/javascript/components/TagEditor/useTags.ts +3 -2
- data/app/javascript/components/TagEditor.tsx +2 -4
- data/app/javascript/components/Toast.tsx +5 -5
- data/app/javascript/components/drag/draggedOrder.ts +6 -6
- data/app/javascript/components/drag/useDragCollection.ts +21 -25
- data/app/javascript/components/drag/useDragUploader.ts +20 -18
- data/app/javascript/components/drag/useDraggable.ts +3 -3
- data/app/javascript/features/RichText.tsx +0 -1
- data/app/javascript/features/contentTabs.ts +2 -2
- data/app/javascript/stores/useModalStore.ts +1 -1
- data/app/javascript/stores/useToastStore.ts +2 -2
- data/app/javascript/types/Attachments.ts +11 -11
- data/app/javascript/types/Crop.ts +16 -12
- data/app/javascript/types/Drag.ts +21 -23
- data/app/javascript/types/Images.ts +8 -8
- data/app/javascript/types/PageEditor.ts +11 -4
- data/app/javascript/types/Pages.ts +22 -27
- data/app/javascript/types/Tags.ts +2 -2
- data/app/javascript/types/Template.ts +4 -4
- data/app/javascript/types.ts +2 -2
- data/app/models/attachment.rb +5 -9
- data/app/models/autopublisher.rb +1 -1
- data/app/models/concerns/pages_core/page_model/redirectable.rb +1 -2
- data/app/models/concerns/pages_core/page_model/searchable.rb +1 -1
- data/app/models/concerns/pages_core/page_model/status.rb +2 -4
- data/app/models/concerns/pages_core/searchable_document.rb +2 -4
- data/app/models/image.rb +0 -15
- data/app/models/page_builder.rb +4 -6
- data/app/resources/admin/page_resource.rb +2 -2
- data/app/resources/export/page_resource.rb +1 -1
- data/app/services/pages_core/invite_service.rb +1 -2
- data/app/views/layouts/admin.html.erb +1 -0
- data/app/views/pages_core/sitemaps/index.xml.builder +10 -0
- data/config/routes.rb +4 -3
- data/db/migrate/20240917142300_add_skip_index_to_pages.rb +7 -0
- data/lib/pages_core/engine.rb +15 -17
- data/lib/pages_core/sitemap.rb +58 -0
- data/lib/pages_core/templates/configuration_proxy.rb +3 -3
- data/lib/pages_core.rb +7 -4
- data/lib/rails/generators/pages_core/frontend/frontend_generator.rb +2 -2
- data/lib/rails/generators/pages_core/frontend/templates/application.html.erb +13 -5
- data/lib/rails/generators/pages_core/frontend/templates/postcss.config.js +2 -6
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/components/base.css +3 -1
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/config.css +2 -3
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/animation.css +1 -1
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/colors.css +6 -5
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/fonts.css +1 -1
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/grid.css +9 -6
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/typography.css +42 -26
- data/lib/rails/generators/pages_core/install/templates/application_controller.rb +0 -6
- data/lib/rails/generators/pages_core/rspec/templates/rails_helper.rb +1 -1
- metadata +81 -49
- data/app/assets/builds/fonts/7b7db107.woff2 +0 -0
- data/app/assets/builds/fonts/921961e9.woff2 +0 -0
- data/app/controller_dummies/admin/admin_controller.rb +0 -6
- data/app/controller_dummies/application_controller.rb +0 -6
- data/app/controller_dummies/attachments_controller.rb +0 -4
- data/app/controller_dummies/frontend_controller.rb +0 -4
- data/app/controller_dummies/images_controller.rb +0 -4
- data/app/controller_dummies/page_files_controller.rb +0 -4
- data/app/controller_dummies/pages_controller.rb +0 -4
- data/app/controller_dummies/sitemaps_controller.rb +0 -4
- data/app/controllers/concerns/pages_core/preview_pages_controller.rb +0 -47
- data/app/controllers/concerns/pages_core/rss_controller.rb +0 -41
- data/app/controllers/pages_core/attachments_controller.rb +0 -42
- data/app/controllers/pages_core/frontend/page_files_controller.rb +0 -25
- data/app/controllers/pages_core/images_controller.rb +0 -15
- data/app/helpers/pages_core/meta_tags_helper.rb +0 -96
- data/app/helpers/pages_core/open_graph_tags_helper.rb +0 -49
- data/app/javascript/components/PageTree/Draggable.tsx +0 -338
- data/app/javascript/lib/Tree.ts +0 -305
- data/app/javascript/types/Trees.ts +0 -19
- data/app/views/sitemaps/show.xml.builder +0 -11
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import * as PageEditor from "../../types/PageEditor";
|
|
4
|
-
|
|
5
1
|
import DateRangeSelect from "../DateRangeSelect";
|
|
2
|
+
import usePageFormContext from "./usePageFormContext";
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
state
|
|
9
|
-
dispatch: (action: PageEditor.Action) => void;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default function Dates(props: Props) {
|
|
13
|
-
const { state, dispatch } = props;
|
|
4
|
+
export default function Dates() {
|
|
5
|
+
const { state, dispatch } = usePageFormContext();
|
|
14
6
|
const { datesEnabled, page } = state;
|
|
15
7
|
|
|
16
8
|
const toggleAllDay = () => {
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
1
|
import * as Attachments from "../../types/Attachments";
|
|
4
2
|
import { Locale } from "../../types";
|
|
5
3
|
|
|
6
4
|
import List from "../Attachments/List";
|
|
7
5
|
|
|
8
|
-
|
|
6
|
+
type Props = {
|
|
9
7
|
locale: string;
|
|
10
8
|
locales: { [index: string]: Locale };
|
|
11
9
|
state: Attachments.State;
|
|
12
|
-
}
|
|
10
|
+
};
|
|
13
11
|
|
|
14
12
|
export default function Files(props: Props) {
|
|
15
13
|
const { locale, locales, state } = props;
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
1
|
import { csrfToken } from "../../lib/request";
|
|
4
2
|
import * as PageEditor from "../../types/PageEditor";
|
|
5
|
-
|
|
6
|
-
interface FormProps {
|
|
7
|
-
state: PageEditor.State;
|
|
8
|
-
children: React.ReactNode;
|
|
9
|
-
}
|
|
3
|
+
import usePageFormContext from "./usePageFormContext";
|
|
10
4
|
|
|
11
5
|
function pageUrl(state: PageEditor.State): string {
|
|
12
6
|
if (state.page.id) {
|
|
@@ -16,8 +10,8 @@ function pageUrl(state: PageEditor.State): string {
|
|
|
16
10
|
}
|
|
17
11
|
}
|
|
18
12
|
|
|
19
|
-
export default function Form(
|
|
20
|
-
const { state
|
|
13
|
+
export default function Form({ children }: React.PropsWithChildren) {
|
|
14
|
+
const { state } = usePageFormContext();
|
|
21
15
|
const { page } = state;
|
|
22
16
|
|
|
23
17
|
return (
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
1
|
import { GridState } from "../../types/Images";
|
|
4
2
|
import { Locale } from "../../types";
|
|
5
3
|
|
|
6
4
|
import Grid from "../ImageGrid/Grid";
|
|
7
5
|
|
|
8
|
-
|
|
6
|
+
type Props = {
|
|
9
7
|
locale: string;
|
|
10
8
|
locales: { [index: string]: Locale };
|
|
11
9
|
state: GridState;
|
|
12
|
-
}
|
|
10
|
+
};
|
|
13
11
|
|
|
14
12
|
export default function Images(props: Props) {
|
|
15
13
|
return (
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import usePageFormContext from "./usePageFormContext";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
state: PageEditor.State;
|
|
7
|
-
dispatch: (action: PageEditor.Action) => void;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default function LocaleLinks(props: Props) {
|
|
11
|
-
const { state, dispatch } = props;
|
|
3
|
+
export default function LocaleLinks() {
|
|
4
|
+
const { state, dispatch } = usePageFormContext();
|
|
12
5
|
const { locale, locales } = state;
|
|
13
6
|
|
|
14
7
|
const handleClick = (newLocale: string) => (evt: React.MouseEvent) => {
|
|
@@ -17,7 +10,7 @@ export default function LocaleLinks(props: Props) {
|
|
|
17
10
|
};
|
|
18
11
|
|
|
19
12
|
if (!locales) {
|
|
20
|
-
return
|
|
13
|
+
return;
|
|
21
14
|
}
|
|
22
15
|
|
|
23
16
|
return (
|
|
@@ -1,22 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Fragment } from "react";
|
|
2
2
|
|
|
3
|
-
import * as PageEditor from "../../types/PageEditor";
|
|
4
3
|
import * as Pages from "../../types/Pages";
|
|
5
4
|
import { MaybeLocalizedValue } from "../../types";
|
|
6
5
|
|
|
7
|
-
import { blockValue, errorsOn } from "./
|
|
6
|
+
import { blockValue, errorsOn } from "./utils";
|
|
7
|
+
import usePageFormContext from "./usePageFormContext";
|
|
8
8
|
import Block from "./Block";
|
|
9
9
|
import PathSegment from "./PathSegment";
|
|
10
10
|
import LabelledField from "../LabelledField";
|
|
11
11
|
import ImageUploader from "../ImageUploader";
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
state
|
|
15
|
-
dispatch: (action: PageEditor.Action) => void;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default function Metadata(props: Props) {
|
|
19
|
-
const { state, dispatch } = props;
|
|
13
|
+
export default function Metadata() {
|
|
14
|
+
const { state, dispatch } = usePageFormContext();
|
|
20
15
|
|
|
21
16
|
const { page, locale, locales, inputDir, templateConfig } = state;
|
|
22
17
|
|
|
@@ -29,8 +24,8 @@ export default function Metadata(props: Props) {
|
|
|
29
24
|
};
|
|
30
25
|
|
|
31
26
|
return (
|
|
32
|
-
<
|
|
33
|
-
<PathSegment
|
|
27
|
+
<Fragment>
|
|
28
|
+
<PathSegment />
|
|
34
29
|
<LabelledField
|
|
35
30
|
htmlFor="page_meta_image_id"
|
|
36
31
|
label="Image"
|
|
@@ -62,6 +57,6 @@ export default function Metadata(props: Props) {
|
|
|
62
57
|
value={blockValue(state, b)}
|
|
63
58
|
/>
|
|
64
59
|
))}
|
|
65
|
-
</
|
|
60
|
+
</Fragment>
|
|
66
61
|
);
|
|
67
62
|
}
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Fragment, useState, ChangeEvent } from "react";
|
|
2
2
|
|
|
3
|
-
import * as PageEditor from "../../types/PageEditor";
|
|
4
3
|
import * as Pages from "../../types/Pages";
|
|
5
4
|
import LabelledField from "../LabelledField";
|
|
6
5
|
import DateTimeSelect from "../DateTimeSelect";
|
|
7
|
-
import { errorsOn } from "./
|
|
6
|
+
import { errorsOn } from "./utils";
|
|
7
|
+
import usePageFormContext from "./usePageFormContext";
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
state: PageEditor.State;
|
|
11
|
-
dispatch: (action: PageEditor.Action) => void;
|
|
9
|
+
type Props = {
|
|
12
10
|
authors: Pages.Author[];
|
|
13
11
|
statuses: Pages.StatusLabels;
|
|
14
|
-
}
|
|
12
|
+
};
|
|
15
13
|
|
|
16
|
-
export default function Options(
|
|
17
|
-
const { state, dispatch
|
|
14
|
+
export default function Options({ authors, statuses }: Props) {
|
|
15
|
+
const { state, dispatch } = usePageFormContext();
|
|
18
16
|
|
|
19
17
|
const { page, locale, templates } = state;
|
|
20
18
|
|
|
@@ -44,6 +42,10 @@ export default function Options(props: OptionsProps) {
|
|
|
44
42
|
setShowAdvanced(!showAdvanced);
|
|
45
43
|
};
|
|
46
44
|
|
|
45
|
+
const toggleSkipIndex = (evt: React.ChangeEvent<HTMLInputElement>) => {
|
|
46
|
+
dispatch({ type: "update", payload: { skip_index: evt.target.checked } });
|
|
47
|
+
};
|
|
48
|
+
|
|
47
49
|
return (
|
|
48
50
|
<div className="page-options">
|
|
49
51
|
<LabelledField
|
|
@@ -123,7 +125,7 @@ export default function Options(props: OptionsProps) {
|
|
|
123
125
|
</a>
|
|
124
126
|
</p>
|
|
125
127
|
{showAdvanced && (
|
|
126
|
-
<
|
|
128
|
+
<Fragment>
|
|
127
129
|
<LabelledField label="Subpages">
|
|
128
130
|
<label className="check-box">
|
|
129
131
|
<input
|
|
@@ -144,6 +146,21 @@ export default function Options(props: OptionsProps) {
|
|
|
144
146
|
Show in news
|
|
145
147
|
</label>
|
|
146
148
|
</LabelledField>
|
|
149
|
+
<LabelledField
|
|
150
|
+
htmlFor="page_skip_index"
|
|
151
|
+
label="Search"
|
|
152
|
+
errors={errorsOn(page, "skip_index")}>
|
|
153
|
+
<label className="check-box">
|
|
154
|
+
<input
|
|
155
|
+
id="page_skip_index"
|
|
156
|
+
name="page[skip_index]"
|
|
157
|
+
type="checkbox"
|
|
158
|
+
checked={page.skip_index}
|
|
159
|
+
onChange={toggleSkipIndex}
|
|
160
|
+
/>{" "}
|
|
161
|
+
Disable search indexing
|
|
162
|
+
</label>
|
|
163
|
+
</LabelledField>
|
|
147
164
|
<LabelledField
|
|
148
165
|
htmlFor="page_unique_name"
|
|
149
166
|
label="Unique name"
|
|
@@ -168,7 +185,7 @@ export default function Options(props: OptionsProps) {
|
|
|
168
185
|
onChange={handleChange("redirect_to")}
|
|
169
186
|
/>
|
|
170
187
|
</LabelledField>
|
|
171
|
-
</
|
|
188
|
+
</Fragment>
|
|
172
189
|
)}
|
|
173
190
|
{url && (
|
|
174
191
|
<LabelledField label="Page link">
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import * as PageEditor from "../../types/PageEditor";
|
|
1
|
+
import { Fragment } from "react";
|
|
4
2
|
import * as Pages from "../../types/Pages";
|
|
3
|
+
import usePageFormContext from "./usePageFormContext";
|
|
5
4
|
|
|
6
5
|
import LocaleLinks from "./LocaleLinks";
|
|
7
6
|
|
|
8
|
-
interface PageDescriptionProps {
|
|
9
|
-
state: PageEditor.State;
|
|
10
|
-
dispatch: (action: PageEditor.Action) => void;
|
|
11
|
-
children: React.ReactNode;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
7
|
function editLink(locale: string, page: Pages.Ancestor | Pages.Resource) {
|
|
15
8
|
return (
|
|
16
9
|
<a href={`/admin/${locale}/pages/${page.id}/edit`}>
|
|
@@ -26,19 +19,19 @@ function pageName(locale: string, page: Pages.Ancestor | Pages.Resource) {
|
|
|
26
19
|
return page.blocks.name[locale] || <i>Untitled</i>;
|
|
27
20
|
}
|
|
28
21
|
|
|
29
|
-
export default function PageDescription(
|
|
30
|
-
const { state
|
|
22
|
+
export default function PageDescription({ children }: React.PropsWithChildren) {
|
|
23
|
+
const { state } = usePageFormContext();
|
|
31
24
|
const { locale, page } = state;
|
|
32
25
|
|
|
33
26
|
return (
|
|
34
27
|
<div className="page-description with_content_tabs">
|
|
35
|
-
<LocaleLinks
|
|
28
|
+
<LocaleLinks />
|
|
36
29
|
<h3>
|
|
37
30
|
{page.ancestors.map((p) => (
|
|
38
|
-
<
|
|
31
|
+
<Fragment key={p.id}>
|
|
39
32
|
{editLink(locale, p)}
|
|
40
33
|
{" » "}
|
|
41
|
-
</
|
|
34
|
+
</Fragment>
|
|
42
35
|
))}
|
|
43
36
|
{page.id ? editLink(locale, page) : "New Page"}
|
|
44
37
|
</h3>
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ChangeEvent } from "react";
|
|
2
2
|
|
|
3
|
-
import * as PageEditor from "../../types/PageEditor";
|
|
4
3
|
import * as Pages from "../../types/Pages";
|
|
5
4
|
import { LocalizedValue } from "../../types";
|
|
6
5
|
|
|
7
|
-
import { errorsOn } from "./
|
|
6
|
+
import { errorsOn } from "./utils";
|
|
7
|
+
import usePageFormContext from "./usePageFormContext";
|
|
8
8
|
import LabelledField from "../LabelledField";
|
|
9
9
|
|
|
10
|
-
interface Props {
|
|
11
|
-
state: PageEditor.State;
|
|
12
|
-
dispatch: (action: PageEditor.Action) => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
10
|
function missingPathSegment(ancestors: Pages.Ancestor[], locale: string) {
|
|
16
11
|
for (let i = 0; i < ancestors.length; i++) {
|
|
17
12
|
if (!ancestors[i].path_segment[locale]) {
|
|
@@ -21,8 +16,8 @@ function missingPathSegment(ancestors: Pages.Ancestor[], locale: string) {
|
|
|
21
16
|
return null;
|
|
22
17
|
}
|
|
23
18
|
|
|
24
|
-
export default function PathSegment(
|
|
25
|
-
const { state, dispatch } =
|
|
19
|
+
export default function PathSegment() {
|
|
20
|
+
const { state, dispatch } = usePageFormContext();
|
|
26
21
|
const { page, locale } = state;
|
|
27
22
|
|
|
28
23
|
const value = (page.path_segment as LocalizedValue)[locale];
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
interface TabPanelProps {
|
|
1
|
+
type Props = {
|
|
4
2
|
active: boolean;
|
|
5
|
-
|
|
6
|
-
}
|
|
3
|
+
};
|
|
7
4
|
|
|
8
|
-
export default function TabPanel(props:
|
|
5
|
+
export default function TabPanel(props: React.PropsWithChildren<Props>) {
|
|
9
6
|
const { active, children } = props;
|
|
10
7
|
|
|
11
8
|
const classNames = ["content-tab"];
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
1
|
import * as PageEditor from "../../types/PageEditor";
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
type Props = {
|
|
6
4
|
tab: string;
|
|
7
5
|
tabs: PageEditor.Tab[];
|
|
8
6
|
setTab: (tab: string) => void;
|
|
9
|
-
}
|
|
7
|
+
};
|
|
10
8
|
|
|
11
9
|
export default function Tabs(props: Props) {
|
|
12
10
|
const { tab, tabs, setTab } = props;
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Fragment } from "react";
|
|
2
2
|
|
|
3
|
-
import * as PageEditor from "../../types/PageEditor";
|
|
4
3
|
import { MaybeLocalizedValue } from "../../types";
|
|
5
|
-
import { blockValue, errorsOn, unconfiguredBlocks } from "./
|
|
4
|
+
import { blockValue, errorsOn, unconfiguredBlocks } from "./utils";
|
|
5
|
+
import usePageFormContext from "./usePageFormContext";
|
|
6
6
|
|
|
7
7
|
import Block from "./Block";
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
state
|
|
11
|
-
dispatch: (action: PageEditor.Action) => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default function UnconfiguredContent(props: Props) {
|
|
15
|
-
const { state, dispatch } = props;
|
|
9
|
+
export default function UnconfiguredContent() {
|
|
10
|
+
const { state, dispatch } = usePageFormContext();
|
|
16
11
|
|
|
17
12
|
const { page, locale, inputDir } = state;
|
|
18
13
|
|
|
@@ -21,7 +16,7 @@ export default function UnconfiguredContent(props: Props) {
|
|
|
21
16
|
};
|
|
22
17
|
|
|
23
18
|
return (
|
|
24
|
-
<
|
|
19
|
+
<Fragment>
|
|
25
20
|
<p>
|
|
26
21
|
This page has additional content fields not enabled by the selected
|
|
27
22
|
template.
|
|
@@ -37,6 +32,6 @@ export default function UnconfiguredContent(props: Props) {
|
|
|
37
32
|
value={blockValue(state, b)}
|
|
38
33
|
/>
|
|
39
34
|
))}
|
|
40
|
-
</
|
|
35
|
+
</Fragment>
|
|
41
36
|
);
|
|
42
37
|
}
|
|
@@ -4,11 +4,11 @@ import * as PageEditor from "../../types/PageEditor";
|
|
|
4
4
|
import * as Images from "../../types/Images";
|
|
5
5
|
import * as Tags from "../../types/Tags";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
type Options = {
|
|
8
8
|
files: Attachments.State;
|
|
9
9
|
images: Images.GridState;
|
|
10
10
|
tags: Tags.State;
|
|
11
|
-
}
|
|
11
|
+
};
|
|
12
12
|
|
|
13
13
|
function dates(state: PageEditor.State) {
|
|
14
14
|
if (state.datesEnabled) {
|
|
@@ -89,6 +89,7 @@ export default function pageParams(state: PageEditor.State, options: Options) {
|
|
|
89
89
|
path_segment: page.path_segment,
|
|
90
90
|
meta_image_id: page.meta_image.image && page.meta_image.image.id,
|
|
91
91
|
parent_page_id: page.parent_page_id,
|
|
92
|
+
skip_index: page.skip_index,
|
|
92
93
|
page_files_attributes: pageFiles(files),
|
|
93
94
|
page_images_attributes: pageImages(images)
|
|
94
95
|
};
|
|
@@ -5,51 +5,6 @@ import * as Pages from "../../types/Pages";
|
|
|
5
5
|
import * as Template from "../../types/Template";
|
|
6
6
|
import { LocalizedValue, MaybeLocalizedValue } from "../../types";
|
|
7
7
|
|
|
8
|
-
export function blockValue(
|
|
9
|
-
state: PageEditor.State,
|
|
10
|
-
block: Template.Block
|
|
11
|
-
): string {
|
|
12
|
-
if (block.localized) {
|
|
13
|
-
const value: LocalizedValue =
|
|
14
|
-
(state.page.blocks[block.name] as LocalizedValue) || {};
|
|
15
|
-
|
|
16
|
-
return value[state.locale] || "";
|
|
17
|
-
} else {
|
|
18
|
-
return (state.page.blocks[block.name] as string) || "";
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function errorsOn(page: Pages.Resource, attribute: string): string[] {
|
|
23
|
-
return page.errors
|
|
24
|
-
.filter((e) => e.attribute === attribute)
|
|
25
|
-
.map((e) => e.message);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function unconfiguredBlocks(state: PageEditor.State): Template.Block[] {
|
|
29
|
-
const allBlocks: Record<string, Template.Block> = state.templates
|
|
30
|
-
.flatMap((t) => t.blocks)
|
|
31
|
-
.reduce((bs, b) => ({ [b.name]: b, ...bs }), {});
|
|
32
|
-
|
|
33
|
-
const anyValue = (v: MaybeLocalizedValue) => {
|
|
34
|
-
if (typeof v === "string") {
|
|
35
|
-
return v ? true : false;
|
|
36
|
-
} else {
|
|
37
|
-
return Object.values(v).filter((v) => v).length > 0;
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const hasValue = Object.keys(allBlocks).filter((k) => {
|
|
42
|
-
const value = state.page.blocks[k] || "";
|
|
43
|
-
return anyValue(value);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const enabled = state.templateConfig.blocks.map((b) => b.name);
|
|
47
|
-
|
|
48
|
-
return hasValue
|
|
49
|
-
.filter((b) => enabled.indexOf(b) === -1)
|
|
50
|
-
.map((n) => allBlocks[n]);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
8
|
function parseDate(str: string): Date | null {
|
|
54
9
|
if (!str) {
|
|
55
10
|
return null;
|
|
@@ -163,7 +118,7 @@ function updatePage(
|
|
|
163
118
|
|
|
164
119
|
export default function usePage(
|
|
165
120
|
initialState: PageEditor.State<Pages.SerializedResource>
|
|
166
|
-
):
|
|
121
|
+
): PageEditor.Return {
|
|
167
122
|
const [state, dispatch] = useReducer(reducer, prepare(initialState));
|
|
168
123
|
return [derivedState(state), dispatch];
|
|
169
124
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import * as PageEditor from "../../types/PageEditor";
|
|
3
|
+
|
|
4
|
+
export const PageFormContext = createContext<PageEditor.Context>(null);
|
|
5
|
+
|
|
6
|
+
export default function usePageFormContext() {
|
|
7
|
+
return useContext(PageFormContext);
|
|
8
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
|
|
3
3
|
import * as PageEditor from "../../types/PageEditor";
|
|
4
|
-
import { unconfiguredBlocks } from "./
|
|
4
|
+
import { unconfiguredBlocks } from "./utils";
|
|
5
5
|
|
|
6
6
|
function tabsList(state: PageEditor.State): PageEditor.Tab[] {
|
|
7
7
|
const { templates, templateConfig } = state;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as PageEditor from "../../types/PageEditor";
|
|
2
|
+
import * as Pages from "../../types/Pages";
|
|
3
|
+
import * as Template from "../../types/Template";
|
|
4
|
+
import { LocalizedValue, MaybeLocalizedValue } from "../../types";
|
|
5
|
+
|
|
6
|
+
export function blockValue(
|
|
7
|
+
state: PageEditor.State,
|
|
8
|
+
block: Template.Block
|
|
9
|
+
): string {
|
|
10
|
+
if (block.localized) {
|
|
11
|
+
const value: LocalizedValue =
|
|
12
|
+
(state.page.blocks[block.name] as LocalizedValue) || {};
|
|
13
|
+
|
|
14
|
+
return value[state.locale] || "";
|
|
15
|
+
} else {
|
|
16
|
+
return (state.page.blocks[block.name] as string) || "";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function errorsOn(page: Pages.Resource, attribute: string): string[] {
|
|
21
|
+
return page.errors
|
|
22
|
+
.filter((e) => e.attribute === attribute)
|
|
23
|
+
.map((e) => e.message);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function unconfiguredBlocks(state: PageEditor.State): Template.Block[] {
|
|
27
|
+
const allBlocks: Record<string, Template.Block> = state.templates
|
|
28
|
+
.flatMap((t) => t.blocks)
|
|
29
|
+
.reduce((bs, b) => ({ [b.name]: b, ...bs }), {});
|
|
30
|
+
|
|
31
|
+
const anyValue = (v: MaybeLocalizedValue) => {
|
|
32
|
+
if (typeof v === "string") {
|
|
33
|
+
return v ? true : false;
|
|
34
|
+
} else {
|
|
35
|
+
return Object.values(v).filter((v) => v).length > 0;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const hasValue = Object.keys(allBlocks).filter((k) => {
|
|
40
|
+
const value = state.page.blocks[k] || "";
|
|
41
|
+
return anyValue(value);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const enabled = state.templateConfig.blocks.map((b) => b.name);
|
|
45
|
+
|
|
46
|
+
return hasValue
|
|
47
|
+
.filter((b) => enabled.indexOf(b) === -1)
|
|
48
|
+
.map((n) => allBlocks[n]);
|
|
49
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
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
|
-
|
|
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();
|
|
@@ -123,50 +124,46 @@ export default function PageForm(props: Props) {
|
|
|
123
124
|
};
|
|
124
125
|
|
|
125
126
|
return (
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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>
|
|
159
161
|
</div>
|
|
160
|
-
</
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
authors={props.authors}
|
|
167
|
-
statuses={props.statuses}
|
|
168
|
-
/>
|
|
169
|
-
</aside>
|
|
170
|
-
</Form>
|
|
162
|
+
</main>
|
|
163
|
+
<aside className="sidebar">
|
|
164
|
+
<Options authors={props.authors} statuses={props.statuses} />
|
|
165
|
+
</aside>
|
|
166
|
+
</Form>
|
|
167
|
+
</PageFormContext.Provider>
|
|
171
168
|
);
|
|
172
169
|
}
|